SendInput()函数

SendInput()函数用于合成键盘事件和鼠标事件,用来模拟鼠标或者键盘操作。

函数原型:

UINT SendInput([in] UINTcInputs,[in] LPINPUT pInputs,[in] int cbSize);

参数:

cInputs

类型:UINT(32位无符号整数)

函数SendInput()第二个参数pInputs的数组个数,可用ARRAYSIZE( )方式获取

pInputs

类型:LPINPUT

INPUT结构体指针,实例化对象时每个对象代表一个模拟操作动作

cbSize

类型:int

输入结构的大小(以字节为单位),可用sizeof( )方式获取

返回值类型

类型:UINT

该函数返回它成功插入键盘或鼠标输入流的事件数,如果函数返回零,则输入已被另一个线程阻止。若要获取扩展的错误信息,请调用 GetLastError。

INPUT结构体

原型:

typedef struct tagINPUT {DWORD type;union {MOUSEINPUTmi;KEYBDINPUTki;HARDWAREINPUT hi;} DUMMYUNIONNAME;} INPUT, *PINPUT, *LPINPUT;

参数:type

类型:DWORD

成员type可以是以下值之一

参数意义

INPUT_MOUSE

0

该事件是鼠标事件。使用联合的mi结构。

INPUT_KEYBOARD

1

该事件是键盘事件。使用联合的ki结构。

INPUT_HARDWARE

2

该事件是硬件事件。使用联合的hi结构

参数:DUMMYUNIONNAME

类型:union

成员DUMMYUNIONNAME为联合体

成员type中的值分别对应DUMMYUNIONNAME参数

INPUT_MOUSE->mi

INPUT_KEYBOARD->ki

HARDWAREINPUT->hi

mi/ki/hi的类型分别对应的是结构体MOUSEINPUT,KEYBDINPUT,HARDWAREINPUT

看到这可能有点乱,我们用一张导图整理一下

下面我们看看

MOUSEINPUT KEYBDINPUT HARDWAREINPUT 这三个结构体

MOUSEINPUT 结构体

原型

typedef struct tagMOUSEINPUT {LONGdx;LONGdy;DWORD mouseData;DWORD dwFlags;DWORD time;ULONG_PTR dwExtraInfo;} MOUSEINPUT, *PMOUSEINPUT, *LPMOUSEINPUT;

参数:dx,dy

类型:LONG

dx,dy默认为鼠标移动相对数值(与上次位置变化相比),若想用其绝对数值需要在dwFlags成员里面使用MOUSEEVENTF_ABSOLUTE标识符

参数:mouseDate

类型:DWORD

1.如果 dwFlags 包含MOUSEEVENTF_WHEEL,则 mouseData 表明指定滚轮移动量。正值表示滚轮向前旋转;负值表示滚轮向后旋转。

2.如果 dwFlags 包含MOUSEEVENTF_XDOWN或MOUSEEVENTF_XUP,则 mouseData 指定按下或释放了哪些 X 按钮。此值可以是以下的任意组合

残数意义
XBUTTON1
0x0001
设置是按下还是松开第一个 X 按钮。
XBUTTON2
0x0002
设置是按下还是松开第二个 X 按钮。

如果dwFlags里面没有MOUSEEVENTF_XDOWN ,MOUSEEVENTF_XUP , mouseData

这三个标识符,则我们把mouseData置为0;

参数:dwFlags

类型:DWORD

此值可以是以下的任意组合

MOUSEEVENTF_MOVE

0x0001

鼠标事件

MOUSEEVENTF_LEFTDOWN

0x0002

鼠标左键按下

MOUSEEVENTF_LEFTUP

0x0004

鼠标左键释放

MOUSEEVENTF_RIGHTDOWN

0x0008

鼠标右键按下

MOUSEEVENTF_RIGHTUP

0x0010

鼠标右键释放

MOUSEEVENTF_MIDDLEDOWN

0x0020

鼠标中部按下

MOUSEEVENTF_MIDDLEUP

0x0040

鼠标中部释放

MOUSEEVENTF_XDOWN

0x0080

鼠标侧键按下

MOUSEEVENTF_XUP

0x0100

鼠标侧键释放

