2009-05-07 2 views
3

이 문제는 : 특정 응용 프로그램의 mainWindow에 대한 처리기가 있고 그 응용 프로그램의 keypress를 시뮬레이트하고 싶습니다. ...응용 프로그램의 활성 ChildWindow를 얻으려면 어떻게해야합니까?

나는 이것을하기 위해 sendMessage/postMessage API 호출을 사용하고 있습니다. .Net SendKeys 함수 또는 win32 API의 keybd_event를 사용하지 않는 이유는 전역 수준에서 키 누르기를 시뮬레이트하기 때문입니다. 필자의 경우, 대상 응용 프로그램이 최상위 활성 응용 프로그램이 아닙니다 (다른 응용 프로그램이 상위 z 수준에서 실행되어 대상 응용 프로그램을 덮을 수 있습니다).

sendMessage 및 postMessage의 문제점은 키를 누를 정확한 자식 창 핸들러를 전달해야한다는 것입니다. 예를 들어 메모장에서 mainWindow의 핸들러에 키를 보내면 아무 일도 일어나지 않습니다. 기본적으로 자식 캔슬러의 핸들러에 키를 보내야합니다.이 키는 작성할 수있는 흰색 캔버스로 구성됩니다.

활성 자식 창에 대한 처리기를 가져 오는 것이 문제입니다. 처음에는 GetTopWindow 또는 GetWindow (GW_CHILD) API 호출을 사용하여 가장 활동적인 자식 창을 반환했습니다. 내가 뭘했는지는 더 이상 childWindow가없는 childwindow가 생길 때까지 GetWindow (GW_CHILD)를 계속 호출하는 것이 었습니다. 이것은 메모장이나 페인트와 같은 일부 응용 프로그램에서는 정상적으로 작동합니다. 그러나 일부 경우 (예 : firefox)와 같이 작동하지 않습니다. 그 이유는 부모 창이 전체 파이어 폭스 영역을 가지고 있으며 자식 창에 열린 웹 페이지 (예 : Google)가 있기 때문입니다. 그래서, mainWindow의 가장 활동적인 자식 창을 요청하면, 웹 페이지 영역에 해당하는 자식 창만 반환합니다. 그것은 활성 창 (사용자가 특정 페이지의 텍스트 상자에 뭔가를 쓰고있는 경우)과 같은 경우에만 작동합니다. 하지만 활성화 된 것은 주소창, 활성 창은 자식 창이 아니기 때문에 작동하지 않는다는 것입니다. 실제로 부모가 ...이 정보를 프로그래밍 방식으로 가져올 수는 없습니다.

는 사실은 다음과 같은 코드를 사용하여 GetGUIThreadInfo API 호출을 사용하여,이 일을하는 방법을 발견

// get thread of the main window handle of the process 
    var threadId = GetWindowThreadProcessId(firefox.MainWindowHandle, IntPtr.Zero); 

    // get gui info 
    var info = new GUITHREADINFO(); 
    info.cbSize = (uint)Marshal.SizeOf(info); 
    if (!GetGUIThreadInfo(threadId, out info)) 
     throw new Win32Exception(); 

    // send the letter W to the active window 
    PostMessage(info.hwndActive, WM_KEYDOWN, (IntPtr)Keys.W, IntPtr.Zero); 

을 그리고 그것은 매우 잘 작동 : 주소 표시 줄이 활성화되어 있으면, 그것은 "W"전송 주소 표시 줄에 문자. google의 검색 텍스트 상자가 활성화되어 있으면 "W"문자가 전송됩니다 ... 완벽한! 그러나 간단한 방법으로 나에게이 방법을 사용할 수 없습니다. 대상 응용 프로그램이 운영 체제의 활성 창이 아닌 경우 ThreadInfo 구조는 비어 있습니다. 예를 들어 파이어 폭스를 타겟으로한다면, 파이어 폭스가 활성화되어 있다면 (최상위 애플리케이션, 집중 형/액티브 형),하지만 메모장이 파이어 폭스 상단에 있다면, 작동하지 않는다. 활성 창 핸들러를 가져올 수 없습니다.

나는이 문제를 해결하기 위해 setForegroundWindow API 호출을 사용하여 대상 응용 프로그램을 활성화 한 다음 활성 자식 창의 처리기를 캡처하지만 대상 응용 프로그램을 포 그라운드로 가져오고 싶지는 않습니다.

또한 AttachThreadInput() 및 GetFocus() API 호출과 같은 다른 기술도 시도해 보았습니다.이 기술은 작동하지만 동일한 문제가 있습니다. 대상 응용 프로그램이 활성 Windows 응용 프로그램이 아닌 경우 작동하지 않습니다.

그래서 기본적으로 해당 응용 프로그램이 활성 상태가 아닌 응용 프로그램의 활성 자식 윈도우에 처리기를 가져 오는 방법을 찾아야합니다.

아이디어가 있으십니까? 감사합니다.

답변

0

다른 모든 것이 실패한 경우 다음과 같은 또 다른 아이디어가 있습니다. WH_CBT 또는 WH_CALLWNDPROC 후크를 사용하여 대상 스레드의 자식 창이 마지막으로 포커스가되었는지 모니터링 할 수 있습니다.

CBT 후크 (WH_CBT)를 설치하고 HCBT_SETFOCUS 알림을 수신 대기합니다. 또는 WH_CALLWNDPROC 후크를 사용하고 WM_SETFOCUS 메시지를 수신하십시오.

후크 proc에서 많은 일을하지 않으면 시스템 리소스가 줄어들 수 있습니다. 필요한 정보를 저장하고 나중에 처리 할 수있는 사용자 지정 메시지를 게시하십시오.