windowsvisual-studiowinapivisual-c++sendinput

SendInput() malfunctions in Notepad


I've implemented a hook procedure that catches some Alt+letter key combinations and injects predefined strings. An example of a hook procedure is shown below. It detects the hotkeys LeftAlt+Q and LeftAlt+A and injects the string ABCD1234 in both cases, using the WinAPI function SendInput().

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

void DisplayString()
{
    INPUT in[24] = { 0 };
    int i;
    for (i = 0; i < ARRAYSIZE(in); i++) in[i].type = INPUT_KEYBOARD;
    i = 0;
    in[i++].ki.wVk = VK_CONTROL;    // CTRL
    in[i].ki.wVk = VK_CONTROL;      // CTRL Up
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i].ki.wVk = VK_LMENU;        // LeftAlt Up
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i++].ki.wVk = VK_LSHIFT;     // LeftShift down
    in[i++].ki.wVk = 'A';
    in[i].ki.wVk = 'A';
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i++].ki.wVk = 'B';
    in[i].ki.wVk = 'B';
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i++].ki.wVk = 'C';
    in[i].ki.wVk = 'C';
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i++].ki.wVk = 'D';
    in[i].ki.wVk = 'D';
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i].ki.wVk = VK_LSHIFT;    // LeftShift Up
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i++].ki.wVk = '1';
    in[i].ki.wVk = '1';
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i++].ki.wVk = '2';
    in[i].ki.wVk = '2';
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i++].ki.wVk = '3';
    in[i].ki.wVk = '3';
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i++].ki.wVk = '4';
    in[i].ki.wVk = '4';
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    in[i++].ki.wVk = VK_CONTROL;    // CTRL
    in[i++].ki.wVk = VK_LMENU;      // LeftAlt Down
    in[i].ki.wVk = VK_CONTROL;      // CTRL Up
    in[i++].ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(ARRAYSIZE(in), in, sizeof(INPUT));
}

HHOOK hHook{ NULL };

#define     VK_HOT_1        0x51
#define     VK_HOT_2        0x41

extern "C" __declspec(dllexport)
LRESULT CALLBACK KeyboardHookProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (code < 0) return CallNextHookEx(hHook, code, wParam, lParam);

    // If LeftAlt pressed
    if (wParam == WM_SYSKEYDOWN && (GetAsyncKeyState(VK_LMENU) & 0x80000000))
    {
        DWORD vkCode = ((KBDLLHOOKSTRUCT*)lParam)->vkCode;  // virtual-key code
        if (vkCode == VK_HOT_1 || vkCode == VK_HOT_2)
        {
            DisplayString();
            return 1;
        }
    }
    return CallNextHookEx(hHook, code, wParam, lParam);
}

The hook procedure is installed using the function SetWindowsHookExW().

The program works as expected in a broad range of applications. I've tested it with WordPad, Notepad++, Chrome, Edge, Command Prompt, PowerShell, and Visual Studio. However, the program exhibits unexplained behavior when the string is injected into Notepad. Only 2-4 characters come up, and the rest appear when additional keys are pressed on the keyboard, with a couple of characters following each key down.

This behavior is new. I used Notepad to test this program during development some weeks ago, and Notepad worked fine. I'm using this program on several PCs, and some work problem-free. All the PCs use Windows 11.

EDIT: AutoHotkey is an advanced Windows app for implementing user-defined hotkeys. The user configures the key combinations to use, and the action to perform when a hotkey is pressed. I've configured AutoHotkey for the same hotkeys and actions as in my application and tested it on a Windows 11 PC. AutoHotkey's behavior is the same as that of my application: injecting text works fine in all tested apps but Notepad.

Moreover, the behavior I observe now is different. The whole string comes out intermittently, two characters at a time, seemingly at the rate of cursor blinks.


Solution

  • I find that if I turn off the Autocorrect setting in Notepad then all my SendInput text appears.

    It seems that if the text you send creates a spelling error (to which Notepad will put a red squiggly line), then autocorrect will interrupt the input stream and not all the text will be sent to the window.

    I'm using Notepad v11.2410.21.0.

    I've registered a Microsoft Feedback issue here: https://aka.ms/AAums69

    Update

    In Notepad it also appears that the spellcheck will interrupt the input stream. i.e. To allow SendInput to work in Notepad both spellcheck and autocorrect need to be turned off.