当子窗口从另一个进程冻结时,父窗口会冻结

时间:2013-05-29 14:49:29

标签: delphi winapi window

免责声明 :我不熟悉Win32 API,尤其是Windows的工作方式。

我想让某个进程的窗口成为另一个进程的子窗口。这两个过程也是父母和孩子。但我认为不重要。到目前为止,一切都像魅力一样 - 直到我冻结子窗口的主线程。

想象一个“托管”notepad.exe和someApplication.exe

的container.exe

当我暂停 someApplication.exe 的主线程几秒钟时,其窗口将被冻结一段时间。这完全可以理解。但 container.exe 的窗口将同时挂起。其他托管进程的子窗口(如 notepad.exe )将继续正常工作。

我正在使用SetParent命令使常规非子窗口成为我的container.exe的子窗口:

SetParent(
    childProcess.HWND,
    myOwnHWND
);

之后,我正在使用setWindowPos

SetWindowPos(
    childProcess.HWND,
    HWND_TOP,
    someXPos,
    someYPos,
    0,
    0,
    SWP_FRAMECHANGED or SWP_NOSIZE or SWP_SHOWWINDOW
)

正如MSDN article on SetParent建议的那样,我还会清除WS_POPUP样式属性并添加WS_CHILD属性。由于这也没有帮助,我还使用WS_EX_NOACTIVATE命令添加了SetWindowLongPtr扩展样式属性。最后,我尝试向两个窗口发送WM_UPDATEUISTATE然后发送WM_CHANGEUISTATE消息,但这也没有改变。

令我困惑的是,父进程的窗口继续正常绘制,直到我触摸它。然后它完全冻结,直到子窗口解冻。我怀疑称为'输入队列'的东西。关于WM_ACTIVATE消息的MSDN article说明:

  

发送到正在激活的窗口和停用的窗口。如果窗口使用相同的输入队列,则消息将同步发送,首先发送到要停用的顶级窗口的窗口过程,然后到窗口过程顶层窗口被激活。如果窗口使用不同的输入队列,则会异步发送消息,因此会立即激活窗口。

因此,我对WS_EX_NOACTIVATE扩展样式属性寄予厚望。

总结一下:实际上是否可以托管另一个进程的窗口,并在子窗口冻结时不冻结自己的窗口?

1 个答案:

答案 0 :(得分:17)

您不能指望阻止任何进程的GUI线程。在您的场景中,事情有点复杂,因为有两个GUI线程。每个过程一个。

但是,通过在这些进程的窗口之间建立父/子关系,您还要求及时为两个GUI线程提供服务。

处于父/子关系的Windows将相互发送消息。如果这些消息是同步的,那就是发送而不是发布,那么阻止一个GUI线程将导致另一个被阻止。

GUI编程的黄金法则仍然有效:不要阻止GUI线程。如果您有一个长时间运行的任务,那么将其移动到后台线程。

<强>更新

好的,正如here所解释的那样,当您关联来自不同线程的窗口时,您将其消息队列相互附加。因此,如果您阻止一个线程,则会阻止所有连接的线程。

所以,不要阻止GUI线程。