delphi利用SendInput模拟鼠标键盘
delphi 利用SendInput模拟鼠标键盘
作者:admin 来源: 日期:2011-8-18 13:21:17 人气:1250 标签:
QQ空间 新浪微博 腾讯微博 腾讯朋友 QQ收藏 百度空间 百度贴吧 更多0
前言
一、SendInput
SendInput可以将指定的鼠标键盘消息插入到系统消息队列,从而实现对鼠标键盘的模拟。有很多程序对SendInput进行了屏蔽,但不是所有的。所以这里介绍一下SendInput的使用。我已经将主要的模拟功能写在了一个单元文件中:SIMouseKeyboard.pas,调用该单元文件中的相关函数就可以实现鼠标键盘的模拟。该单元文件的下载见本楼末尾。SendInput的参数其实很简单,在Windows.pas就有函数的声明如下:
function SendInput(cInputs: UINT; var pInputs: TInput; cbSize: Integer): UINT; stdcall;
cInputs:定义pInputs中记录数组的元素数目。pInputs:TInput类型记录数组的第1个元素。每个元素代表插人到系统消息队列的键盘或鼠标事件。cbSize:定义TInput的大小,一般为SizeOf(TInput)。函数返回成功插入系统消息队列中事件的数目,失败返回0。调用SendInput关键的就是要搞清楚它的几个记录结构的意思,在Windows.pas中对TInput的声明如下:
tagINPUT = packed record
Itype: DWORD;
case Integer of
0: (mi: TMouseInput);
1: (ki: TKeybdInput);
2: (hi: THardwareInput);
end;
TInput = tagINPUT;
其中mi、ki、hi是3个共用型的记录结构,Itype指出记录结构中所使用的类型,它有3个值。INPUT_MOUSE:表示使用mi记录结构,忽略ki和hi;INPUT_KEYBOARD:表示使用ki记录结构,忽略mi和hi。
二、键盘模拟
TKeybdInput记录结构的声明如下:
tagKEYBDINPUT = packed record
wVk: WORD;
wScan: WORD;
dwFlags: DWORD;
time: DWORD;
dwExtraInfo: DWORD;
end;
TKeybdInput = tagKEYBDINPUT;
其中wVk是将要操作的按键的虚键码。wScan是安全码,一般不用。dwFlags指定键盘所进行的操作,为0时表示按下某键,KEYEVENTF_KEYUP表示放开某键。time是时间戳,可以使用API函数GetTickCount的返回值。dwExtraInfo是扩展信息,可以使用API函数GetMessageExtraInfo的返回值。例如击键“A”的程序如下:
procedure KeyPressA;
var
Inputs : array [0..1] of TInput;
begin
Inputs[0].Itype:=INPUT_KEYBOARD;
with Inputs[0].ki do
begin
wVk:=VK_A;
wScan:=0;
dwFlags:=0;
time:=GetTickCount;
dwExtraInfo:=GetMessageExtraInfo;
end;
Inputs[1].Itype:=INPUT_KEYBOARD;
with Inputs[1].ki do
begin
wVk:=VK_A;
wScan:=0;
dwFlags:=KEYEVENTF_KEYUP;
time:=GetTickCount;
dwExtraInfo:=GetMessageExtraInfo;
end;
SendInput(2,Inputs[0],SizeOf(TInput));
end;
注意:在Windows.pas单元中并没有字母和数字的虚键码的声明,在我写的SIMouseKeyboard.pas单元文件中对所有的虚键码进行了重新声明,包含了字母、数字和标点符号。
三、鼠标模拟
TMouseInput记录结构的声明如下:
tagMOUSEINPUT = packed record
dx: Longint;
dy: Longint;
mouseData: DWORD;
dwFlags: DWORD;
time: DWORD;
dwExtraInfo: DWORD;
end;
TMouseInput = tagMOUSEINPUT;
其中dx、dy是鼠标移动时的坐标差(不是象素单位),在鼠标移动时有效。mouseData是鼠标滚轮滚动值,在滚动鼠标滚轮时有效。当mouseData小于0时向下滚动,当mouseData大于0时向上滚动,mouseData的绝对值一般设为120。dwFlags指定鼠标所进行的操作,例如,MOUSEEVENTF_MOVE表示移动鼠标,MOUSEEVENTF_LEFTDOWN表示按下鼠标左键,MOUSEEVENTF_LEFTUP表示放开鼠标左键。time是时间戳,可以使用API函数GetTickCount的返回值。dwExtraInfo是扩展信息,可以使用API函数GetMessageExtraInfo的返回值。例如单击鼠标左键的程序如下:
procedure MouseClick;
var
Inputs : array [0..1] of TInput;
begin
Inputs[0].Itype:=INPUT_MOUSE;
with Inputs[0].mi do
begin
dx:=0;
dy:=0;
mouseData:=0;
dwFlags:=MOUSEEVENTF_LEFTDOWN;
time:=GetTickCount;
dwExtraInfo:=GetMessageExtraInfo;
mousemove是什么键end;
Inputs[1].Itype:=INPUT_MOUSE;
with Inputs[1].mi do
begin
dx:=0;
dy:=0;
mouseData:=0;
dwFlags:=MOUSEEVENTF_LEFTUP;
time:=GetTickCount;
dwExtraInfo:=GetMessageExtraInfo;
end;
SendInput(2,Inputs[0],SizeOf(TInput));
end;
鼠标的移动总是很麻烦,上面的dx、dy不是以象素为单位的,而是以鼠标设备移动量为单位的,它们之间的比值受鼠标移动速度设置的影响。具体的解决方法我已经在《Delphi下
利用WinIo模拟鼠标键盘详解》一文中进行了讨论,这里不再重复。dwFlags可以设置一个MOUSEEVENTF_ABSOLUTE标志,这使得可以用另外一种方法移动鼠标。当dwFlags设置了MOUSEEVENTF_ABSOLUTE标志,dx、dy为屏幕坐标值,表示将鼠标移动到dx,dy的位置。但是这个坐标值也不是以象素为单位的。这个值的范围是0到65535($FFFF),当dx等于0、dy等于0时表示屏幕的最左上角,当dx等于65535、dy等于65535时表示屏幕的最右下角,相当于将屏幕的宽和高分别65536等分。API函数GetSystemMetrics(SM_CXSCREEN)可以返回屏幕的宽度,函数GetSystemMetrics(SM_CYSCREEN)可以返回屏幕的高度,利用屏幕的宽度和高度就可以将象素坐标换算成相应的dx、dy。注意:这种换算最多会出现1象素的误差。例如:将鼠标指针移动到屏幕150,120坐标处的程序如下:
procedure MouseMove;
var
Input : TInput;
begin
Input.Itype:=INPUT_MOUSE;
with Input.mi do
begin
dx:=($FFFF div (GetSystemMetrics(SM_CXSCREEN)-1)) * 150;
dy:=($FFFF div (GetSystemMetrics(SM_CYSCREEN)-1)) * 120;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论