鼠标和键盘的操作也将转换为相应的系统信息,并在收到鼠标或键盘信息后进行处理。可以通过SendMessage()和PostMessage()在将消息发送到指定窗口的过程中,可以通过使用这两个函数发送鼠标和键盘的相关信息来模拟鼠标和键盘。SendMessage()和PostMessage()外,也可通过keybd_event()和mouse_event()模拟鼠标和键盘按钮的两个特殊函数。
01 基于发送消息的模拟
Windows该应用程序基于消息机制,鼠标和键盘的操作将被系统转换为相应的消息。首先,学习如何通过发送信息来模拟鼠标和键盘。
1. 鼠标、键盘按键常用的消息
无论是鼠标指针(或光标)的移动、单击,还是键盘的按钮,通常都在Windows应用程序将转换为相应的信息。在操作鼠标时,最常用的是移动鼠标和单击鼠标键。例如,当教新手使用计算机时,他会告诉他移动鼠标指针(或光标)“我的电脑”然后单击鼠标右键,在弹出的快捷菜单中单击鼠标左键“属性”对话框。移动鼠标光标时,系统中对应的信息是WM_MOUSEMOVE按鼠标左键时的消息是WM_LBUTTONDOWN,当鼠标左键释放时,相应的信息是WM_LBUTTONUP。鼠标在系统中有很多新闻。MSDN鼠标消息如图1所示。
图1 鼠标相关信息
同样,键盘的按下和起的消息也定义在系统中。按键盘的消息是WM_KEY DOWN,对应键盘抬起的消息是WM_KEYUP。除了这两个消息,还有一个常用的消息,那就是WM_CHAR新闻。键盘的消息比鼠标少得多,在MSDN键盘信息如图2所示。
图2 键盘相关信息
2. PostMessage()函数模拟键盘按钮
PostMessage()和SendMessage()这两个函数可以向指定的窗口发送信息。由于鼠标和键盘按钮的操作被系统转换为相应的信息,因此可以使用PostMessage()和SendMessage()通过按鼠标和键盘按钮发送的信息来模拟它们的操作。最好使用模拟键盘按钮信息PostMessage()而不是使用SendMessage()。很多情况下,SendMessage()不会成功。
现在通过编写一个简单的小工具,它PostMessage()函数模拟键盘发送(发送)F5按键信息模拟网页刷新)信息刷新网页。首先打开VC6.0,创建一个MFC对话框工程,界面按图3所示设置。
图3 模拟键盘刷新网页界面布局
布局在图3所示的界面上,然后是“开始”按钮设置控件变量。这个小程序在“IE浏览器标题”输入要刷新的页面标题“刷新频率”输入刷新时间间隔,单位为秒。
当您了解程序的功能并安排程序界面时,您可以开始编写程序代码。程序代码分为两部分,第一部分是程序处理“开始”按钮的事件,第二部分是要按照指定的时间间隔对指定的浏览器发送按F5刷新网页。
先写响应“开始”按钮事件代码,双击“开始”按钮编写响应事件。代码如下:
如果是代码,首先判断按钮的文本“开始”,则通过SetTimer()函数设置定时器;如果按钮的文本不是“开始”,则通过KillTimer()函数关闭定时器。
这里的SetTimer()和KillTimer()是MFC中CWnd两个成员函数不是API函数。很多MFC中的类成员函数和API函数的写法是一样的,但它们仍然不同。比较一下SetTimer()在MFC中的定义和API定义函数的差异。
MFC定义如下:
API函数的定义如下:
从定义中可以看出,MFC中SetTimer()函数的定义比API中SetTimer()函数的定义少了一个参数,即HWND的窗口句柄的参数。在MFC窗口相关成员函数不需要指定窗口句柄MFC内部已经维护了m_hWnd句柄变量(如果要查看或使用)MFC内部维护的m_hWnd成员变量可以直接使用或调用GetSafeHwnd()建议使用第二种方法获取成员函数)。
将定时器添加到按钮事件中,定时器将按规定的时间间隔进行处理。定时器部分的代码如下:
定时器的处理非常简单,通过FindWindow()函数得到需要刷新窗口的句柄,然后发送WM_KEYDOWN和WM_KEYUP消息来模拟键盘按键即可。其实在模拟的过程中,可以省去WM_KEYUP但是,为了模拟效果更接近真实性,建议在模拟时将消息成对发送。
将编写好的程序编译连接起来,运行起来看效果“IE浏览器标题”输入浏览器的标题,可以通过Spy 获得,然后在那里“刷新频率”输入1。然后单击“开始”按钮,观察浏览器每1秒刷新一次。“停止”按钮后,程序不再刷新浏览器的按钮模拟。
到此,通过PostMessage()函数发送按F5键盘按键模拟程序完成。PostMessage()函数的优点是目标窗口可以在后台,而不需要激活窗口。刷新的浏览器可以最小化,然后操作刷新网页的小程序,浏览器仍然在任务栏中刷新。
02 通过API函数模拟鼠标键盘按钮的操作
在开发程序时,总是很难发送信息,因为有很多类型的信息,不同信息的附件参数也因不同类型的信息而异。Windows几乎每一个常用的新闻都提供了相应的信息API函数。使用它,以免记住太多的信息API开发函数相对直观。
1. 鼠标键盘模拟函数
在使用Windows模拟鼠标或键盘按钮时,系统信息可能不直观、不方便。微软在设计时考虑到了这一点,所以在Windows大部分新闻可以直接使用相应的等价API函数,不需要直接发送消息。例如,它可以使用WM_GETTEXT获取文本内容的新闻,相应的函数GetWindowText()。想象一下,如果程序一目了然SendMessage()与PostMessage()等函数,不是很吓人吗?
以下是模拟鼠标和键盘输入的两个函数。keybd_event()和mouse_event()定义如下:
从函数的名称可以看出,这两个API函数对应键盘事件和鼠标事件。在程序中使用时,读取代码的人更直观。以下使用keybd_event()和mouse_event()用两个函数完成刷新网页的小工具。
2. 网页刷新工具
keybd_event()和 mouse_event()这两个 API 函数,从函数的参数来看,不需要将窗口句柄作为参数传递给它们。然后,在模拟鼠标和键盘时,这两个函数必须激活目标窗口并处于所有窗口的前端。因此,在程序中,首先要完成的是将目标窗口设置在前面并激活它们。让我们来看看程序的界面部分,如图4所示。
图4 模拟鼠标键盘
这个窗口比上一个程序的窗口简单。界面上有两个按钮,第一个按钮“模拟键盘”是通过keybd_event()模拟按压F5按钮刷新网页,第二个按钮“模拟鼠标”是通过mouse_event()模拟鼠标右键,弹出浏览器的快捷菜单,然后通过keybd_event()模拟按R点击刷新网页。
了解程序要实现的功能后,首先将目标窗口设置在前面并处于激活状态,代码如下:
这个自定义函数很简单,分别调用FindWindow()和SetForegroundWindow()两个API函数。SetForegroundWindow()函数的使用相对简单,将指定的窗口设置在前面并激活,只有一个参数,是目标窗口的窗口句柄(这里的窗口句柄变量m_hWnd就是由MFC也可以使用提供的变量GetSafeHwnd()获取函数。
“模拟键盘”按钮对应的代码如下:
在模拟键盘按钮之前,首先调用自定义函数FindAndFocus()将浏览器设置在前面并激活(“模拟鼠标”还需要先调用按钮FindAndFocus()自定义函数)。通过调用keybd_event()模拟函数F5网页刷新三次键。
“模拟鼠标”按钮对应的代码如下:
两个奇怪的代码用于代码中API函数,分别是ClientToScreen ()和SetCursorPos()。它们的定义如下:
ClientToScreen()函数的作用是将窗口区域的坐标转换为屏幕坐标。更直接的解释是在屏幕上获得指定窗口的坐标位置。
SetCursorPos()函数的作用是将鼠标光标移动到指定的坐标位置。
在程序中为什么不使用mouse_event()移动鼠标光标的位置,但使用它SetCursorPos()位置?API函数中,与SetCursorPos()对应的函数是GetCursorPos(),而SetCursorPos()函数常与GetCursorPos()函数一起使用。因为在很多情况下,在程序设置鼠标光标位置进行一系列操作后,仍然需要将鼠标光标位置设置回原来的位置,所以在调用中SetCursorPos()前,需要调用GetCursorPos()获得鼠标光标的当前位置,以便在操作完成后将鼠标光标设置为原始位置。也可以看出,很多API函数成对出现,有Set也有Get,记忆起来很方便。
调用程序SetCursorPos()函数时,参数中x坐标和y坐标分别增加了两个整形手术的常量,这可能更令人费解。这两个整形手术的常量是通过ClientToScreen()函数得到浏览器左上角x和y坐标,浏览器鼠标右键菜单必须在浏览器客户区域激活,因此需要在左上角坐标的基础上增加两个偏移,代码中的两个整形常量是一个偏移(只要鼠标能落在浏览器窗口)。
鼠标和键盘按钮的模拟将在许多地方使用,如一些病毒使用模拟鼠标单击杀毒软件的警告提示,如游戏辅助工具通过模拟鼠标快速单击……鼠标和键盘按钮的模拟并不简单。在常规情况下,鼠标和键盘按钮可以通过上述内容进行模拟。但在某些情况下,例如,一些游戏被过滤了PostMessage()函数发送的消息,一些游戏hook了keybd_event()和mouse_event()函数,一些游戏使用DX响应鼠标和键盘……