How to build the value of WM_CHAR vkCode for non alpha characters?

Viewed 69

How to build the vkCode value of WM_CHAR lParam for non-alpha characters !@#$%¨&*()-= etc?

test("a#b@c&d*ef-g+!h", hWnd);

struct extraKeyInfo
{
    unsigned short repeatCount = 1;
    unsigned char scanCode;
    bool extendedKey = 0; 
    bool contextCode = 0; 
    bool prevKeyState = 0;
    bool transitionState = 0;
    operator unsigned int()
    {
        return repeatCount | (scanCode << 16) | (extendedKey << 24) | (contextCode << 29) |
            (prevKeyState << 30) | (transitionState << 31);
    }
};

void test(const char* str, HWND hWnd)
{

    extraKeyInfo lParam = {};

    for (int i = 0; i < strlen(str); i++)
    {
        short vkCode = LOBYTE(VkKeyScan(str[i]));
    
        // vkCode 32 = space.
        if ((!isalpha(str[i])) && (vkCode != 32))
            vkCode << 19; /* <= my doubt lies here */

        lParam.scanCode = MapVirtualKey(vkCode, MAPVK_VK_TO_VSC);
        PostMessage(hWnd, WM_CHAR, vkCode, lParam);
    }

    return;
}
1 Answers

You can use the Win32 API call VkKeyScanEx to convert a character value to a virtual key code. Note however that virtual key codes identify keys so they depend on keyboard layout and there is not a one-to-one correspondence between printable characters and key codes because multiple characters may be associated with the same key but distinguished via shift state.

#include <Windows.h>
#include <iostream>

short get_virtual_key_code(char ch) {
    auto key_code = VkKeyScanExA(ch, 0);
    return LOBYTE(key_code); // high byte contains modifier flags e.g. shift etc.
}

int main() {
    std::cout << "A => " << std::hex << get_virtual_key_code('A') << "\n"; // 0x41
    std::cout << "a => " << std::hex << get_virtual_key_code('a') << "\n"; // 0x41 again, same key code different flags 
    std::cout << "/ => " << std::hex << get_virtual_key_code('/') << "\n"; // typically 0xBF on US keyboards.
    return 0;
}
Related