c++ - 从热键启动时 SendInput 到 Ctrl+C 文本不起作用

标签 c++ winapi sendinput

目前正在使用此代码复制 Windows 10 中当前打开的窗口中的选定文本。如果我在目标程序(记事本)获得焦点时自行运行此代码,则此代码工作正常。记事本中选定的文本被复制到数据变量 OK。

wchar_t title[MAX_PATH];
HWND target_window = GetForegroundWindow();
GetWindowText(target_window, title, MAX_PATH);
std::wcout << "Target window is '" << title << "'" << std::endl;

// Send Control + C
int key_count = 4;

INPUT* input = new INPUT[key_count];
for (int i = 0; i < key_count; i++)
{
    input[i].ki.dwFlags = 0;
    input[i].type = INPUT_KEYBOARD;
}

input[0].ki.wVk = VK_CONTROL;
input[0].ki.wScan = MapVirtualKey(VK_CONTROL, MAPVK_VK_TO_VSC);
input[1].ki.wVk = 0x43; // Virtual key code for 'c'
input[1].ki.wScan = MapVirtualKey(0x43, MAPVK_VK_TO_VSC);
input[2].ki.dwFlags = KEYEVENTF_KEYUP;
input[2].ki.wVk = input[0].ki.wVk;
input[2].ki.wScan = input[0].ki.wScan;

input[3].ki.dwFlags = KEYEVENTF_KEYUP;
input[3].ki.wVk = input[1].ki.wVk;
input[3].ki.wScan = input[1].ki.wScan;

if (!SendInput(key_count, (LPINPUT)input, sizeof(INPUT)))
{
    // TODO: error handling
}
else
{
    // not ideal but not sure of another way to wait for SendInput to complete
    Sleep(100); 
    if (OpenClipboard(NULL))
    {
        HGLOBAL hglb = GetClipboardData(CF_UNICODETEXT);
        LPWSTR lpwstr = (LPWSTR)(GlobalLock(hglb));
        std::wstring data(lpwstr);
        GlobalUnlock(hglb);
        CloseClipboard();
        // do something with selected text in data
    }
    else
    {
        // TODO: error handling
    }
}

但是,如果我通过热键启动完全相同的代码,它就不起作用:

if (RegisterHotKey(
    NULL,
    1,
    MOD_CONTROL | MOD_ALT | MOD_NOREPEAT,
    VK_OEM_2))  // back slash question mark key
{
    std::cout << "Hotkey 'Ctrl+Alt+/' registered, using MOD_NOREPEAT flag\n";
}

MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0) != 0)
{
    if (msg.message == WM_HOTKEY)
    {
        std::cout << "WM_HOTKEY received\n";

        // Call function to COPY TEXT here

        if (RegisterHotKey(
            NULL,
            1,
            MOD_CONTROL | MOD_ALT | MOD_NOREPEAT,
            VK_OEM_2))  // back slash question mark key
        {
            std::cout << "Hotkey 'Ctrl+Alt+/' registered, using MOD_NOREPEAT flag\n";
        }
    }
}

现在,在这两种情况下,GetWindowText() 都显示我要从中复制文本的程序的标题。

此外,我编写了一个简单的测试实用程序来检查 Ctrl+C 是否正在传递给 Window,确实如此。似乎正在传递 Ctrl+C,但没有发生复制。

最佳答案

Alt 是否可能因为热键而仍然关闭,而您实际上正在发送 Ctrl+Alt+C? SendInput 将输入直接插入全局输入队列。

您可以尝试设置一个计时器来响应热键,并在计时器处理程序中调用 GetAsyncKeyState,直到所有修改键都启动,然后再生成输入。

更好的选择是使用 UI Automation而不是像这样的黑客攻击。

关于c++ - 从热键启动时 SendInput 到 Ctrl+C 文本不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45426656/

相关文章:

c# - SendInput Ctrl + C 然后通过 Clipboard.GetText 检索复制的内容不起作用

windows - sendenput API 能否模拟键盘按键在一段时间内被按住?

c++ - 尝试读取和写入字符串时发生访问冲突?

C#、Powershell、未记录的 WinApi 函数 GetFontResourceInfoW

c++ - Win32 消息泵,DispatchMessage() 是处理整个消息队列还是只处理顶部消息?

c# - 以编程方式获取 Win32 旧版控件的工具提示文本

c# - 模拟点击进入隐藏窗口

java - 如何将字符串编码为 8 位 ASCII 字符?

c++ - STM32L011 : Interrupt flag cannot be cleared in Interrupt Handler

c++ - 用 C++ 将视频上传到 ScreenCast.com