从热键启动时 SendInput 到 Ctrl+C 文本不起作用
SendInput to Ctrl+C text Doesn't Work When Launched from Hotkey
目前正在使用此代码在 Windows 10 中复制当前打开的 Window 中的选定文本。如果我 运行 在我的目标程序之前,此代码可以正常工作(记事本)有焦点。记事本中选中的文本被复制到数据变量中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 而不是像这样的 hack。
目前正在使用此代码在 Windows 10 中复制当前打开的 Window 中的选定文本。如果我 运行 在我的目标程序之前,此代码可以正常工作(记事本)有焦点。记事本中选中的文本被复制到数据变量中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 而不是像这样的 hack。