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) &amp; 0x8000 来掩盖其他所有内容。 或者GetAsyncKeyState(VK_RBUTTON) &lt; 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_MOUSEWH_MOUSE_LL 挂钩。

【讨论】:

以上是关于SendInput() 的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何正确使用 SendInput() 在 C# 中模拟鼠标输入

时间:2019-04-10 标签:c++win32SendInput()

SendInput 无法将回车键发送到特定程序

在 Node-FFI 中使用 SendInput

如何在 AutoHotkey 中的 SendInput 命令之间添加延迟?

在多显示器环境中计算 SendInput() 的归一化坐标