函数原型如下:
BOOL
WINAPI PostMessage(
HWND
hWnd,
UINT
Msg,
WPARAM
wParam,
LPARAM
lParam);
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam)
大家都知道通过 PostMessage/SendMessage可以模拟鼠标键盘发送虚拟按键:
hWnd为接收消息的控件句柄
Msg为键盘或鼠标的消息类型(按下、松开、双击、滚动等等)
wParam为键盘按键虚拟码(并非ASCII码)
IParam包括鼠标坐标及键盘按键信息
但不少人在实现过程中遇到问题,现就几个典型问题进行说明。
-
消息发送不成功
此问题大部分是因为没有找准接收控件句柄,一定要具体到最下层的控件,可通过使用FindWindowEx、EnumChildWindows、GetWindowText、GetClassName等API函数获取到想要的控件句柄,再向此句柄发送消息才有效。比如:记事本中的子控件的类名为“Edit”,.NET编译的TextBox控件类名一般包含“EDIT”等等,要找到此类控件句柄发送消息才能得到有效输入,其它热键输入类型控件也一样。VS中的Spy++是个好东西,可以捕捉任意控件查看属性或消息内容。
也有少部分是因为接收端程序屏蔽了PostMessage/SendMessage消息,发送过去根本就没反应。甚至通过API函数keybd_event、.NET内部方法System.Windows.Forms.SendKeys.Send等全局类按键都没有用,这种可尝试系统底层接口(驱动级)的有关方法,这方面我没什么资料,网上说有类似开源资源且打包成了DLL库可直接调用,但需要系统管理员权限。
-
发送1次按键结果出现2次按键的情况
发送一次WM_KEYDOWN及一次WM_KEYUP结果出现了2次按键,原因是最后一个参数lParam不规范导致,此参数0到15位为该键在键盘上的重复次数,经常设为1,即按键1次;16至23位为键盘的扫描码,通过API函数MapVirtualKey可以得到;24位为扩展键,即某些右ALT和CTRL;29一般为0;30位-[原状态]已按下为1否则0(KEYUP要设为1);31位-[状态切换](KEYDOWN设为0,KEYUP要设为1)。
资料显示第30位对于keydown在和shift等结合的时候通常要设置为1,未经验证。
-
中文输入问题
要实现中文输入必须用全局类方式实现,如:API函数keybd_event、.NET内部方法System.Windows.Forms.SendKeys.Send等,这要求先要激活窗口且切换到中文输入法状态才可以。原因是中文输入需要通过输入法程序,而PostMessage/SendMessage绕过了输入法直接到达控件。
-
程序卡死
一般是使用SendMessage导致,因为使用SendMessage需要一直等待接收端处理完,如果消息传递过程中出现问题将导致线程中断。建议使用PostMessage,发送出去即可不看结果,不用理会消息最后处理结果怎样。
如果懂C#.NET的朋友可参考本人写的源代码,里面代码示例,重点部分有详细的注解说明。