VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)

VB爱好者乐园(VBGood)

 找回密码
 立即注册
搜索
楼主: liusai

[原创] VB API初级入门(新手必看。注意:不是广告)

  [复制链接]
 楼主| 发表于 2007-2-28 13:05:29 | 显示全部楼层
原帖由 scsgbl 于 2007-2-28 12:57 发表
在任务管理器的窗口里还是能关啊


不可能会在任务管理器窗口中显示的,你可以先把程序生成EXE以后再试,看看可不可以。一般在VBIDE环境下调试的时候显示的是VB的窗口,所以我估计你把VB的窗口误认为是你程序的窗口。
回复 支持 反对

使用道具 举报

发表于 2007-2-28 13:07:26 | 显示全部楼层
哦明白了原来是生成的工程隐藏了
回复 支持 反对

使用道具 举报

发表于 2007-2-28 16:53:10 | 显示全部楼层
我还有问题Z的举例获取的HWND都是对自己本身内部的句柄,能不能举个获取我已经打开的一个程序中的窗体上的TEXT的句柄,不知道我说的清楚不清楚,就是自己编写好一个程序获取另外一个已经在运行的窗体上的TEXT控件的句柄?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-3-1 13:32:34 | 显示全部楼层
楼上所说的我打算在下一课中有所讲到,请尽请关注。。。。

这些天都比较忙,所以可能下一课需要过几天才讲到,还请大家谅解。
回复 支持 反对

使用道具 举报

发表于 2007-3-1 14:33:47 | 显示全部楼层
菜鸟路过,
没有看懂。
支持楼主,
楼主保重。
回复 支持 反对

使用道具 举报

发表于 2007-3-1 20:01:02 | 显示全部楼层
第一次看,写的不错
回复 支持 反对

使用道具 举报

