Converting Keycode to localized input code

Godot Version

4.3

Question

Using C++, how do I convert the get_keycode_with_modifiers() returned keycode value to a localized code?

I would like to create a chat window which requires localization support.

Copilot gave me totally false answers, I hope someone is able to help me out here.

I am aware that the get_key_label() method returns the localization dependent label, but it ignores the SHIFT/ALT modifiers for alternative characters and there is no way to know for me how to alter the label when also the ALT/SHIFT key is pressed.

Thanks in advance & much appreciated! Devs you rock!

const InputEventKey* key_event = Object::cast_to<const InputEventKey>(*event);

if (key_event->is_pressed()) {
  Key k = DisplayServer::get_singleton()->keyboard_get_label_from_physical(key_event->get_physical_keycode_with_modifiers());

  printf("%c", (int)k);
}

This is my test code which doesn’t obey SHIFT/ALT flags.

Copilot generated code below works quite well, so there must be something going on in Godot’s DisplayServerWindows::_process_key_events() method that does end up ignoring (masking away) modifiers.

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    static BYTE keyboardState[256];
    static WCHAR buffer[16];
    HKL keyboardLayout = GetKeyboardLayout(0);

    switch (uMsg) {
        case WM_KEYDOWN: {
            // Get the virtual key code
            UINT virtualKey = wParam;
            // Get the scan code
            UINT scanCode = (lParam & 0x00FF0000) >> 16;

            GetKeyboardState(keyboardState);

            // Translate the virtual key code to a Unicode string
            int result = ToUnicodeEx(virtualKey, scanCode, keyboardState, buffer, sizeof(buffer) / sizeof(buffer[0]), 0, keyboardLayout);
            if (result > 0) {
                buffer[result] = '\0'; // Null-terminate the string
                std::cout << static_cast<char>(buffer[0]) << std::endl;
            }
            return 0;
        }
        case WM_DESTROY: {
            PostQuitMessage(0);
            return 0;
        }
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}