如何获取未聚焦的应用程序的活动ChildWindow?

时间:2021-05-19 07:31:13

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.

我需要将Handler放到正在运行的某个应用程序的子窗口中。我有主窗口处理程序,但我需要知道哪个特定的子窗口是活动的,以便使用SendMessage / PostMessage。

I finally managed to do this using the following code, using firefox:

我终于设法使用以下代码,使用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.

这非常有效!但是,如果应用程序未处于活动状态,例如,如果notepad覆盖了firefox,则GUIThreadInfo会为每个成员提供null。只有当firefox是windows的最顶层(活动)应用程序时,才会填充结构。

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?

我知道这可以通过将firefox带到前台来解决,但我需要避免这样做。有没有人有任何其他想法来获取不是Windows中最顶层窗口的应用程序的活动子窗口?

Thanks

2 个解决方案

#1


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.

如果你有进程的最顶层窗口句柄,你应该能够使用GetTopWindow接收Z顺序顶部的窗口。如果应用程序设置为活动/当前应用程序,则应该是活动的窗口。


Edit:

What about using AttachThreadInput to attach your thread to the other process thread?

使用AttachThreadInput将线程附加到其他进程线程怎么样?

Once you've done that, GetFocus() and PostMessage()/SendMessage() should work. Just make sure you detach the input when you're done.

完成后,GetFocus()和PostMessage()/ SendMessage()应该可以正常工作。只需确保在完成后分离输入。

The only sample I can find of this is unfortunately in Delphi, but would be easy to translate.

不幸的是,在德尔福,我能找到的唯一一个样本,但很容易翻译。

#2


You could consider obtaining the child window handle using the GetWindow Function (hWnd, GW_CHILD) and Post the message on this handle.

您可以考虑使用GetWindow函数(hWnd,GW_CHILD)获取子窗口句柄,并在此句柄上发布消息。

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.

另请注意,在Microsoft Windows Vista及更高版本上。邮件过帐受用户界面权限隔离(UIPI)的约束。进程的线程只能将消息发布到完整性级别较低或相等的进程中的线程的消息队列。

#1


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.

如果你有进程的最顶层窗口句柄,你应该能够使用GetTopWindow接收Z顺序顶部的窗口。如果应用程序设置为活动/当前应用程序,则应该是活动的窗口。


Edit:

What about using AttachThreadInput to attach your thread to the other process thread?

使用AttachThreadInput将线程附加到其他进程线程怎么样?

Once you've done that, GetFocus() and PostMessage()/SendMessage() should work. Just make sure you detach the input when you're done.

完成后,GetFocus()和PostMessage()/ SendMessage()应该可以正常工作。只需确保在完成后分离输入。

The only sample I can find of this is unfortunately in Delphi, but would be easy to translate.

不幸的是,在德尔福,我能找到的唯一一个样本,但很容易翻译。

#2


You could consider obtaining the child window handle using the GetWindow Function (hWnd, GW_CHILD) and Post the message on this handle.

您可以考虑使用GetWindow函数(hWnd,GW_CHILD)获取子窗口句柄,并在此句柄上发布消息。

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.

另请注意,在Microsoft Windows Vista及更高版本上。邮件过帐受用户界面权限隔离(UIPI)的约束。进程的线程只能将消息发布到完整性级别较低或相等的进程中的线程的消息队列。