VBA调用API获取其它程序的窗口的句柄

2017-09-21 08:00:00
网络
转贴
295

一般可以使用Windows API函数 FindWindow


我们需要获取指定窗体上某个控件的句柄,思路如下

1. 如果我们事先知道该控件的类名或是标题, 可以使用 API 函数 FindWindow 来得到该控件的句柄。FindWindow 的声明如下(API Viewer可以查到声明代码):
   Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
  一般我们只会用到其中一个参数,那么另外一个参数写为空字符串 vbNullString 就可以了。

2. 另外一种情况就是对该控件的类名或标题一无所知,或难以得到。对于这种情况,我想了一种比较笨的办法,如果有好的方法请高手不吝赐教:先使用 Spy++ 查看该窗体的结构,找到该控件在所属窗体上的层次和位置,然后在自己的程序中顺着这根藤摸过去。由于在一般的应用程序中,特定的控件在窗体上的位置一般是 固定不变的,所以这个方法还是有效的。我在昨天写的程序中即应用了这种方法解决了如何获取特定控件句柄的问题。

 至于如何知晓 Spy++ 的树状结构中看到的某控件就是你所要的目标控件,可以同时使用 Spy++ 和我昨天的那个查看鼠标光标处的窗口/控件句柄的小程序做对比,看该控件的句柄是否相同。注意:Spy++ 显示的句柄值为十六进制,可以在 VB 的小程序中使用 Hex 函数将十进制转为十六进制。

那么具体如何得到窗体上目标控件的句柄呢?我们先用一个叫做 GetTopWindow 的 API 函数得到窗体上第一个子窗体(控件也是窗体)的句柄,再按照刚才从 Spy++ 中看到的位置,使用 GetNextWindow 做一个循环就可以了。当然了,如果该控件的父窗体又是该窗体的一个子窗体,这种方法也是可以的。这两个 API 的声明如下:

Public Declare Function GetTopWindow Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, ByVal wFlag As Long) As Long

最后补充一点:只有当 GetNextWindow 函数的第二个参数为 2 时,才能返回下一个窗体的句柄。



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 PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Const WM_KEYDOWN = &H100
Private Const WM_KEYUP = &H101
Dim x ‘用 FindWindow 和 FindWindowEx 找到控件窗口。 ’然后用 SendMessage或PostMessage 发送消息。 Private Sub Command1_Click()
    AppActivate x  '激活其它窗口
    Dim NotepadHwnd As Long, hwnd As Long
    NotepadHwnd = FindWindow("notepad", vbNullString) '查找notepad记事本窗口
    hwnd = FindWindowEx(NotepadHwnd, 0, "Edit", vbNullString)    '得到窗口类名为Edit的窗口句柄 
    a = PostMessage(hwnd, WM_KEYDOWN, &HBB, 0&)  '模拟键按下事件
''-- 将Text1中的文本粘贴到记事本
        'VB.Clipboard.SetText Text1.Text
        'SendMessage TemphWnd, WM_PASTE, 0, ByVal 0&
        '把记事本的内容设置为Text1中的文本
        SendMessage hwnd, WM_SETTEXT, 0, ByVal CStr(Text1.Text)
End Sub
分享