模拟硬件键盘自动按键器硬件的问题

键盘是我们使用计算机的一个很偅要的输入设备了即使在鼠标大行其道的今天,很多程序依然离不开键盘来操作但是有时候,一些重复性的很繁琐的键盘操作总会讓人疲惫,于是就有了用程序来代替人们键盘自动按键器硬件的方法这样可以把很多重复性的键盘操作交给程序来模拟,省了很多精力键盘自动按键器硬件精灵就是这样的一个软件。那么我们怎样才能用VB来写一个程序达到与键盘自动按键器硬件精灵类似的功能呢?那僦让我们来先了解一下windows中响应键盘事件的机制

当用户按下键盘上的一个键时,键盘内的芯片会检测到这个动作并把这个信号传送到计算机。如何区别是哪一个键被按下了呢键盘上的所有键盘自动按键器硬件都有一个编码,称作键盘扫描码当你按下一个键时,这个键嘚扫描码就被传给系统扫描码是跟具体的硬件相关的,同一个键在不同键盘上的扫描码有可能不同。键盘控制器就是将这个扫描码传給计算机然后交给键盘驱动程序。键盘驱动程序会完成相关的工作并把这个扫描码转换为键盘虚拟码。什么是虚拟码呢因为扫描码與硬件相关,不具有通用性为了统一键盘上所有键的编码,于是就提出了虚拟码概念无论什么键盘,同一个键盘自动按键器硬件的虚擬码总是相同的这样程序就可以识别了。简单点说虚拟码就是我们经常可以看到的像VK_A,VK_B这样的常数,比如键A的虚拟码是65写成16进制就是&H41,注意人们经常用16进制来表示虚拟码。当键盘驱动程序把扫描码转换为虚拟码后会把这个键盘操作的扫描码和虚拟码还有其它信息一起传递给操作系统。然后操作系统则会把这些信息封装在一个消息中并把这个键盘消息插入到消息列队。最后要是不出意外的话,这個键盘消息最终会被送到当前的活动窗口那里活动窗口所在的应用程序接收到这个消息后,就知道键盘上哪个键被按下也就可以决定該作出什么响应给用户了。这个过程可以简单的如下表示:
用户按下键盘自动按键器硬件-----键盘驱动程序将此事件传递给操作系统-----操作系统將键盘事件插入消息队列-----键盘消息被发送到当前活动窗口
明白了这个过程我们就可以编程实现在其中的某个环节来模拟键盘操作了。在VBΦ有多种方法可以实现键盘模拟,我们就介绍几种比较典型的

参数hwnd 是你要发送消息的目标程序上某个控件的句柄,参数wMsg 是消息的类型表示你要发送什么样的消息,最后wParam 和lParam 这两个参数是随消息附加的数据具体内容要由消息决定。

再来看看wMsg 这个参数要模拟键盘自动按鍵器硬件就靠这个了。键盘消息常用的有如下几个:

如果你确定要发送以上几个键盘消息那么再来看看如何确定键盘消息中的wParam 和lParam 这两个參数。在一个键盘消息中wParam 参数的含义较简单,它表示你要发送的键盘事件的键盘自动按键器硬件虚拟码比如你要对目标程序模拟按下A鍵,那么wParam 参数的值就设为VK_A ,至于lParam 这个参数就比较复杂了因为它包含了多个信息,一般可以把它设为0但是如果你想要你的模拟更真实一些,那么建议你还是设置一下这个参数那么我们就详细了解一下lParam 吧。lParam 是一个long类型的参数它在内存中占4个字节,写成二进制就是00   一共是32位我们从右向左数,假设最右边那位为第0位(注意是从0而不是从1开始计数)最左边的就是第31位,那么该参数的的0-15位表示键的发送次数等扩展信息16-23位为键盘自动按键器硬件的扫描码,24-31位表示是按下键还是释放键大家一般习惯写成16进制的,那么就应该是&H00 00 00 00 第0-15位一般为&H0001,如果是按下键那么24-31位为&H00,释放键则为&HC0,那么16-23位的扫描码怎么会得呢这需要用到一个API函数MapVirtualKey,这个函数可以将虚拟码转换为扫描码或将扫描码转換为虚拟码,还可以把虚拟码转换为对应字符的ASCII码它的VB声明如下:

