已阅读5页,还剩2页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
原创Delphi下利用WinIo模拟鼠标键盘详解前言 一日发现SendInput对某程序居然无效,无奈只好开始研究WinIo。上网查了很多资料,发现关于WinIo模拟鼠标键盘的资料很少,有的也只是支言片语讲的不是很详细,而且大部分都是关于模拟键盘的。自己写了一些程序研究一方,经历了无数次的键盘死锁、鼠标满屏乱飞、复位重启,总算小有结果。现在将研究结果写出来与大家分享。另外,本人的水平有限文中有出错的地方欢迎根贴讨论。(PS:关于SendInput的使用可以参考我写的另一篇贴子Delphi下利用SendInput模拟鼠标键盘/bbs/view12-17219-1.htm)我已经将主要的模拟功能写在了一个单元文件中:MouseKeyboard.pas,调用该单元文件中的相关函数就可以实现鼠标键盘的模拟。该单元文件的下载和使用方法请参考2楼的内容。在本楼的末尾有一个中英文对译PS/2鼠标键盘协议的下载,这个协议对编写模拟鼠标键盘的程序很有帮助。另外我还提供了一个鼠标移动速度测试程序、一个使用MouseKeyboard.pas的简单示范程序的下载。一、WinIo简介WinIo通过加载一个内核模式的设备驱动程序,利用几种底层编程技巧,使得Windows应用程序可以直接对I/O端口和物理内存进行存取,从而绕过了Windows系统的保护机制。WinIo包含了3个文件:WinIo.dll、WinIo.sys和WINIO.VXD,其中WINIO.VXD驱动程序用在Win95/98系统上,WinIo.sys驱动程序用在WinNT/2000/XP系统上,WinIo.dll提供了功能函数的调用。在WinIo.dll中有两个函数最重要:InitializeWinIo用来初始化WinIo的驱动程序,必须在调用所有其它功能函数之前调用该函数;ShutdownWinIo用来卸载WinIo的驱动程序,在中止应用函数之前或者不再需要使用WinIo时调用。在初始化完成之后就可以直接读写I/O端口而不会出现非法操作,本程序就是利用向鼠标键盘硬件端口写入数据来模拟鼠标键盘的操作。由于是底层的硬件端口读写,所以必需对硬件的相关协议有所了解,对于鼠标键盘最重要的协议就是PS/2鼠标键盘协议(以下简称PS/2协议)。我这里提供了一个pdf版的中英文对译PS/2鼠标键盘协议,在该协议的前半部主要讲硬件的电气接口协议,但是后半部分的内容对于模拟鼠标键盘非常有用。这个协议可是我在网上翻腾了好久才找到的。协议的下载见本楼末尾。二、Intel8042Intel8042或兼容微控制器(以下简称i8042)被用作PC键盘的控制器,虽然名为键盘控制器,但是实际上鼠标也是由其控制的。i8042一般整合在芯片组中。向i8042发送指定的命令和数据就可以模拟鼠标键盘的操作。i8042包含了如下四个寄存器:一个字节的输入缓冲区:包含从鼠标或键盘读入的字节;只读。一个字节的输出缓冲区:包含要写到鼠标或键盘的字节;只写。一个字节的状态寄存器:8个状态标志;只读。一个字节的控制寄存器:7个控制标志;读写。其中前三个寄存器(输入、输出、状态)可以通过$60和$64端口直接存取,读写$60和$64端口所实现的功能如下:端口读写功能$60读读输入缓冲区$60写写输出缓冲区$64读读状态寄存器$64写发送命令写$64端口不会写入到任何特定的寄存器中,但是解释为发送命令给i8042。如果命令接收一个参数,则参数被发往$60端口。同样,命令的任何返回结构可以从$60端口读出。i8042的状态标志是从$64端口读出的。它们包含了错误信息、状态信息和输入输出缓冲区里有无数据的指示。这些标志的定义如下:Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0PERRTOMOBFINHA2SYSIBFOBF其中标志位OBF最重要(其它标志位的意思请参考PS/2协议),它表示输出缓冲区是否已满,是否可以写入输出缓冲区。0表示输出缓冲区空,1表示输出缓冲区已满。所以在向$60端口写入数据之前要检查该标志位是否已被置0。另外在向$64端口发送命令之前也要检查该标志位,已确保上次的操作已经完成。向指定端口写入数据的程序如下,其中使用了内嵌汇编对端口进行操作。注意:鼠标键盘是慢速设备,每次操作时要有一定的延时:procedureSetByte(Por,Cod:Byte);beginSleep(1);asmPUSHEAXPUSHEDX/等待状态寄存器标志位OBF置0Loop:INAL,$64ANDAL,01bJNZLoop/写入数据MOVAL,CodMOVDL,PorMOVDH,0OUTDX,ALPOPEDXPOPEAXend;end;发送命令给i8042就是写$64端口。在命令发送后,命令参数写到$60端口。命令中用来模拟鼠标键盘操作的有两条(其它命令请参考PS/2协议):$D2:写键盘缓冲区,把参数写到输入缓冲区就像从键盘接收到的一样。$D3:写鼠标缓冲区,把参数写到输入缓冲区就像从鼠标接收到的一样。例如:按下“A”键,利用上面的程序可以写成“SetByte($64,$D2);SetByte($60,$1E);”。注意:如果向$60端口发送的数据不只1个字节,那么发送的每个字节前都要发送一条命令,例如:按下“Insert”键的程序为“SetByte($64,$D2);SetByte($60,$E0);SetByte($64,$D2);SetByte($60,$52);”,要调用SetByte四次。知道了如何向i8042发送命令,下面就可以具体的模拟鼠标键盘。三、键盘模拟键盘的处理器会扫描或监视按键矩阵。如果它发现有键被按下、释放或按住,键盘将发送“扫描码”的数据包到i8042。扫描码有两种不同的类型:“通码”和“断码”,当一个键被按下或按住就发送通码;当一个键被释放就发送断码。每个按键被分配了唯一的通码和断码,这样i8042通过查找唯一的扫描码就可以测定是哪个按键。每个键一整套的通断码组成了“扫描码集”。有三套标准的扫描码集分别是第一套、第二套和第三套。i8042缺省支持第一套扫描码。一部份键的断码是将通码的最高位置1,但并不是所有的键都这样,而且很多键的扫描码不只有1个字节。所以没有一个简单的公式可以计算扫描码。如果你要知道某特定按键的通码和断码,你将不得不查表获得。例如:“A”键的通码为$1E,断码为$9E,“Insert”键的通码为$E0,$52,断码为$E0,$D2,模拟按键的程序如下:/按下并放开“A”键SetByte($64,$D2);SetByte($60,$1E);SetByte($64,$D2);SetByte($60,$9E);/按下并放开“Insert”键SetByte($64,$D2);SetByte($60,$E0);SetByte($64,$D2);SetByte($60,$52);SetByte($64,$D2);SetByte($60,$E0);SetByte($64,$D2);SetByte($60,$D2);特别的在PS/2协议中说在第一第二套扫描码里没有“Pause/Break”键的断码。当这个键按下时发送它的通码,当它释放时,什么都没有被发送。在第一套扫描码里Pause键的通码长达6个字节:$E1,$1D,$45,$E1,$9D,$C5。但是我在实际测试中发现Pause键的通码其实是前3个字节:$E1,$1D,$45,后3个字节$E1,$9D,$C5是Pause键的断码。至少在我的键盘上是这样。在PS/2协议中已经把所有三套扫描码集中所有的通码和断码做成了表格,具体的内容可以查阅相关的部份。在单元文件MouseKeyboard.pas中我已经将第一套键盘扫描码定义成常量数组,其中还包括了键对应的字符。单元中有两个函数MKFindKeyCode和MKFindKeyChar,可以用来对常量数组进行查找。四、鼠标模拟标准的PS/2鼠标支持下面的输入:X(左右)位移、Y(上下)位移、左键、中键和右键。鼠标以一个固定的频率读取这些输入并更新不同的计数器然后标记出反映的移动和按键状态。有很多PS/2鼠标具有额外的输入比如微软的Intellimouse,它既支持标准输入也支持滚轮和两个附加的按键。标准的鼠标有两个计数器保持位移的跟踪:X位移计数器和Y位移计数器。可存放9位的2进制补码并且每个计数器都有相关的溢出标志。它们的内容连同三个鼠标按钮的状态一起以三字节移动数据包的形式发送给i8042。位移计数器表示从最后一次位移数据包被送往i8042后有位移量发生。标准的PS/2鼠标发送位移和按键信息给i8042采用如下的3字节数据包格式:Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0Byte1Y溢出位X溢出位Y符号位X符号位置1中键位右键位左键位Byte2X左右移位值,补码Byte3Y上下移位值,补码位移计数器是一个9位二进制补码整数。它的最高位作为符号位出现在位移数据包的第一个字节里,这些计数器在鼠标读取输入发现有位移时被更新,这些值是自从最后一次发送位移数据包给i8042后位移的累计量(即最后一次包发给i8042后位移计数器被复位),位移计数器可表示的值的范围是-255到+255。如果超过了范围,相应的溢出位就被设置,并且在复位前计数器不会增减。对标准的PS/2鼠标的一个流行的扩展是微软的Intellimouse。它包括支持五个鼠标按键和三个位移轴(左右、上下和滚轮)。这些附加特征要求使用4字节的位移数据包而不是标准3字节数据包。微软的Intellimouse使用4字节的位移数据包格式有两种情况分别如下:1、三键带滚轮鼠标:Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0Byte1Y溢出位X溢出位Y符号位X符号位置1中键位右键位左键位Byte2X左右移位值,补码Byte3Y上下移位值,补码Byte4Z滚动移位值,补码Z位移是二进制补码表示滚轮的自上次数据报告以来的位移。有效值的范围在-8到+7,这意味着数值实际只有低四位有用,高四位仅用作符号扩展位。当Z小于0时表示向上滚动,当Z大于0时表示向下滚动。2、五键带滚轮鼠标:Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0Byte1Y溢出位X溢出位Y符号位X符号位置1中键位右键位左键位Byte2X左右移位值,补码Byte3Y上下移位值,补码Byte4置0置0第5键位第4键位Z3Z2Z1Z0Z0Z3是二进制补码用于表示从上次数据报告以来滚轮的位移量,有效范围从-8到+7;第4键位:置1表示第4键按下了,置0表示第4键没有按下;第5键位:置1表示第5键按下了,置0表示第5键没有按下。可以看出三键带滚轮鼠标和五键带滚轮鼠标这两种数据包格式是相互兼容的。一般现在使用的鼠标都是带滚轮的,所以使用的都是4字节的数据包格式。调用API函数GetSystemMetrics(SM_CMOUSEBUTTONS)可以返回当前鼠标的按键数,调用GetSystemMetrics(SM_MOUSEWHEELPRESENT)可以返回当前鼠标是否有带滚轮。通过调用这两个API函数可以判断当前使用的是3字节数据包还是4字节数据包。知道了数据包的格式就可以向i8042发送$D3命令模拟鼠标操作,模拟单击鼠标左键的程序如下:/按下鼠标左键SetByte($64,$D3);SetByte($60,$09);SetByte($64,$D3);SetByte($60,$00);SetByte($64,$D3);SetByte($60,$00);SetByte($64,$D3);SetByte($60,$00);/三键带滚轮鼠标/放开鼠标左键SetByte($64,$D3);SetByte($60,$08);SetByte($64,$D3);SetByte($60,$00);SetByte($64,$D3);SetByte($60,$00);SetByte($64,$D3);SetByte($60,$00);/三键带滚轮鼠标现在再来谈谈鼠标移动的模拟,鼠标移动的模拟其实是一个很头痛的问题。如果只是让鼠标随便动动那是很简单,但是要将鼠标在屏幕上的指针移动到指定坐标就不是那么容易的事件了。首先,鼠标位移计数器使用的是平面直角坐标系。也就说当鼠标向左移动时X小于0,当鼠标向右移动时X大于0,当鼠标向下移动时Y小于0当鼠标向上移动时Y大于0。屏幕上的指针坐标使用的是计算机屏幕坐标系,对应于平面直角坐标系在X轴上是一致的,在Y轴上相差一个正负号。其次,决定位移计数器增减数量的参数叫分辨率,缺省的分辨率为:4计数单位每毫米。这就意味着鼠标位移计数器的位移量(以下简称鼠标位移量)同鼠标指针在屏幕上的象素位移量(以下简称指针位移量)并不一样。鼠标位移量同指针位移量的比值与鼠标移动速度的设置有关,通过“控制面板”中“鼠标”选项卡的“调整指针移动速度”可以对该值进行设置,这个值保存在注册表HKEY_CURRENT_USERControlPanelMouseMouseSensitivity中,通过修改注册表可以将这个值设置成带有小数点的,通过调用API函数SystemParametersinfo使用参数SPI_GETMOUSESPEED就可以获取该值。另外,使用第三方鼠标驱动程序也可以设置鼠标的移动速度,一般这类驱动程度都有带鼠标加速功能,这使得鼠标位移量同指针位移量的比值根本无法确定。当使用Windows自带的鼠标驱动程序,在鼠标选项卡中将指针移动速度设置在中间位置,注册表中MouseSensitivity的值为10,此时鼠标位移量同指针位移量的比值还是可以计算的,当鼠标位移量小于7时:指针位移量等于鼠标位移量;当鼠标位移量大于等于7时:指针位移量等于鼠标位移量的2倍。在这种情况下的前20个比值如下,其中n为鼠标位移量,cX、cY为指针位移量:n,cX,cY1,1,12,2,23,3,34,4,45,5,56,6,67,14,148,16,169,18,1810,20,2011,22,2212,24,2413,26,2614,28,2815,30,3016,32,3217,34,3418,36,3619,38,3820,40,40例如:让鼠标指针在屏幕上移动的程序如下:/鼠标上移50象索SetByte($64,$D3);SetByte($60,$08);SetByte($64,$D3);SetByte($60,$00);SetByte($64,$D3);SetByte($60,$19);SetByte($64,$D3);SetByte($60,$00);/三键带滚轮/鼠标左移50象索SetByte($64,$D3);SetByte($60,$18);SetByte($64,$D3);SetByte($60,$E7);SetByte($64,$D3);SetByte($60,$00);SetByte($64,$D3);SetByte($60,$00);/三键带滚轮另外我发现一些鼠标对于大的鼠标移动量(大于128
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024重金属污染土壤修复剂
- 《医用物理学》超长详细笔记
- 强调工作重要性的排比句50例
- 2024年自然科学研究与试验发展服务项目资金需求报告代可行性研究报告
- 2024年眼用抗感染药项目资金申请报告
- 2024年甲醇制烯烃项目资金需求报告代可行性研究报告
- 起重机械钢结构冷喷烯锌防护涂装技术指南-意见征求稿
- Python程序设计实践- 习题及答案 ch19 实验15 数据可视化
- 护理措施及护理问题
- 模范人物敬业奉献事迹材料范文5篇
- 慢性病防治和健康生活知识讲座
- 中华民族共同体概论课件第十六讲文明新路与人类命运共同体
- 人教部编版一年级道德与法治上册第10课《吃饭有讲究》精美课件
- 2024-2030全球与中国铂铜合金市场现状及未来发展趋势
- 2024年度-《医疗事故处理条例》解读
- 供电企业舆情的预防及处置
- (高清版)WST 433-2023 静脉治疗护理技术操作标准
- 医院科研合作与成果转化协议书
- 销售配合与带动(课件)
- 4、《通向金融王国的自由之路》
- 生产建设项目水土保持方案编制
评论
0/150
提交评论