2010-02-12 7 views
17

내 앱. 시스템에서 실행 중이며 단축키를 모니터링합니다. 사용자가 임의의 창에서 텍스트를 선택하고 단축키를 누르면 WM_HOTKEY 메시지를받을 때 선택한 텍스트를 얻는 방법은 무엇입니까? 기본 Win32 API를 사용하여 포커스가있는 창에서 선택한 텍스트를 가져 오는 방법은 무엇입니까?

내가 활성 창 ( GetActiveWindow())와 forground에는 창 ( GetForegroundWindow())에 keybd_event()SendInput()를 사용하여 Ctrl + C를 보내는 시도, 클립 보드에 텍스트를 캡처하려면, 이들 사이에서 조합을 시도했다. 모두 헛된 것. 일반 Win32 시스템 API를 사용하여 Windows에서 초점을 맞춘 창의 선택한 텍스트를 가져올 수 있습니까?

+1

올바른 창 핸들을 얻고 있습니까? 이것을 Spy ++로 테스트 할 수 있습니다. 또한 오래된 WM_GETTEXT를 시도해 보셨습니까? – Luke

+0

어떤 Windows 버전입니까? –

+0

@Aaron : Windows XP 이상; 32 및 64 비트 모두; 기본적으로 내 응용 프로그램 (http://artha.sourceforge.net/)을 Windows로 이식하는 중이므로 계속 진행하려면이 기능이 필요합니다. – legends2k

답변

19

TL : 그렇습니다. 일반 Win32 시스템 API를 사용하여이를 수행하는 방법이 있지만 올바르게 구현하는 것은 어렵습니다.

WM_COPY 및 WM_GETTEXT가 작동하지만 모든 경우에 적용되지는 않습니다. 요청을 올바르게 처리하는 수신 창에 따라 다르며 대부분의 경우 그렇지 않습니다. 이 작업을 수행 할 수있는 한 가지 방법을 찾아 보겠습니다. 원하는만큼 간단한 것은 아니지만 win32 프로그래밍의 모험이 가득한 세상은 무엇입니까? 준비된? 승인. 가자.

먼저 대상 창의 HWND id를 가져와야합니다. 이렇게하는 방법은 여러 가지가 있습니다. 그러한 접근법 중 하나는 앞에서 언급 한 것과 같습니다 : 전경 창을 가져온 다음 초점이있는 창을 얻습니다. 그러나 많은 사람들이 잊어 버리는 하나의 거대한 잡았다가 있습니다. 전경 창이 나타나면 AttachThreadInput 여야합니다. 그렇지 않으면 GetFocus()은 단순히 NULL을 반환합니다.

훨씬 쉬운 방법이 있습니다. GUITREADINFO 기능을 사용하면됩니다. 입력 된 스레드를 다른 프로그램에 연결하는 것과 관련된 모든 숨겨진 위험을 피할 수 있으므로 훨씬 안전합니다. 텍스트가 조금 더 복잡 복사 할 키 입력을 보내기

LPGUITHREADINFO lpgui = NULL; 
HWND target_window = NULL; 

if(GetGUIThreadInfo(NULL, lpgui)) 
    target_window = lpgui->hwndFocus; 
else 
{ 
    // You can get more information on why the function failed by calling 
    // the win32 function, GetLastError(). 
} 

...

우리가 가장 중요하게, 더 빨리 때문에 대신 keybd_event의 SendInput을 사용하려고하고있는가에 의해 엉망이 될 수 없다 동시 사용자 입력 또는 키 스트로크를 시뮬레이트하는 다른 프로그램.

이것은 프로그램이 Windows XP 이상에서 실행되어야 함을 의미합니다. 그러나 실행중인 98!

// We're sending two keys CONTROL and 'V'. Since keydown and keyup are two 
// seperate messages, we multiply that number by two. 
int key_count = 4; 

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

input[0].wVK = VK_CONTROL; 
input[0].wScan = MapVirtualKey(VK_CONTROL, MAPVK_VK_TO_VSC); 
input[1].wVK = 0x56 // Virtual key code for 'v' 
input[1].wScan = MapVirtualKey(0x56, MAPVK_VK_TO_VSC); 
input[2].dwFlags = KEYEVENTF_KEYUP; 
input[2].wVK = input[0].wVK; 
input[2].wScan = input[0].wScan; 
input[3].dwFlags = KEYEVENTF_KEYUP; 
input[3].wVK = input[1].wVK; 
input[3].wScan = input[1].wScan; 

if(!SendInput(key_count, (LPINPUT)input, sizeof(INPUT))) 
{ 
    // You can get more information on why this function failed by calling 
    // the win32 function, GetLastError(). 
} 

있습니다. 그렇게 나쁘지 않았지, 그렇지?

이제 우리는 클립 보드에있는 것을 들여다보기 만하면됩니다. 이것은 처음 생각했던 것처럼 간단하지 않습니다. "클립 보드"는 실제로 동일한 것을 여러 번 표현할 수 있습니다. 클립 보드에 복사 할 때 활성화되는 응용 프로그램은 을 정확히 무엇을 제어할지 클립 보드에 있습니다.

예를 들어 Microsoft Office에서 텍스트를 복사하면 클립 보드에 동일한 텍스트의 일반 텍스트 표현과 함께 RTF 데이터가 저장됩니다. 그렇게하면 워드 패드와 메모장에 붙여 넣을 수 있습니다. 워드 패드는 서식있는 텍스트 형식을 사용하고 메모장은 일반 텍스트 형식을 사용합니다.

이 간단한 예제에서는 우리가 평문에만 관심이 있다고 가정 해 보겠습니다.

if(OpenClipboard(NULL)) 
{ 
    // Optionally you may want to change CF_TEXT below to CF_UNICODE. 
    // Play around with it, and check out all the standard formats at: 
    // http://msdn.microsoft.com/en-us/library/ms649013(VS.85).aspx 
    HGLOBAL hglb = GetClipboardData(CF_TEXT); 
    LPSTR lpstr = GlobalLock(hglb); 

    // Copy lpstr, then do whatever you want with the copy. 

    GlobalUnlock(hglb); 
    CloseClipboard(); 
} 
else 
{ 
    // You know the drill by now. Check GetLastError() to find out what 
    // went wrong. :) 
} 

그리고 거기에 있습니다! lpstr을 사용하고자하는 변수에 복사하고 lpstr을 직접 사용하지 마십시오. 클립 보드를 닫기 전에 클립 보드의 내용을 제어해야하기 때문입니다.

Win32 프로그래밍은 처음 엔 상당히 어려울 수 있지만 잠시 후 ... 여전히 어려운 상황입니다.

건배!

+0

우선, 뉘앙스를 설명하는 등 세부적인 답변을 해주셔서 감사드립니다. 나는 그것을 시도하고 다시 당신에게 돌아갈거야. – legends2k

+0

이것은 저급 키보드 후크와 관련된 이전 프로젝트에서 전에 거쳐야했던 모든 것들입니다. 주로 그 프로젝트에서 복사/붙여 넣기하고 설명 텍스트를 추가했습니다. 희망이 도움이됩니다! – kurige

+1

효과가있었습니다! 오, 오랜 시간이 지난 후, 마침내 효과가있었습니다! 이전에 SendInput을 사용해 보았을 때도 똑같은 일을했지만 문제는 제가 등록한 단축키였습니다. 나는'Ctrl + Alt + S'에 등록했고 _WM_HOTKEY_에는'Ctrl + C '로 SendInput을 호출했습니다. 그러나 사용자가'Ctrl + Alt + S'를 누를 때'Ctrl + C '를 가상으로 전달할 때'Alt'가 계속 내려갑니다. 단축키를'Windows + S '로 바꿨을 때 완벽하게 작동했습니다. 콤비네이션에서 'Alt'가있는 핫키에서,'Alt' (KEYEVENTF_KEYUP)를 사실상하지 않을 때도 작동합니다. – legends2k

0

SendMessage (WM_COPY 등)를 시도해보십시오.

+0

나는 이것을 시도했습니다. ( – legends2k

3

각 SendInput() 뒤에 Sleep()을 추가하십시오. 일부 앱은 키보드 입력을 포착하는 데 그다지 빠르지 않습니다.

+0

kurige의 답변과 함께 사용하면 고맙습니다 :) Thanks : – legends2k

+0

예를 들어 Chrome에서 내 프로세스가 그것을 읽기 전에 클립 보드에 선택된 텍스트. –

+3

그러나 클립 보드 체인에 창을 등록하고 응용 프로그램 WndProc에 WM_DRAWCLIPBOARD를 추가하는 것이 좋습니다. 그렇게하면 입력을받는 윈도우가 클립 보드를 수정 한 후에 메시지를 받게됩니다. –

관련 문제