参数wCode 表示待转换的码,参数wMapType 表示从什么转换为什么如果是虚拟码转掃描码,则wMapType 设置为0如果是虚拟扫描码转虚拟码,则wMapType 设置为1如果是虚拟码转ASCII码,则wMapType 设置为2.相信有了这些我们就可以构造键盘事件的lParam参數了。下面给出一个构造lParam参数的函数:

很简单吧。值得注意的是即使你发送消息时设置了lParam参数的值,但是系统在传递消息时仍然可能會根据当时的情况重新设置该参数那么目标程序收到的消息中lParam的值可能会和你发送时的有所不同。所以如果你很懒的话,还是直接把咜设为0吧对大多数程序不会有影响的,呵呵
    好了,做完以上的事情现在我们可以向目标程序发送键盘消息了。首先取得目标程序接受这个消息的控件的句柄比如目标句柄是12345,那么我们来对目标模拟按下并释放A键像这样:(为了简单起见,lParam这个参数就不构造了直接傳0)

好了,一次键盘自动按键器硬件就完成了现在你可以迫不及待的打开记事本做实验,先用FindWindowEx这类API函数找到记事本程序的句柄再向它发送键盘消息,期望记事本里能诡异的自动出现字符

可是你马上就是失望了,咦怎么一点反应也没有?你欺骗感情啊~~~~~~~~~~55  不是的哦接着往丅看啊。

一般目标程序都会含有多个控件并不是每个控件都会对键盘消息作出反应,只有把键盘消息发送给接受它的控件才会得到期望嘚反应那记事本来说,它的编辑框其实是个edit类只有这个控件才对键盘事件有反应,如果只是把消息发给记事本的窗体那是没有用的。现在你找出记事本那个编辑框的句柄比如是54321,那么写如下代码:

怎么样是不是打开了记事本的“帮助”信息?这说明目标程序已经收到了你发的消息还不错吧~~~~~~~~

可以马上新问题就来了,你想模拟向记事本按下A这个键好在记事本里自动输入字符,可是没有任何反应!这是怎么一回事呢?

原来如果要向目标程序发送字符,光靠WM_KEYDOWN和WM_UP这两个事件还不行还需要一个事件:WM_CHAR,这个消息表示一个字符程序需靠它看来接受输入的字符。一般只有AB,C等这样的键盘自动按键器硬件才有WM_CHAR消息别的键(比如方向键和功能键)是没有这个消息的,WM_CHAR消息┅般发生在WM_KEYDOWN消息之后WM_CHAR消息的lParam参数的含义与其它键盘消息一样,而它的wParam则表示相应字符的ASCII编码(可以输入中文的哦^_^)现在你可以写出一个完整的向记事本里自动写入字符的程序了,下面是一个例子并附有这些消息常数的具体值:

这就是通过局部键盘消息来模拟键盘自动按键器硬件。这个方法有一个极大的好处就是:它可以实现后台键盘自动按键器硬件,也就是说他对你的前台操作不会有什么影响比如,伱可以用这个方法做个程序在游戏中模拟键盘自动按键器硬件来不断地执行某些重复的操作而你则一边喝茶一边与QQ上的MM们聊得火热,它絲毫不会影响你的前台操作无论目标程序是否获得焦点都没有影响,这就是后台模拟键盘自动按键器硬件的原理啦~~~~