++++++ 该用户已被删除
发表于 2007-3-1 20:24:21 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-3-2 15:49:15 | 显示全部楼层
好了,离别几天,今天咱们接着聊。接上面的。

    首先咱们先看SetWindowText,咱们在上面讲过GetWindowText这个API,GetWindowText是用来获取窗口文本的,而这个正好相反。现在可以看看表面意思Set(设置)Window(窗口)Text(文本),好了这样理解就够了,我们已经知道这个API是设置窗口文本的,接着咱们就到API浏览器中找找这个API,如下:

  
    Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String) As Long

    接着咱们看里面所需要传递的参数,一共有两,第一个ByVal hwnd As Long我就不用说了,传入句柄呗,第二个ByVal lpString As String,其中声明的lpString是字符串变量,可想而知,这里需要传入字符串,好了,开始实践。新建一个标准EXE,然后添加一个TextBox控件,然后再添加一个CommandButton,写入以下代码:

  
    Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String) As Long

    Private Sub Command1_Click()
       SetWindowText Text1.hwnd, "这是咱们设置的文本"
    End Sub

  
    呵呵,这个看似比前面的更简单,不过我还是要罗嗦一下,首先把Text1的句柄传入第一个参数,这样API知道咱们需要操作哪个窗口,第二个是一个字符串变量,所以这里就是我们需要传入的文本。好了,F5运行,点击Command1,OK。
  

    再看SetWindowPos,可以说这个API可以看成设置窗口位置,但是最终的实现效果取决于咱们传递的参数,好了,在API浏览器中找到这个API,如下:

  
    Private Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

    呵!好家伙,这个API看起来有些复杂啊?不过别担心,有我在嘛,我会帮你好好分析的,这里还请大家别光我一个人分析,必须把自己融入进来,咱们一起分析这样不更有趣?好了,废话少说,先看第一个参数:
  

  ByVal hwnd As Long  这里我就不讲了,传入窗口句柄
  

    ByVal hWndInsertAfter As Long 好了,看看这个!hwndInstrAfter,可以看到里面包函有hwnd字符,这时你可能会说我前面不是已经说过嘛,只要看见包函有hwnd字符的都应该传入句柄嘛?呵呵,没错,你很聪明,记得我说的话呢!在这里夸一下你,别骄傲啊!现在咱们好好分析一下这个地方应该传入哪些参数!打开MSDN,不好意思是英文,这里我就把翻译过来的说明放上来,如下:

  
  hWndInsertAfter -  Long,窗口句柄。在窗口列表中,窗口hwnd会置于这个窗口句柄的后面。也可能选用下述值之一:

  
  HWND_BOTTOM     将窗口置于窗口列表底部

  
  HWND_TOP        将窗口置于Z序列的顶部;Z序列代表在分级结构中,窗口针对一个给定级别的窗口显示的顺序

  
  HWND_TOPMOST    将窗口置于列表顶部,并位于任何最顶部窗口的前面

  
  HWND_NOTOPMOST  将窗口置于列表顶部,并位于任何最顶部窗口的后面

  
    可以看到这个地方有四个参数供我们选择,一般我们会使用第三个API常数和第四个API常数,这几个API常数都可以在API浏览器中找到,至于具体实现什么功能我相信大家都知道吧,后面有写呢!

  
    再看看后面的几个 x,y,cx,cy 分别为Long变量,我上面讲过,SetWindowPos可以看成设置窗口位置嘛,所以这里理所当然是传入相关的坐标值,如果忽略则为0,自己可以试下。

  
    ByVal wFlags As Long,这个参数,我又说过,看看字符Flags,呵呵,熟悉吧,所以这里咱们需要传入相关的标识常数,利用咱们以前学过的常数分析法进行分析,Set(S)Window(W)Pos(P)=SWP_ ,可以看到相关的常数了吧?这里我把相关常数的说明发上来大家看下,如下:

  
  SWP_DRAWFRAME    围绕窗口画一个框
  
  SWP_HIDEWINDOW   隐藏窗口
  
  SWP_NOACTIVATE   不激活窗口
  
  SWP_NOMOVE       保持当前位置(x和y设定将被忽略)
  
  SWP_NOREDRAW     窗口不自动重画
  
  SWP_NOSIZE       保持当前大小(cx和cy会被忽略)
  
  SWP_NOZORDER     保持窗口在列表的当前位置(hWndInsertAfter将被忽略)
  
  SWP_SHOWWINDOW   显示窗口
  
  SWP_FRAMECHANGED 强迫一条WM_NCCALCSIZE消息进入窗口,即使窗口的大小没有改变

    所以我说过,一个这样的API他具体实现的功能取决于你所传递的参数。假设这里咱们需要实现一个窗口永远置前的功能,首先新建一个标准EXE,输入以下代码:

  
    Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
 Private Const HWND_TOPMOST = -1
 Private Const SWP_NOMOVE = &H2
 Private Const SWP_NOSIZE = &H1
 Private Sub Form_Load()
     SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE
 End Sub

    现在咱们开始分析,第一个参数传入句柄,第二个我上面讲过,实现什么功能传入什么参数,这里咱们是实现的窗口永久置前的功能,所以传入HWND_TOPMOST常数,现在看看其实坐标,如果你不想改变窗口的具体位置的话,这里可不设为0,再看看后面的wFlags,我传入了两个常数,这两个常数的相关说明请大家看看上面就知道,主要是不改变窗口位置和不改变窗口大小的前提下把窗口置前,其它常数如果大家有兴趣可以自己试试。

  
    最后一个,看看SetWindowRgn,这里我要解释一番,这个API所实现的功能呢就是改变窗口外观,也就是咱们所说的异形窗口等,通过这个API咱们可以把窗口改变成任何形状,在API浏览器找到这个API,如下:

  
    Private Declare Function SetWindowRgn Lib "user32" Alias "SetWindowRgn" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long

    好了,第一个参数,句柄。第二个参数,Long变量,这里需要传入什么咱们下面会讲到。第三个,Boolean变量,可以说明这里需要传入布尔值,Redraw为重画的意思,所以如果我们用这个API改变窗口形状,这里需要为True,表示重画窗口。

  
    现在新建一个标准EXE,然后把Form的ScaleMode设置成3-Pixel,我们知道Windows是以像素为单位的,所以使用这个API进行设置的时候是以像素为单位进行处理窗口外观。然后把BorderStyle设置为0-None,这样看得更明显。好了,写入以下代码:

  
  Private Declare Function SetWindowRgn Lib "user32" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long
  Private Declare Function CreateRoundRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long, ByVal X3 As Long, ByVal Y3 As Long) As Long
  Private Sub Form_Load()
      Dim hRgn As Long
   
      hRgn = CreateRoundRectRgn(0, 0, Me.ScaleWidth, Me.ScaleHeight, 10, 10)
      SetWindowRgn Me.hWnd, hRgn, True
  End Sub

    我不得不说一下这里我又用了一个API,主要是因为使用SetWindowRgn API是需要和其它API一起进行工作的,首先让我们先看看CreateRoundRectRgn这个API。分析如下:

  
    整体的意思是:创建圆角矩形。这里提示大家一个技巧,一般API中包函Rgn字符的都是代表可以改变对象外观的。可以看看我们使用的两个API,一个是SetWindowRgn(Rgn),一个是CreateRoundRectRgn(Rgn),希望你能明白其中的共同点。

  参数:x1,y1,x2,y2,x3,y3这些都是坐标值,具体说明见以下:
  
  X1,Y1 ----------  Long,矩形左上角的X,Y坐标
  X2,Y2 ----------  Long,矩形右下角的X,Y坐标
  X3 -------------  Long,圆角椭圆的宽。其范围从0(没有圆角)到矩形宽(全圆)
  Y3 -------------  Long,圆角椭圆的高。其范围从0(没有圆角)到矩形高(全圆)

    所以上面的代码具体是先通过CreateRoundRectRgn创建一个圆角矩形对象,然后通过SetWindowRgn来改变窗口的外观。
  
    小提示:使用CreateRoundRectRgn可以创建圆角矩形,也可以使用CreateEllipticRgn创建椭圆形,CreatePolyPolygonRgn创建多边形,CreateRectRgn矩形等,细心观察它们最后三个字符 Rgn 呵呵,明白了吧。

