0

I am creating a personal project to help me press keybinds using a custom GUI. In order to do so, I have a DearImGui frame running within an external window as an independent app.

When I press the button, the app simulates a keypress for each of the keys in the keybind. However, there seems to be an issue while sending the control, shift, and alt keys. I've been struggling with this for over a day now, and just now realized the issue was probably a security measure within Windows. I believe Windows is preventing me from simulating key presses on the control, shift, and alt keys as a preventative against malware that may pretend to be a human.

I decided to include very minimalistic examples since I believe the problem originated from windows and was not an error in my programming.

This example successfully presses F8:

if (ImGui::Button("Button 1", ImVec2(334, 30)))
{
    keybd_event(0x77, 0, 0, 0); //Press down the Key
    keybd_event(0x77, 0, KEYEVENTF_KEYUP, 0); //Release the Key
}

While this one should send the combo CTRL + F1, but only registers F1:

if (ImGui::Button("Button 2", ImVec2(334, 30)))
{
    keybd_event(0x70, 0, 0, 0); //Press down the Key
    keybd_event(VK_CONTROL, 0, 0, 0); //Press down the Key
    keybd_event(0x70, 0, KEYEVENTF_KEYUP, 0); //Release the Key
    keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); //Release the Key
}

Note: all other keys seem to work fine, and I have also tried only sending a ctrl key on its own to see if this was a "you can only do one at a time" problem(it was not.)

  • 1
    `keybd_event()` has been deprecated for a very long time, and really isn't well-suited for multi-key input. You should be using `SendInput()` instead, giving it an array of all of the events you want to inject at one time. – Remy Lebeau Jun 22 '22 at 00:28
  • @RemyLebeau I copied this code from another post: ```c++ INPUT ip; ip.type = INPUT_KEYBOARD; ip.ki.wScan = 0; ip.ki.time = 0; ip.ki.dwExtraInfo = 0; ip.ki.wVk = 0x41; ip.ki.dwFlags = 0; // 0 for key press SendInput(1, &ip, sizeof(INPUT)); ip.ki.dwFlags = KEYEVENTF_KEYUP; SendInput(1, &ip, sizeof(INPUT)); ``` How can I put an array into this? It currently only outputs the "a" key. How would I make it read from an array so I can have more than one key down at once? have never used this function before and I'm somewhat new, so I'd appreciate an example of just putting an array in. – TheGamingDolpghin Jun 22 '22 at 01:11
  • 2
    Wrong order, the CTRL key has to go down first. Just like you'd press it on the keyboard. – Hans Passant Jun 22 '22 at 01:19
  • @TheGamingDolpghin "*I copied this code from another post*" - see [Is it a bug to pass a single-element array to SendInput?](https://stackoverflow.com/questions/46744894/) "*How can I put an array into this?*" - like this: `INPUT ips[2] = {}; ip[0].type = INPUT_KEYBOARD; ip[0].ki.wVk = 0x41; ips[1] = ips[0]; ips[1].ki.dwFlags = KEYEVENTF_KEYUP; SendInput(2, ips, sizeof(INPUT));` Expand the array for more events as needed. But did you read the [documentation](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput) yet? It also has an example of an array. – Remy Lebeau Jun 22 '22 at 01:48
  • Thanks, both of you, but @HansPassant was right. I was over-confident in my program and didn't double-check in-depth enough to notice the keys were being registered in the wrong order. I'll still be learning ```SendInput()``` because it might be useful in the future and it's not too complicated from what I've seen so far. – TheGamingDolpghin Jun 22 '22 at 01:52
  • The only thing you can't emulate is Ctrl+Alt+Del – Anders Jun 22 '22 at 16:05

1 Answers1

0

You are "pressing down" the keys in the wrong order. You need to "press" down the Ctrl key before the F1 key.

if (ImGui::Button("Button 2", ImVec2(334, 30)))
{
    keybd_event(VK_CONTROL, 0, 0, 0); //Press down the Key
    keybd_event(VK_F1, 0, 0, 0); //Press down the Key
    keybd_event(VK_F1, 0, KEYEVENTF_KEYUP, 0); //Release the Key
    keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); //Release the Key
}

That being said, keybd_event() is deprecated, please use SendInput() instead, eg:

if (ImGui::Button("Button 2", ImVec2(334, 30)))
{
    INPUT ips[4] = {};

    ips[0].type = INPUT_KEYBOARD;
    ips[0].ki.wVk = VK_CONTROL;

    ips[1] = ip[0];
    ips[1].ki.wVk = VK_F1;

    ips[2] = ip[1];
    ips[2].ki.dwFlags = KEYEVENTF_KEYUP;

    ips[3] = ips[0];
    ips[3].ki.dwFlags = KEYEVENTF_KEYUP;

    SendInput(4, ips, sizeof(INPUT));
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770