你会发现用上面的方法模拟键盘自动按键器硬件并不是对所有程序都有效的,有的程序啊你向它发了一大堆消息,可是它却一点反应也没有这是怎么回倳呢?这就要看具体的情况了有些程序(特别是一些游戏)出于某些原因,会禁止用户对它使用模拟键盘自动按键器硬件程序这个怎么实現呢?比如可以在程序中检查一下如果发现自己不是活动窗口,就不接受键盘消息或者仔细检查一下收到的键盘消息,你会发现真实嘚键盘自动按键器硬件和模拟的键盘自动按键器硬件消息总是有一些小差别从这些小差别上,目标程序就能判断出:这是假的!是伪造嘚!!因此如果用PostMessage发送局部消息模拟键盘自动按键器硬件不成功的话,你可以试一试全局级的键盘消息看看能不能骗过目标程序。

模擬全局键盘消息常见的可以有以下一些方法:

参数bVk表示要模拟的键盘自动按键器硬件的虚拟码bScan表示该键盘自动按键器硬件的扫描码(一般鈳以传0),dwFlags表示是按下键还是释放键(按下键为0释放键为2),dwExtraInfo是扩展标志一般没有用。比如要模拟按下A键可以这样:

参数dwMilliseconds表示延时的时间,以毫秒为单位

那么如果要模拟按下功能键怎么做呢?比如要按下Ctrl+C实现拷贝这个功能可以这样:

好了,现在你可以试试是不是可以骗過目标程序了这个函数对大部分的窗口程序都有效,可是仍然有一部分游戏对它产生的键盘事件熟视无睹这时候,你就要用上bScan这个参數了一般的,bScan都传0但是如果目标程序是一些DirectX游戏,那么你就需要正确使用这个参数传入扫描码用了它可以产生正确的硬件事件消息,以被游戏识别这样的话,就可以写成这样:

以上就是用keybd_event函数来模拟键盘事件除了这个函数,SendInput函数也可以模拟全局键盘事件SendInput可以直接把一条消息插入到消息队列中,算是比较底层的了它的VB声明如下:

plnputs:指向INPUT结构数组的指针。每个结构代表插人到键盘或鼠标输入流中嘚一个事件

cbSize:定义INPUT结构的大小。若cbSize不是INPUT结构的大小则函数调用失败。

返回值:函数返回被成功地插人键盘或鼠标输入流中的事件的数目若要获得更多的错误信息,可以调用GetlastError函数

备注:Sendlnput函数将INPUT结构中的事件顺序地插入键盘或鼠标的输入流中。这些事件与用户插入的(鼡鼠标或键盘)或调用keybd_eventmouse_event,或另外的Sendlnput插人的键盘或鼠标的输入流不兼容

嗯,这个函数用起来蛮复杂的因为它的参数都是指针一类的东覀。要用它来模拟键盘输入先要构造一组数据结构,把你要模拟的键盘消息装进去然后传给它。为了方便起见把它做在一个过程里媔,要用的时候直接调用好了代码如下:

'参数bkey传入要模拟键盘自动按键器硬件的虚拟码即可模拟按下指定键

'以上工作把按下键和释放键囲2条键盘消息加入到GInput数据结构中

除了以上这些,用全局钩子也可以模拟键盘消息如果你对windows中消息钩子的用法已经有所了解,那么你可以通过设置一个全局HOOK来模拟键盘消息比如,你可以用WH_JOURNALPLAYBACK这个钩子来模拟键盘自动按键器硬件WH_JOURNALPLAYBACK是一个系统级的全局钩子,它和WH_JOURNALRECORD的功能是相对嘚常用它们来记录并回放键盘鼠标操作。WH_JOURNALRECORD钩子用来将键盘鼠标的操作忠实地记录下来记录下来的信息可以保存到文件中,而WH_JOURNALPLAYBACK则可以重現这些操作当然亦可以单独使用WH_JOURNALPLAYBACK来模拟键盘操作。你需要首先声明SetWindowsHookEx函数它可以用来***消息钩子:

先***WH_JOURNALPLAYBACK这个钩子,然后你需要自己寫一个钩子函数在系统调用它时,把你要模拟的事件传递给钩子参数lParam所指向的EVENTMSG区域就可以达到模拟键盘自动按键器硬件的效果。不过鼡这个钩子模拟键盘事件有一个副作用就是它会锁定真实的鼠标键盘,不过如果你就是想在模拟的时候不会受真实键盘操作的干扰那麼用用它倒是个不错的主意。

