【问题标题】:Issues with SendInput()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 也可以,因为返回值是有符号的,最高有效位是符号位。

标签: c++ winapi sendinput


【解决方案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 挂钩。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 2011-10-13
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 2012-11-12
    相关资源
    最近更新 更多