Windows API 函数中 SendMessage 与 PostMessage 用处很大,经常被程序员们使用。对老手们来说,了如知掌,但对新手来说,可能会遇到这样那样的问题。我作为一名老手中的新手和新手的中老手,来谈谈具体用法和常见的坑,不妥之处,请大神们指正。
这两个函数调用方法是一样的,不同之处在于 SendMessage发出消息后,会等待回应结果,而PostMessage发出消息后,不等待回应。下面就以SendMessge为例,讲讲具体调用方法。
SendMessage( hWnd, Msg, wParam, lParam)
第一个参数:hWnd 是窗口句柄
第二个参数:Msg 是消息名称
第三个参数:wParam 是对消息名称进行具体说明的附加(不同的消息有自己不同的附加说明参数)
第四个参数:lParam 还是对消息名称进行具体说明的附加(不同的消息有自己不同的附加说明参数)
有人感到迷惑,wParam与lParam有什么区别呢?网上很少有人解释,可能大神们都太忙了,没时间吧,我来解释一下:
wParam意思是Word类型的Param(字符型参数)
lParam意思是Long类型的Param(长整型参数)
这两个参数要根据第二个参数 Msg 而定。用Python来先举一个例子。
# _*_ coding:utf-8 _*_
import win32gui, win32con
hwnd = win32gui.FindWindow('Chrome_WidgetWin_1', 'CSDN - 专业开发者社区 - Google Chrome')
win32gui.SetForegroundWindow(hwnd) # 激活窗口至前端(这行语句不能少)
win32gui.SendMessage(hwnd, win32con.WM_KEYDOWN, win32con.VK_NEXT, 0)
win32gui.SendMessage(hwnd, win32con.WM_KEYUP, win32con.VK_NEXT, 1)
#这段代码是向Google Chrome浏览器窗口发送一个PgDn按键,运行后网页向下翻了一页
上面的代码具体解释一下:
第一个参数hwnd是浏览器窗口的句柄;
注意,这里有一个常见的坑:若向记事本等字处理窗口发送消息时,不要用整个父窗口的句柄,而要用编辑区的句柄,否则不会生效!
上例的代码中,如果使用 hwnd = win32gui.FindWindow('Notepad',None),是不会生效的。要改用以下语句:
hwnd = win32gui.FindWindowEx(win32gui.FindWindow('Notepad',None),None,'Edit',None)
注意,第二个要避免的坑:如果你发送的WM_MOVE(移动窗口)、WM_CLOSE(关闭窗口)之类的消息,则要使用父窗口的句柄。
第二参数是win32con.WM_KEYDOWN 与 win32con.WM_KEYDOWN 分别表示按下松开某个按键;
第三个参数win32con.VK_NEXT 表示PgDn键;
第四个参数 0 与 1 是自由微软定义的,WM_KEYDOWN就要使用 0 ,WM_KEYUP 就要用1。这个最容易把人搞迷糊,我怎么知道什么消息要对应什么参数呢?别急,在MSDN上能查的到https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-sendmessage。只不过是英文的,看得人不爽而已,用谷歌释翻译吧,需要用到哪个就研究哪个,也不可能全部都掌握的一清二楚。
推荐方法如下:
进入https://docs.microsoft.com/en-us/windows/win32/winmsg/about-messages-and-message-queues#system-defined-messages页面,滚动到system-defined-messages,在参数列表中查找自己需要的消息类别。
(这里是总体上的分类 ,具体用法要点进去查看。特别说明:并不是这里所有类型的消息都是适用于SendMessage和PostMessage函数,这些消息是供给很多函数调用的,不同函数适用不同的消息,具体能用哪些要看去函数说明)
第一步,进入如下页面:
第二步,点击一个自己认为可能满足你需要的消息类别,以Scroll Bar Notifications(滚动条类消息)为例:
第三步,进入到Scroll Bar Notifications页面,再点击具体的消息,我们以WM_VSCROLL(垂直滚动条):
第四步,这时进入具体的消息说明页面:
最后,给出这个垂直滚动条消息的Python调用例子:
#_*_coding:utf-8_*_
#以一个记事本窗口为例子
hwnd = win32gui.FindWindowEx(win32gui.FindWindow('Notepad',None),None,'Edit',None)
win32gui.SendMessage(hwnd, win32con.WM_VSCROLL, win32con.SB_PAGEDOWN,None)
#代码运行后,文本区会向下滚动一页