SendInput() 的问题
Posted
技术标签:
【中文标题】SendInput() 的问题【英文标题】:Issues with SendInput() 【发布时间】:2021-09-09 13:49:25 【问题描述】:我希望能就这段代码得到一些帮助。
#include <windows.h>
#include <thread>
void keyPress(WORD keyCode)
INPUT input;
input.type = INPUT_KEYBOARD;
input.ki.wScan = keyCode;
input.ki.dwFlags = KEYEVENTF_SCANCODE;
SendInput(1, &input, sizeof(INPUT));
void keyRelease(WORD keyCode)
INPUT input;
input.type = INPUT_KEYBOARD;
input.ki.wScan = keyCode;
input.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(1, &input, sizeof(INPUT));
void CtrlPress()
while (true)
if (GetAsyncKeyState(VK_RBUTTON))
Sleep(1000);
keyPress(0x1D);
Sleep(3000);
keyRelease(0x1D);
else
keyRelease(0x1D);;
int main()
CtrlPress();
本质上,我想要它做的是在我按下鼠标右键后按Ctrl 1000ms,然后按住它3000ms,然后释放它,只要循环鼠标右键被按住。如果松开鼠标右键,我还希望循环立即停止并松开 Ctrl。
但是,代码有问题,因为它会大大降低我的 PC 速度。
【问题讨论】:
在您的问题中,您写道:"However something is wrong with the code as it drastically slows down my PC as is."
-- 仅仅是您的程序没有响应吗?还是其他进程在运行您的程序时也会变慢?
旁注:根据函数GetAsyncKeyState
的官方微软文档,不应该依赖最低有效位的值(即不应该使用它)。它仅用于向后兼容 16 位 Windows。如果您只对最重要的位感兴趣,那么您应该改写GetAsyncKeyState(VK_RBUTTON) & 0x8000
来掩盖其他所有内容。
或者GetAsyncKeyState(VK_RBUTTON) < 0
也可以,因为返回值是有符号的,最高有效位是符号位。
【参考方案1】:
由于您希望在释放鼠标右键时立即释放 Ctrl 键,因此您真的不应该使用 Sleep()
来暂停整个 1 秒/3secs 每次循环迭代的间隔,当鼠标按钮按下时,否则您可能会在释放鼠标按钮后延迟最多 4 秒,然后才能再次执行任何操作。
我会为这样的事情使用状态机,例如:
#include <windows.h>
void keyPress(WORD keyCode)
INPUT input;
input.type = INPUT_KEYBOARD;
input.ki.wScan = keyCode;
input.ki.dwFlags = KEYEVENTF_SCANCODE;
SendInput(1, &input, sizeof(INPUT));
void keyRelease(WORD keyCode)
INPUT input;
input.type = INPUT_KEYBOARD;
input.ki.wScan = keyCode;
input.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(1, &input, sizeof(INPUT));
enum myKeyState IsUp, IsDown, WaitingForPress ;
void CtrlPress()
myKeyState state = IsUp;
DWORD startTime = 0;
while (true)
if (GetAsyncKeyState(VK_RBUTTON) < 0)
switch (state)
case IsUp:
startTime = GetTickCount();
state = WaitingForPress;
break;
case IsDown:
if ((GetTickCount() - startTime) >= 3000)
keyRelease(0x1D);
startTime = GetTickCount();
state = WaitingForPress;
break;
case WaitingForPress:
if ((GetTickCount() - startTime) >= 1000)
keyPress(0x1D);
startTime = GetTickCount();
state = IsDown;
break;
else
if (state == IsDown)
keyRelease(0x1D);
state = IsUp;
Sleep(0); // to avoid CPU throttling
int main()
CtrlPress();
话虽如此,与其使用GetAsyncKeyState()
定期轮询鼠标状态,我建议你让操作系统通知鼠标当你状态变化。在控制台应用程序中,您可以使用SetWindowsHookEx()
安装WH_MOUSE
或WH_MOUSE_LL
挂钩。
【讨论】:
以上是关于SendInput() 的问题的主要内容,如果未能解决你的问题,请参考以下文章
如何正确使用 SendInput() 在 C# 中模拟鼠标输入
时间:2019-04-10 标签:c++win32SendInput()