评分

参与人数 2威望 +4 人气 +1 收起 理由
jzy123456 + 1 + 1 精品文章
squall0815 + 3 精品文章

查看全部评分

回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-3-2 15:52:04 | 显示全部楼层
3,获取其它窗口的句柄
  
    这个我本来打算不讲的,不过网友们既然提出来了,我也只好详细说说。一般获取其它窗口的句柄使用以下API:

  
  FindWindow,FindWindowEx,WindowFromPoint
  

    这两个API就足矣,先看看第一个API的原型:

  
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

    里面一共有两个参数,先看第一个:ByVal lpClassName As String,字符串变量,所以这里需要传入字符串,第二个ByVal lpWindowName As String,同样一个字符串变量,这里也需要传入字符串。再看这个API为Function,有返回值的,那返回值就是我们需要的句柄了。好了,现在了解了两个参数的具体传递类型,那我们现在就要知道这两个参数中到底应该传入哪些值?如下:

  
  ByVal lpClassName As String,lpClassName:类名。指窗口类名,如果忽略则传入vbNullString。
  

  ByVal lpWindowName As String,lpWindowName:窗口名称。指窗口文本,如果忽略则传入vbNullString。

  
    现在明白了两个参数需要传入哪些值就好办了,一个窗口的类名咱们有可能不知道,但是一个窗口的名称就好办了。如:咱们打开记事本程序,可以看到窗口标题显示为“无标题-记事本”。好了这就是咱们需要的,现在咱们就要通过这个窗口标题来获取记事本的句柄。新建一个标准EXE,然后输入以下代码:

  
  Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
  Private Sub Form_Load()
      Dim WindowHandle As Long
   
      WindowHandle = FindWindow(vbNullString, "无标题 - 记事本")
        
      MsgBox WindowHandle
  End Sub
  

    好了,F5运行,显示MsgBox消息框,如果不为0,那么咱们就获取成功了,如果为0,那么表示获取失败,这个时候你有必要检查一下你所要获取的窗口文本是否符合你所要获取的那个窗口文本(呵,这句话还真长!)。具体代码意思我就不讲了,大家可以自己分析下。

  
    小提示:这个时候咱们已经得到句柄了,具体得到这个句柄干什么?那就看你了。给个例子,如下:

  
    SetWindowText WindowHandle, "哈哈"

  
    看看把这个代码放在上面代码中试下,呵呵!注意,SetWindowText你要先声明这个API。别忘了。

  


    再看第二个FindWindowEx,这个API是在窗口列表中寻找与指定条件相符的第一个子窗口,原型如下:

  
    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

    看里面的参数,第一个和第二个:ByVal hWnd1 As Long,ByVal hWnd2 As Long,这里都需要传入句柄,再看第三个和第四个:ByVal lpsz1 As String, ByVal lpsz2 As String,这里所要传入的是字符串。具体意思如下:

  hWnd1 ----------  Long,在其中查找子的父窗口。如设为零,表示使用桌面窗口(通常说的顶级窗口都被认为是桌面的子窗口,所以也会对它们进行查找)

  hWnd2 ----------  Long,从这个窗口后开始查找。这样便可利用对FindWindowEx的多次调用找到符合条件的所有子窗口。如设为零,表示从第一个子窗口开始搜索

  lpsz1 ----------  String,欲搜索的类名。零表示忽略,注意一般传入vbNullString

  lpsz2 ----------  String,欲搜索的类名。零表示忽略,注意一般传入vbNullString

    用实践帮我们分析,这里还是拿记事本开刀。打开一个记事本,新建一个标准EXE,接着新建一个CommandButton,Caption设置为:设置文本。OK,写入以下代码:

  
  Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
  Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
  Private Declare Function EnableWindow Lib "user32" (ByVal hwnd As Long, ByVal fEnable As Long) As Long

  Private Sub Command1_Click()
      Dim WindowHandle As Long, ChildWindowHandle As Long
   
      WindowHandle = FindWindow(vbNullString, "无标题 - 记事本")
        
      If WindowHandle Then '如果获取句柄成功
               
          ChildWindowHandle = FindWindowEx(WindowHandle, 0, "Edit", vbNullString)
        
          If ChildWindowHandle Then '如果成功获取子句柄
              EnableWindow ChildWindowHandle, False '禁用子窗口
          Else
              MsgBox "无法获取子窗口"
          End If
      End If
  End Sub
  

    好了,帮大家分析。看第一行:Dim WindowHandle As Long, ChildWindowHandle As Long,用于储存获取的句柄的。WindowHandle = FindWindow(vbNullString, "无标题 - 记事本")这个就不用讲了,上面已经讲过。

  
    ChildWindowHandle = FindWindowEx(WindowHandle, 0, "Edit", vbNullString),这一段是通过我们已经获取的记事本句柄获取其中的子窗口句柄。大家可以用Spy++查看到记事本的TextBox类,然后根据类名写入即可。

  
    EnableWindow ChildWindowHandle, False 这又是一个新的API,虽然前面我没有前过,但是这个API使用起来及其简单。这个API中有两个参数,第一个理所当然是传入窗口句柄,第二个为Long变量,其实这里应该设为Boolean变量好些,主要是用来处理当前窗口是否可用。True可用,False禁用。

  
    现在F5运行,记得打开记事本哦,然后点击Command1,看看能不能在记事本的文本框中输入字符串?是否被禁用了?

  
    小提示:EnableWindow之所有讲出来,是希望提高大家使用API的兴趣,有些被禁用的窗口你可以使用这个API把它激活,至于怎么使用就看你自己了,这里给大家布置一个作业,呵呵,自己去完成吧。



  
    最后一个API,WindowFromPoint,这个API主要是获取当前坐标的窗口句柄,不是有人想知道当前鼠标指针位置的窗口句柄吗?用这个是不错的选择,原型如下:
  

  Private Declare Function WindowFromPoint Lib "user32" Alias "WindowFromPoint" (ByVal xPoint As Long, ByVal yPoint As Long) As Long

    两个参数,一个是xPoint(x坐标值),一个是yPoint(y坐标值),现在你可以在这个两个参数分别传入其它窗口的坐标值就可以获取其它窗口的句柄了。可以看到为Function声明,返回值就是咱们需要的句柄。

  
    咱们想实现的功能是获取当前鼠标指针位置的句柄,所以这里当然需要用到GetCursorPos了,结合前面所讲的,新建一个标准EXE,添加一个Timer控件,Interval设置为100,Enabled=True,OK,写如以下代码:

  
  Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
  Private Type POINTAPI
          x As Long
          y As Long
  End Type
  Private Sub Timer1_Timer()
      Dim lpPoint As POINTAPI
      Dim WindowHandle As Long
   
      GetCursorPos lpPoint '获取当前鼠标指针坐标
      WindowHandle = WindowFromPoint(lpPoint.x, lpPoint.y)
   
      Me.Caption = "当前鼠标指针位置句柄:" & WindowHandle
  End Sub

  
    好了,最后一次给大家分析了,至于GetCursorPos的使用与说明前面已经讲过,这里不再分析。看看WindowHandle = WindowFromPoint(lpPoint.x, lpPoint.y)这句,它是通过GetCursorPos获取的鼠标坐标值获取当前鼠标坐标位置的句柄。最后一句我就不用说了,在程序窗口显示获取的句柄。


  
  
    好了,API入门已经告一段落,其实我还想写下去,不过似乎看的人多,响应的人少,很是打击我写下去的心情。不过还是希望大家能从上面学到一些知识。具体的API应用我就不多说,大家可以自己慢慢体会。如果你把以上我讲的全部都搞懂的话,那么证明你已经基本了解API的使用方法了,那下面就靠你自己了。至此,我希望我带了一个好头帮助你了解API。88:)

评分

参与人数 5威望 +33 人气 +1 收起 理由
jzy123456 + 1 + 1 精品文章
笑小龙 + 2 精品文章
happynight + 5 精品文章
踏雪冬思 + 5 精品文章
410023425 + 20 我很赞同

查看全部评分

回复 支持 反对

使用道具 举报

发表于 2007-3-2 15:55:16 | 显示全部楼层
上帝啊,我爱死你了。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

文字版|手机版|小黑屋|VBGood  

GMT+8, 2021-2-27 23:02

VB爱好者乐园(VBGood)
快速回复 返回顶部 返回列表