2017-07-31 63 views
0

当前使用此代码在Windows 10当前打开的窗口中复制选定的文本。如果我自己运行它的目标程序时,此代码工作正常(记事本)有焦点。记事本中选定的文本被复制到数据变量OK中。发送输入到Ctrl + C文本从热键启动时不起作用

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正在通过,但副本没有发生。

+1

你的第一个代码片段中的注释表明你想处理刚刚复制到剪贴板的数据。如果是这种情况,那么将数据复制到剪贴板是不合适的。用户可能不希望甚至不了解这一事实,即程序中的某些操作会破坏它们的剪贴板数据。 – IInspectable

+0

我很清楚这一点;剪贴板将在最终程序中备份和恢复。如果有另一种方式从任何程序中抓取文本而不使用剪贴板,那么这将是可取的。然而,从我发现的其他方法直接抓取文本不能在所有程序中一致地工作。 –

+0

为什么不直接发送'WM_GETTEXT'到前台窗口的活动输入控件?看['GetGUIThreadInfo()'](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633506.aspx)找到该控件。 –

回答

1

难道Alt键仍然向下,因为热键和你实际发送按Ctrl + Alt键+ÇSendInput将输入直接插入全局输入队列。

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

更好的选择是使用UI Automation而不是像这样的破解。

+0

GetAsyncKeyState检查所有修改键是否解决了问题。我还将研究UI自动化框架,但是担心它可能无法与我需要集成的某些第三方应用程序一起使用。 –

相关问题