Deathface
Deathface

Reputation: 1

Simulate double direct keyboard input in C++

I found this c++ script that let you simulate a direct keyboard input, however, I need to simulate two inputs like [Ctrl + A]. I've been looking for ways to make it but I can't find the answer, if someone could help me or give me a clue I'd be grateful.

#include "stdafx.h"
#pragma comment(lib,"user32")
using namespace std;

int main()
{
    char ch = 'a';
    INPUT key;
    memset(&key,0,sizeof(INPUT));//Zero the structure.
    key.type = INPUT_KEYBOARD;
    key.ki.dwExtraInfo = GetMessageExtraInfo();//<-- you will need to pinvoke this too.
    key.ki.wScan = 
        static_cast<WORD>(MapVirtualKeyEx(VkKeyScanA(ch), MAPVK_VK_TO_VSC, GetKeyboardLayout(0)));//more pinvoking
    key.ki.dwFlags = KEYEVENTF_SCANCODE;//<-- you will probably have to declare this constant somewhere-
    //in your C# program.

    //Ready to send the key-down event.
    SendInput(1, &key, sizeof(INPUT));

    Sleep(1000);//Wait one second before sending key-up.

    //Sending key-up.
    key.ki.dwExtraInfo = GetMessageExtraInfo();
    key.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;//Key-up need be defined too, or just use the value.
    SendInput(1, &key, sizeof(INPUT));
}

I've written this code, Ctrl press isn't working, however, 'W' press does.

int main()
{
    Sleep(2000); 
    INPUT ip;
    char key1 = VK_CONTROL, key2 = 'w';

    ip.type = INPUT_KEYBOARD;
    ip.ki.wScan = 0; // hardware scan code for key
    ip.ki.time = 0;
    ip.ki.dwExtraInfo = 0;

    ip.ki.wScan = key1;
    ip.ki.dwFlags = 0; // 0 for key press
    SendInput(1, &ip, sizeof(INPUT));

    // Press  key2
    ip.ki.wScan = key2;
    ip.ki.dwFlags = 0; // 0 for key press
    SendInput(1, &ip, sizeof(INPUT));

    // Release key2
    ip.ki.wScan = key2;
    ip.ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(1, &ip, sizeof(INPUT));

    // Release key1
    ip.ki.wScan = key1;
    ip.ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(1, &ip, sizeof(INPUT));
}

I've noticed if I delete the VK_CONTROL press lines, 'W' press doesn't work neither.

int main() {
    Sleep(2000);
    INPUT ip;
    char key2 = 'w';

    ip.type = INPUT_KEYBOARD;
    ip.ki.wScan = 0; // hardware scan code for key
    ip.ki.time = 0;
    ip.ki.dwExtraInfo = 0;

    // Press  key2
    ip.ki.wScan = key2;
    ip.ki.dwFlags = 0; // 0 for key press
    SendInput(1, &ip, sizeof(INPUT));

    // Release key2
    ip.ki.wScan = key2;
    ip.ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(1, &ip, sizeof(INPUT));
}

Upvotes: 0

Views: 501

Answers (2)

CWilson
CWilson

Reputation: 435

You are sending virtual codes to the scan code parameter. The scan code for w is not 'w'.

In scan code set 1 (US keyboards), w's scan code is 0x11, and left control's scan code is 0x1D. Microsoft's Keyboard Scan Code Specification details sets 1 and 2, and can be found at https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc. There are commonly 3 sets of scan codes, and they are enumerated various places on the web. Or, you can use a utility to capture your own keyboard's scan codes. Sharpkeys or AutoHotkey appear to be popular utilities for doing just this.

Upvotes: 0

rsjaffe
rsjaffe

Reputation: 5730

To send a ctrl-a, you need to send, in order:

key-down events
VK_CONTROL
virtual code for a

key-up events
virtual code for a
VK_CONTROL

so, using VkKeyScanExW to get the virtual scan code for 'a'

key.ki.wVk = VK_CONTROL;
/* send keystroke */
key.ki.wVk = /* the virtual key code for a that you derived */
/* send keystroke */
/* set flag to keyup */
key.ki.wVk = /* Virtual code for a */
/* send keystroke */
key.ki.wVk = VK_CONTROL;
/* send keystroke */

where VK_CONTROL is the macro defined in Windows that gives you the keyboard virtual code for ctrl. Leave wScan set to 0.

Upvotes: 1

Related Questions