Windows消息机制模拟用户输入的方法介绍

电子说

1.3w人已加入

描述

Windows 消息机制API

xiaoxi guanli jizhi

Windows平台上的应用程序是事件驱动的 ,它们不会显式地调用底层函数以获得用户输入或其它信息,而是等待系统将这些信息提供给它们。同类定义的窗口向系统声明一个唯一的 窗口过程函数 (Window Procedures)。当有关某一窗口句柄的事件发生时(比如:鼠标单击这个窗口,或键盘向这个窗口输入一个字符),系统调用这个函数,把某个特定的消息作为参数。

要向特定的窗口过程发送消息,Windows提供了以下函数:

C++语言

由于lpPrevWndFunc为同一类窗口共有,发送的消息在被某一窗口处理前事实上可能已被多个窗口接收。本文不会用到这一函数,关于此函数的完整定义请参阅:

C++语言

这一函数在中定义,它向唯一的窗口句柄发送消息,并只在发送的消息被处理后返回。与之相似的是PostMessageW,它在发送消息后立即返回,即只将消息添加到目的窗口句柄的消息队列里,并不等待其处理。

HWND hwnd:接收消息的窗口句柄

(特别地(HWND)0xffff为广播)

UINT Msg:发送的消息类型

WPARAM wParam:发送的消息

LPARAM lParam:发送消息的附加参数

实现刷屏

mian dui dui xiang

获得Windows提供的API函数后,下面用C++实现。

首先将刷屏过程封装到一个类中

--------Bomb.h--------

C++语言

构造类时向构造函数提供刷屏消息的重复次数和刷屏消息 (UTF-16格式)

ShowMessage()用于调试,把当前类保存的消息输出到控制台上

StartBombing(int)用于开始刷屏,参数定义开始刷屏前的延时。用户可在这段延时内把键盘焦点设置到目标窗口上去,使目标窗口句柄或得消息后把消息内容加入到文本输入框中去。此函数有一个无延迟参数的重载。

消息内容存储在私有段中一个类型为WPARAM的数组中(该类型在上文中有介绍),附加消息是一个值为NULL的LPARAM类型——实现本例中的功能不需要向SendMessageW()提供附加消息。

--------Bomb.cpp--------

C++语言

C++语言

出于某些考量,我们在此不提供主要函数的定义。在StartBombing()中,程序按用户设定的刷屏消息重复次数循环times次,并按消息长度循环MessageLength,每次将消息字符串中的第j个字符以WH_CHAR模式向所有窗口广播。获得键盘输入焦点的窗口会将其加入到文本框中。

在发送完一条消息后,通过keybd_event函数模拟一次【回车键按下】事件,使目标窗口(比如:wechat)发送消息或换行。

--------Main.cpp--------

C++语言

这是应用程序入口点。注意它设置了wcout/wcin的本地化,使其将储存在WPARAM类型(其本质是unsigned int)中的UTF-16数据转化为中文字符输出/输入。

可见,按以上代码编译的应用程序已经可以完成质问马人王的任务。然而, 这速度也太慢了?? 这个速度比打字快不了多少,如果这样的话就没必要用刷屏软件了。哪里出了问题呢?

问题在于,如本文开头介绍:SendMessageW()强制在目标窗口过程将消息处理完毕后才返回,这使得整个过程变得相当缓慢。

解决方法是显而易见的:用PostMessageW()取代原函数。但是这样做会带来新的问题:Post函数只是简单地把消息加入到目标的消息队列去,之后立即返回。而原程序在Post/Send函数返回后会调用keybd_event()模拟一个键盘事件。然而,窗口过程处理消息的速度现在看来并不尽如人意,这往往会导致大量字符消息堆积在消息队列中,最终导致键盘事件和消息发送间不协调(比如:微信PC端输入框中堆积了很多信息而不发送,因为回车键按下事件没有按正常顺序处理)

所以,要兼顾消息的稳定性和发送速度,就要把keybd_event替换成另一个PostMessageW(),使【回车键按下】这一事件也像其它字符事件那样加入到消息队列中去,这样就能保证字符消息和回车间的先后顺序不变。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分