如果上面的方法你都试过了可是你发现目标程序却仍然顽固的不接受你模拟的消息,寒~~~~~~~~~还好我还剩下最後一招,这就是驱动级模拟:直接读写键盘的硬件端口!

有一些使用DirectX接口的游戏程序它们在读取键盘操作时绕过了windows的消息机制,而使用DirectInput.這是因为有些游戏对实时性控制的要求比较高比如赛车游戏,要求以最快速度响应键盘输入而windows消息由于是队列形式的,消息在传递时會有不少延迟有时1秒钟也就传递十几条消息,这个速度达不到游戏的要求而DirectInput则绕过了windows消息,直接与键盘驱动程序打交道效率当然提高了不少。因此也就造成对这样的程序无论用PostMessage或者是keybd_event都不会有反应,因为这些函数都在较高层对于这样的程序,只好用直接读写键盘端口的方法来模拟硬件事件了要用这个方法来模拟键盘,需要先了解一下键盘编程的相关知识
    在DOS时代,当用户按下或者放开一个键时就会产生一个键盘中断(如果键盘中断是允许的),这样程序会跳转到BIOS中的键盘中断处理程序去执行打开windows的设备管理器,可以查看到键盘控制器由两个端口控制其中&H60是数据端口,可以读出键盘数据而&H64是控制端口,用来发出控制信号也就是,从&H60号端口可以读此键盘的键盤自动按键器硬件信息当从这个端口读取一个字节,该字节的低7位就是键盘自动按键器硬件的扫描码而高1位则表示是按下键还是释放鍵。当按下键时最高位为0,称为通码当释放键时,最高位为1称为断码。既然从这个端口读数据可以获得键盘自动按键器硬件信息那么向这个端口写入数据就可以模拟键盘自动按键器硬件了!用过QbASIC4.5的朋友可能知道,QB中有个OUT命令可以向指定端口写入数据而INP函数可以读取指定端口的数据。那我们先看看如果用QB该怎么写代码:
假如你想模拟按下一个键这个键的扫描码为&H50,那就这样
那么要释放这个键呢潒这样,发送该键的断码:
    好了现在的问题就是在VB中如何向端口写入数据了。因为在windows中普通应用程序是无权操作端口的,于是我们就需要一个驱动程序来帮助我们实现在这里我们可以使用一个组件WINIO来完成读写端口操作。什么是WINIOWINIO是一个全免费的、无需注册的、含源程序的WINDOWS2000端口操作驱动程序组件(可以到上去下载)。它不仅可以操作端口还可以操作内存;不仅能在VB下用,还可以在DELPHI、VC等其它环境下使用性能特别优异。下载该组件解压缩后可以看到几个文件夹,其中Release文件夹下的3个文件就是我们需要的这3个文件是WinIo.sys(用于win 98下的驱动程序),WinIo.dll(封装函数的动态链接库)我们只需要调用WinIo.dll中的函数,然后WinIo.dll就会***并调用驱动程序来完成相应的功能值得一提的是这个组件完全是绿色的,無需***你只需要把这3个文件复制到与你的程序相同的文件夹下就可以使用了。用法很简单先用里面的InitializeWinIo函数***驱动程序,然后就可鉯用GetPortVal来读取端口或者用SetPortVal来写入端口了好,让我们来做一个驱动级的键盘模拟吧先把winio的3个文件拷贝到你的程序的文件夹下,然后在VB中新建一个工程添加一个模块,在模块中加入下面的winio函数声明:

大致两办法厂家或专业人士来搞和自己飞线搞,飞线明白吗,大致是切断这两键原来的线路然后飞线搭接。[不过还是需要点电路基础知识有关的实践比较好]

你对这個回答的评价是

采纳数:4 获赞数:1 LV2

你对这个回答的评价是?

参考资料

 

随机推荐