SendInput() 的问题

Issues with SendInput()

我希望在这段代码中得到一些帮助。

#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 会松开。

但是,代码有问题,因为它原样大大降低了我的电脑速度。

因为您希望 Ctrl 键在释放鼠标右键时立即释放,所以您真的不应该使用Sleep() 在按下鼠标按钮时在每次循环迭代中暂停整个 1 秒/3 秒间隔,否则您可能会在松开鼠标按钮后最多延迟 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() 定期轮询 鼠标状态,我建议您使用 OS 来 通知 当鼠标状态改变时。在控制台应用程序中,您可以使用 SetWindowsHookEx() 为此目的安装 WH_MOUSEWH_MOUSE_LL 挂钩。