SendInput()函数:
SendInput()函数用于合成键盘事件和鼠标事件,用来模拟鼠标或者键盘操作。
函数原型:
UINT SendInput(
[in] UINT cInputs,
[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 {
MOUSEINPUT mi;
KEYBDINPUT ki;
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 {
LONG dx;
LONG dy;
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 {
WORD wVk;
WORD wScan;
DWORD dwFlags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT, *LPKEYBDINPUT;
参数:wVk
类型:word
虚拟键盘代码.
参数:dwFlags
类型:DWORD
此值可以是以下的数值
KEYEVENTF_KEYUP
0x0002
如果指定,则正在释放按键。如果未指定,则正在按下该键。
KEYEVENTF_SCANCODE
0x0008
If specified, wScan identifies the key and wVk is ignored.
KEYEVENTF_UNICODE
0x0004
If specified, the system synthesizes a VK_PACKET keystroke. The wVk parameter must be zero. This flag can only be combined with the KEYEVENTF_KEYUP flag. 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;
}
}
版权归原作者 @李子涵 所有, 如有侵权,请联系我们删除。