Dacul
Dacul

Reputation: 33

C++ loop simulate keypress while key is pressed

I am trying to get a small app that will continuously simulate UP (↑ arrow key) while another key is pressed, in my case Right CTRL.

The code I wrote however, will only send one UP for each press - and while I keep Right CTRL pressed, it will only send one UP and stop.

I want to mention that this code is built entirely from documentation I found online, I have never written anything in C++ ever before, or any other language so any suggestions would greatly help me. I initially tried doing this while CAPS LOCK was active, but I found that getting the key state (on/off) did not work for me at all, no matter what I tried.

int main()
{
  // This structure will be used to create the keyboard
  // input event.
  INPUT ip;

  // Pause for 1 seconds.
  Sleep(1000);

  // Set up a generic keyboard event.
  ip.type = INPUT_KEYBOARD;
  ip.ki.wScan = 0; // hardware scan code for key
  ip.ki.time = 0;
  ip.ki.dwExtraInfo = 0;

  while(1){
      if(GetAsyncKeyState(VK_RCONTROL))
      {
            // Press the "UP arrow" key
            ip.ki.wVk = 0x26; // virtual-key code for the "UP arrow" key
            ip.ki.dwFlags = 0; // 0 for key press
            SendInput(1, &ip, sizeof(INPUT));

            Sleep(50);

            // Release the "UP arrow" key
            ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
            SendInput(1, &ip, sizeof(INPUT));

            Sleep(50);
      }
  }

  // Exit normally
  return 0;
}  

Upvotes: 3

Views: 2257

Answers (1)

AndyG
AndyG

Reputation: 41220

GetAsyncKeyState does not return a boolean about whether the key is up or down, but rather a SHORT (a 16 bit integer, usually literally short)

If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.

So what does this mean? The "most significant bit" in hardware is implementation defined (Which end of a bit field is the most significant bit?), but we can treat everything as if the "leftmost" bit is significant (1000 versus 0001).

So we can test for keydown with a bitmask.

I've written a small demo program to help you visualize all this:

std::cout << "number of bytes in a short: " << sizeof(short) << std::endl;
short i = 0;
i = 1 << (sizeof(short)*8-1); // use bit shifting to set most significant bit
std::cout << "Initial value of i: " << i << std::endl;
std::cout << "Initial value of i as hex: " << std::hex << i << std::endl;
std::cout << "Is most significant bit set?\n";
short bitmask = 0x8000;
std::cout << std::boolalpha << ((bitmask & i) != 0) << std::endl;
std::cout << "Unsetting MSB\n";
i = 0x0000;
std::cout << "Is most significant bit set?\n";
std::cout << std::boolalpha << ((bitmask & i) != 0) << std::endl;

This demo shows how you can apply a bitmask to a short to ask if the most significant bit is set.

GetAsyncKeyState gives you the additional ability to check if the key was pressed since last check. For a simpler call, check out GetKeyState

Upvotes: 1

Related Questions