26

免责声明:我不熟悉 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
)

正如SetParent 上的 MSDN 文章所建议的那样,我还清除了WS_POPUP样式属性并添加了一个WS_CHILD属性。由于这也没有帮助,我还WS_EX_NOACTIVATE通过使用SetWindowLongPtr命令添加了扩展样式属性。最后,我尝试发送两个窗口WM_UPDATEUISTATE,然后发送一条WM_CHANGEUISTATE消息,但这也没有改变任何事情。

让我感到困惑的是,父进程的窗口继续正常绘制,直到我触摸它。然后它完全冻结,直到子窗口解冻。我怀疑有一个叫做“输入队列”的东西。有关消息的MSDN 文章WM_ACTIVATE指出:

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

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

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

4

1 回答 1

18

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

但是,通过在这些进程的窗口之间建立父/子关系,您还引入了两个 GUI 线程都得到及时服务的要求。

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

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

更新

好的,正如这里所解释的,当您关联来自不同线程的窗口时,您将它们的消息队列彼此附加。所以如果你阻塞了一个线程,你就阻塞了所有附加的线程。

所以,不要阻塞 GUI 线程。

于 2013-05-29T15:22:09.280 回答