У меня эта проблема: у меня есть обработчик в 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, оно не работает.
Так что в основном мне нужно найти способ получить обработчик активного дочернего окна приложения, даже если это приложение не является самым активным.
Любые идеи? Спасибо