如何获取未获得焦点的应用程序的活动ChildWindow?
我需要将处理程序获取到正在运行的某个应用程序的子窗口。 我有主窗口处理程序,但我需要知道哪个特定子窗口处于活动状态,以便使用 SendMessage/PostMessage。
我终于设法使用以下代码,使用 firefox 来做到这一点:
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("user32.dll", EntryPoint = "GetGUIThreadInfo")]
internal static extern bool GetGUIThreadInfo(uint idThread, out GUITHREADINFO threadInfo);
private void button1_Click(object sender, EventArgs e)
{
//start firefox
firefox = new Process();
firefox.StartInfo.FileName = @"C:\Program Files\Mozilla Firefox\firefox.exe";
firefox.Start();
Thread.Sleep(10000);
// 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);
}
这效果非常好! 但是,如果应用程序未处于活动状态,例如,如果记事本覆盖了 firefox,则 GUIThreadInfo 的每个成员都为 null。 仅当 Firefox 是 Windows 最顶层(活动)应用程序时,该结构才会被填充。
我知道可以通过将 Firefox 置于前台来解决此问题,但我需要避免这样做。 有没有人有任何其他想法来获取不是 Windows 最顶层窗口的应用程序的活动子窗口?
谢谢
I need to get the Handler to the child Window of a certain application that is running. I have the main window handler, but I need to know which specific child window is active, in order to use the SendMessage/PostMessage.
I finally managed to do this using the following code, using firefox:
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("user32.dll", EntryPoint = "GetGUIThreadInfo")]
internal static extern bool GetGUIThreadInfo(uint idThread, out GUITHREADINFO threadInfo);
private void button1_Click(object sender, EventArgs e)
{
//start firefox
firefox = new Process();
firefox.StartInfo.FileName = @"C:\Program Files\Mozilla Firefox\firefox.exe";
firefox.Start();
Thread.Sleep(10000);
// 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);
}
This works very well! However, if the application is not active, for example, if notepad is covering firefox, the GUIThreadInfo comes with every member null. Only if firefox is the top-most (active) application of windows, will the structure be filled.
I know this could be fixed by bringing firefox to the foreground but I needed to avoid doing this. Does anyone have any other idea to get the active child window of an application that is not the top-most window in Windows?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您拥有该进程的最顶层窗口句柄,则应该能够使用 GetTopWindow 接收 Z 顺序顶部的窗口。 如果应用程序设置为活动/当前应用程序,这应该是活动的窗口。
编辑:
如何使用 AttachThreadInput 附加您的线程到其他进程线程?
完成此操作后,GetFocus() 和 PostMessage()/SendMessage() 应该可以工作。 只需确保完成后分离输入即可。
我能找到的唯一示例不幸的是在Delphi中,但是很容易翻译。
If you have the topmost window handle for the process, you should be able to use GetTopWindow to receive the window at the top of the Z order. This should be the window that would be active if the application were set to be the active/current app.
Edit:
What about using AttachThreadInput to attach your thread to the other process thread?
Once you've done that, GetFocus() and PostMessage()/SendMessage() should work. Just make sure you detach the input when you're done.
The only sample I can find of this is unfortunately in Delphi, but would be easy to translate.
您可以考虑使用 GetWindow 函数 (hWnd, GW_CHILD) 并将消息发布到该句柄上。
另请注意,在 Microsoft Windows Vista 及更高版本上。 消息发布受用户界面权限隔离 (UIPI) 的约束。 进程的线程只能将消息发布到完整性级别较低或相同的进程中的线程的消息队列。
You could consider obtaining the child window handle using the GetWindow Function (hWnd, GW_CHILD) and Post the message on this handle.
Also be aware that on Microsoft Windows Vista and later. Message posting is subject to User Interface Privilege Isolation (UIPI). The thread of a process can post messages only to message queues of threads in processes of lesser or equal integrity level.