2017-07-31 66 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自動化框架,但是擔心它可能無法與我需要集成的某些第三方應用程序一起使用。 –

相關問題