Search code examples
cwindowsapieventskeyboard

C keyboard events


This is my first time programming in Windows API with C. I made this simple program that takes a string and types it again on your computer. I think this could be implemented better because I have a lot of if and else if statements. My question is: Is this a good way to build a program like this? Is there a better way of doing the same?

#include <stdio.h>
#include <windows.h>

void keyboard(char *str)
{
    int x = strlen(str);

    INPUT inputStruct[x];
    ZeroMemory(inputStruct, sizeof(inputStruct));

    for (int i = 0; i < x; i++)
    {
        inputStruct[i].type = 1;

        if (str[i] == 'a')
            inputStruct[i].ki.wVk = 0x41;
        else if (str[i] == 'b')
            inputStruct[i].ki.wVk = 0x42;
        else if (str[i] == 'c')
            inputStruct[i].ki.wVk = 0x43;
        else if (str[i] == 'd')
            inputStruct[i].ki.wVk = 0x44;
        else if (str[i] == 'e')
            inputStruct[i].ki.wVk = 0x45;
        else if (str[i] == 'f')
            inputStruct[i].ki.wVk = 0x46;
        else if (str[i] == 'g')
            inputStruct[i].ki.wVk = 0x47;
        else if (str[i] == 'h')
            inputStruct[i].ki.wVk = 0x48;
        else if (str[i] == 'i')
            inputStruct[i].ki.wVk = 0x49;
        else if (str[i] == 'j')
            inputStruct[i].ki.wVk = 0x4A;
        else if (str[i] == 'k')
            inputStruct[i].ki.wVk = 0x4B;
        else if (str[i] == 'l')
            inputStruct[i].ki.wVk = 0x4C;
        else if (str[i] == 'm')
            inputStruct[i].ki.wVk = 0x4D;
        else if (str[i] == 'n')
            inputStruct[i].ki.wVk = 0x4E;
        else if (str[i] == 'o')
            inputStruct[i].ki.wVk = 0x4F;
        else if (str[i] == 'p')
            inputStruct[i].ki.wVk = 0x50;
        else if (str[i] == 'q')
            inputStruct[i].ki.wVk = 0x51;
        else if (str[i] == 'r')
            inputStruct[i].ki.wVk = 0x52;
        else if (str[i] == 's')
            inputStruct[i].ki.wVk = 0x53;
        else if (str[i] == 't')
            inputStruct[i].ki.wVk = 0x54;
        else if (str[i] == 'u')
            inputStruct[i].ki.wVk = 0x55;
        else if (str[i] == 'v')
            inputStruct[i].ki.wVk = 0x56;
        else if (str[i] == 'w')
            inputStruct[i].ki.wVk = 0x57;
        else if (str[i] == 'x')
            inputStruct[i].ki.wVk = 0x58;
        else if (str[i] == 'y')
            inputStruct[i].ki.wVk = 0x59;
        else if (str[i] == 'z')
            inputStruct[i].ki.wVk = 0x5A;
        else if (str[i] == ' ')
            inputStruct[i].ki.wVk = 0x20;
    }

    SendInput(x, inputStruct, sizeof(INPUT));
}

int main()
{
    keyboard("this is my test program");
}

Solution

  • You can use

    VkKeyScan
    

    in order to translate your char to virtual key code

    so just try

    inputStruct[i].ki.wVk = VkKeyScan(str[i]);
    

    instead of bunch of if clauses like the one below

    if (str[i] == ' ')
        inputStruct[i].ki.wVk = 0x20
    

    so final code will look like below

    for (int i = 0; i < x; i++)
    {
        inputStruct[i].type = 1;
        inputStruct[i].ki.wVk = VkKeyScan(str[i]);
    }
    

    You can press shift before sending key then send keys as you wish to be pressed as capitals

    Below code is the demo for your second purpose

    INPUT inputs[4] = { 0 };
    ZeroMemory(inputs, sizeof(inputs));
    
    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = VK_LSHIFT;
    
    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = VkKeyScan(L'a');
    
    inputs[2].type = INPUT_KEYBOARD;
    inputs[2].ki.wVk = VkKeyScan(L'a');
    inputs[2].ki.dwFlags = KEYEVENTF_KEYUP;
    
    inputs[3].type = INPUT_KEYBOARD;
    inputs[3].ki.wVk = VK_LSHIFT;
    inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;
    
    UINT uSent = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));