-1

I was hoping to get some help with this piece of code.

#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();
}

Essentially, what I want it to do is to press Ctrl 1000ms after I press the right mouse button, and then keep it pressed for 3000ms, and then release it, and loop as long as the right mouse button is held down. I also want the loop to immediately stop and Ctrl to be let go if the right mouse button is let go.

However, something is wrong with the code, as it drastically slows down my PC as-is.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • In your question, you wrote: `"However something is wrong with the code as it drastically slows down my PC as is."` -- Is it only that your program is being unresponsive? Or do other processes also get slow when running your program? – Andreas Wenzel Sep 09 '21 at 13:57
  • 2
    Side note: According to the official Microsoft documentation on the function [`GetAsyncKeyState`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate), the value of the least significant bit should not be relied upon (i.e. it should not be used). It is only provided for backward compatibility with 16-bit Windows. If you are only interested in the most significant bit, then you should mask out everything else by writing `GetAsyncKeyState(VK_RBUTTON) & 0x8000` instead. – Andreas Wenzel Sep 09 '21 at 14:03
  • 1
    Or `GetAsyncKeyState(VK_RBUTTON) < 0` would work, too, since the return value is signed, and the most significant bit is the sign bit. – Remy Lebeau Sep 09 '21 at 17:00

1 Answers1

1

Since you want the Ctrl key to be released immediately when the right mouse button is released, you really shouldn't be using Sleep() to pause the entire 1sec/3secs intervals on each loop iteration while the mouse button is down, otherwise you risk delaying up to 4secs after the mouse button is released before you can do anything again.

I would use a state machine for something like this, eg:

#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();
}

That being said, rather than using GetAsyncKeyState() to poll the mouse status at regular intervals, I would instead suggest you ask the OS to notify you when the mouse status changes. In a console app, you can use SetWindowsHookEx() to install a WH_MOUSE or WH_MOUSE_LL hook for that purpose.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770