MOUSEEVENTF_WHEEL

0x0800

.鼠标滚轮移动,移动数值在mouseData指定

MOUSEEVENTF_ABSOLUTE

0x8000

若使用此值,则说明成员dxdy为绝对坐标,坐标 (0,0) 映射到显示表面的左上角;坐标 (65535,65535) 映射到右下角。在多显示器系统中,坐标映射到主显示器。

参数:time

类型:DWORD

事件的时间戳(以毫秒为单位)。如果此参数为 0,系统将提供自己的时间戳。

参数:dwExtraInfo

类型:DWORD

与鼠标事件关联的附加值。应用程序调用 GetMessageExtraInfo 来获取此额外信息。

KEYBDINPUT结构体

原型

typedef struct tagKEYBDINPUT {WORDwVk;WORDwScan;DWORD dwFlags;DWORD time;ULONG_PTR dwExtraInfo;} KEYBDINPUT, *PKEYBDINPUT, *LPKEYBDINPUT;

参数:wVk

类型:word

虚拟键盘代码.

参数:dwFlags

类型:DWORD

此值可以是以下的数值

KEYEVENTF_KEYUP

0x0002

如果指定,则正在释放按键。如果未指定,则正在按下该键。

KEYEVENTF_SCANCODE

0x0008

If specified,wScanidentifies the key andwVkis ignored.

KEYEVENTF_UNICODE

0x0004

If specified, the system synthesizes aVK_PACKETkeystroke. ThewVkparameter must be zero. This flag can only be combined with theKEYEVENTF_KEYUPflag. For more information, see the Remarks section.

示范代码

//**********************************************************************//// Sends Win + D to toggle to the desktop//按下win+D键示例//**********************************************************************void ShowDesktop(){OutputString(L"Sending 'Win-D'\r\n");INPUT inputs[4] = {};ZeroMemory(inputs, sizeof(inputs));inputs[0].type = INPUT_KEYBOARD;inputs[0].ki.wVk = VK_LWIN; inputs[1].type = INPUT_KEYBOARD;inputs[1].ki.wVk = VK_D;inputs[2].type = INPUT_KEYBOARD;inputs[2].ki.wVk = VK_D;inputs[2].ki.dwFlags = KEYEVENTF_KEYUP;inputs[3].type = INPUT_KEYBOARD;inputs[3].ki.wVk = VK_LWIN;inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;UINT uSent = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));if (uSent != ARRAYSIZE(inputs)){OutputString(L"SendInput failed: 0x%x\n", HRESULT_FROM_WIN32(GetLastError()));} }

封装的两个函数

#define Press 1#define Realse 0/*成员dx,dy为移动为xy距离,absolute为移动是否相对值,成功返回1*//*Virtually为虚拟键码,Status为状态按下Press或者Realse*/BOOL MouseEvent(int dx, int dy, bool absolute);BOOL KeyBoardEvent(unsigned int VirtualKey, bool Status);BOOL MouseEvent(int dx, int dy, bool absolute){INPUT inputs[1] = {};ZeroMemory(inputs, sizeof(inputs));inputs[0].type = INPUT_MOUSE;inputs[0].mi.dx = dx;inputs[0].mi.dy = dy;inputs[0].mi.mouseData = 0;if (absolute == 1){inputs[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;}else if (absolute == 0){inputs[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;}UINT uSent = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));if (uSent != ARRAYSIZE(inputs)){cout << "SendInput failed: 0x%x\n" << HRESULT_FROM_WIN32(GetLastError());return 0;}else{cout << "Success" << endl;return 1;}}BOOL KeyBoardEvent(unsigned int VirtualKey, bool Status){INPUT inputs[1] = {};ZeroMemory(inputs, sizeof(inputs));inputs[0].type = INPUT_KEYBOARD;inputs[0].ki.wVk = VirtualKey;if (Status == Press){}else if (Status == Realse){inputs[0].ki.dwFlags = KEYEVENTF_KEYUP;}UINT uSent = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));if (uSent != ARRAYSIZE(inputs)){cout << "SendInput failed: 0x%x\n" << HRESULT_FROM_WIN32(GetLastError());return 0;}else{cout << "Success" << endl;return 1;}}