2009-05-07 3 views
3

У меня эта проблема: у меня есть обработчик в MainWindow определенного приложения, и я хочу, чтобы имитировать нажатие клавиши на этой заявке ...Как получить активное приложение ChildWindow приложения?

Я использую SendMessage/PostMessage API вызовы, чтобы сделать это. Причина, по которой я не использую функцию .Net SendKeys или keybd_event из win32 api, заключается в том, что они имитируют нажатия клавиш на глобальном уровне. В моем случае целевое приложение не является самым активным (другое приложение может работать на более высоком уровне z, следовательно, охватывающее целевое приложение).

Проблема с sendMessage и postMessage заключается в том, что вы должны передать обработчик точного дочернего окна, в котором вы хотите нажать клавишу. Например, в блокноте, если я отправлю ключ в обработчик mainWindow, ничего не происходит, я должен отправить ключ обработчику дочернего окна, которое в основном состоит из белого холста, где вы можете писать.

Получение обработчика активного окна ребенка является проблемой. Вначале я использовал вызовы GetTopWindow или GetWindow (GW_CHILD) api, поскольку он возвращает самое активное дочернее окно. То, что я делал, состояло в том, чтобы продолжать называть GetWindow (GW_CHILD) до тех пор, пока у меня не будет дочернего окна, у которого больше нет childWindows. Это работает нормально для некоторых приложений, таких как блокнот или краска. Однако в некоторых случаях (например, firefox) это не работает. Причиной этого является то, что родительское окно имеет всю область firefox, а его дочерняя ветвь имеет открытый WebPage (например, google). Поэтому, когда я запрашиваю наиболее активное дочернее окно mainWindow, он возвращает единственное дочернее окно, которое у него есть, которое соответствует области веб-страницы. Он работает только в том случае, если активным окном является это (например, если пользователь пишет что-то в текстовом поле определенной страницы). Но если активным является, скажем, адресная строка, это не работает, потому что активное окно не является дочерним окном, а фактически родителем ... и я не могу получить эту информацию программно.

Я на самом деле нашел способ сделать это, используя API-интерфейс вызова GetGUIThreadInfo, используя следующий код:

// 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 пуста. Например, если я нацелен на firefox, он работает, если firefox активен (самое верхнее приложение, сфокусированное/активное), но если, скажем, блокнот находится поверх Firefox, он не работает, он не может получить активный обработчик окна.

Я знаю, что я могу решить эту проблему, используя вызов setForegroundWindow api для активации целевого приложения, а затем захватить обработчик активного дочернего окна, но я не хочу, чтобы целевое приложение было перенесено на передний план.

Я также пробовал другие методы, такие как AttachThreadInput() и GetFocus() api calls, который также работает, но имеет ту же проблему: если целевое приложение не является активным приложением Windows, оно не работает.

Так что в основном мне нужно найти способ получить обработчик активного дочернего окна приложения, даже если это приложение не является самым активным.

Любые идеи? Спасибо

ответ

0

Если все остальное не удается, вот еще одна идея: вы можете подумать об использовании крючков WH_CBT или WH_CALLWNDPROC для отслеживания последнего дочернего окна целевого потока.

Установите крюк CBT (WH_CBT) и прослушайте уведомление HCBT_SETFOCUS. Или используйте крюк WH_CALLWNDPROC и прослушайте сообщение WM_SETFOCUS.

Не делайте много усилий в процессе проклятия или вы будете болеть за системные ресурсы. Просто сохраните необходимую информацию и опубликуйте собственное сообщение, чтобы обработать его позже.

Смежные вопросы