0

I want to use a std::string for the SendInput() function.

After doing some research, I found that the VkKeyScanEx might help but the code needs additional logic for uppercase or special characters. In the latter case I realized that I can simulate a SHIFT key press, send the lowercase key input and then it would come out as uppercase. However, there are also the "special" characters like !"§$%&/()=? which need a held down SHIFT key to come out correctly. Furthermore, there are also the umlauts like äüö. My code below works but the umlauts are also capitalized which is wrong for example (because isalnum() returns true for those as well). Isn't there a reasonable way of handling any string input and simulating it via the user's keyboard regardless of region, language and so on without causing such a logical mess? Isn't there a simpler and foolproof way to do this?

const auto key_board_layout = GetKeyboardLayout(0);

void configure_input(INPUT& input)
{
    input.type = INPUT_KEYBOARD;
    input.ki.wScan = 0;
    input.ki.time = 0;
    input.ki.dwExtraInfo = 0;
    input.ki.dwFlags = 0;
}

void send_input(const HWND window_handle, const std::string& message)
{
    SetForegroundWindow(window_handle);
    std::locale::global(std::locale("")); // Needed to not crash on certain special characters      

    for (auto character : message)
    {
        INPUT key_input;
        configure_input(key_input);

        INPUT shift_input;
        configure_input(shift_input);
        shift_input.ki.wVk = VK_SHIFT;

        // Type the key
        const auto virtual_key = VkKeyScanEx(character, key_board_layout);
        key_input.ki.wVk = virtual_key;
        const auto is_shift_key_required = isupper(character) || !isalnum(character);
        if(is_shift_key_required)
        {
            // Hold down the shift key
            SendInput(1, &shift_input, sizeof(INPUT));
        }
        SendInput(1, &key_input, sizeof(INPUT));

        // Release the key
        key_input.ki.dwFlags = KEYEVENTF_KEYUP;
        SendInput(1, &key_input, sizeof(INPUT));

        if(is_shift_key_required)
        {
            // Release the shift key
            shift_input.ki.dwFlags = KEYEVENTF_KEYUP;
            SendInput(1, &shift_input, sizeof(INPUT));
        }
    }
}
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • 1
    How about using `KEYEVENTF_UNICODE`. Also, you must not call `SendInput` one event at a time. Assemble all the events into an array, and send them in a single atomic call to `SendInput`. After all, that is pretty much the entire reason for the existence of `SendInput`. – David Heffernan Jan 22 '20 at 16:38
  • 1
    See [my answer](https://stackoverflow.com/a/38625599/65863) to [this question](https://stackoverflow.com/questions/38622583/), and [my answer](https://stackoverflow.com/a/31307429/65863) to [this question](https://stackoverflow.com/questions/31305404/), for code examples of using `SendInput()` with `KEYEVENTF_UNICODE` and `std::wstring` – Remy Lebeau Jan 22 '20 at 17:40
  • Thanks to both of you. @RemyLebeau: Your answer https://stackoverflow.com/a/38625599/3764804 worked. :) – BullyWiiPlaza Jan 22 '20 at 19:50
  • 1
    The combination of `SetForegroundWindow` and `SendInput` usually means, you should be using [UI Automation](https://learn.microsoft.com/en-us/windows/win32/winauto/entry-uiauto-win32) instead. – IInspectable Jan 22 '20 at 20:42

0 Answers0