微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

delphi – 父窗口冻结时,子窗口冻结,虽然它是从另一个过程

免责声明:我不熟悉Win32 API,尤其是Windows如何工作。此外,这是我的第一篇关于SO。这个问题可能是令人难以置信的愚蠢。

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

想象一下,一个“hosts”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,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指出:

Sent to both the window being activated and the window being deactivated. If the windows use the same input queue,the message is sent synchronously,first to the window procedure of the top-level window being deactivated,then to the window procedure of the top-level window being activated. If the windows use different input queues,the message is sent asynchronously,so the window is activated immediately.

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

总结:实际上可能托管另一个进程的窗口,并且当子窗口冻结时不冻结您自己的窗口?

解决方法

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

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

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

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

更新

OK,正如解释here当你从不同的线程关联窗口,你附加他们的消息队列彼此。所以如果你阻塞一个线程,你阻塞所有附加的线程。

所以,不要阻塞GUI线程。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都是大家转来转去,原文出处我已经找不到了。这篇文章写的很不错,但最后部分“PermuteFunction 的终极版本”描述的不太清楚,完全按照该文章代码执行,是不行的。可能是作者故意这样做的?本文最后提供修正后的下载地址。原文如下:一、关于API Hook1.什么是API Hook不知道大家是否还记得,在DO
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都是大家转来转去,原文出处我已经找不到了。 这篇文章写的很不错,但最后部分“PermuteFunction 的终极版本”描述的不太清楚,完全按照该文章代码执行,是不行的。需要修改mess.pas中代码才行。其实文中提到的一个结构,代码中并没有使用typePIMAGE_IMPORT_DESCRIPTOR = ^IMA
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c++ 调用, 抽空研究了一下该库的最新版 ,把部分api 翻译成了dephi版的 记录一下 地址 ffmpegvcl.zip
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和EDX)2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP)6个段寄存器(ES、CS、SS、DS、FS和GS)
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的功能是:将源操作数送到目的操作数中,即:(dst) <--(src) 1.dst和src类型必须匹配,即必须同为字节
有三个API函数可以运行可执行文件WinExec、ShellExecute和CreateProcess。 1.CreateProcess因为使用复杂,比较少用。 2.WinExec主要运行EXE文件。如:WinExec('Notepad.exe Readme.txt', SW_SHOW); 3.ShellExecute不仅可以运行EXE文件,也可以运行已经关联的文件。 首先必须引用shellapi
API原型: Declare Function MoveFileEx& Lib "kernel32" Alias "MoveFileExA" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal dwFlags As Long) 参数 类型及说明 lpExistingFileName String,欲移
附带通用控件安装方法: ---------- 基本安装 1、对于单个控件,Componet-->install component..-->PAS或DCU文件-->install; 2、对于带*.dpk文件的控件包,File-->Open(下拉列表框中选*.dpk)-->install即可; 3、对于带*.bpl文件的控件包,Install Packages-->Add-->bpl文件名即可; 4
type   TRec=Record     msg:string;     pic:TMemoryStream; end; procedure TForm2.BitBtn1Click(Sender: TObject); var   ms:TMemoryStream;   Rec1,Rec2:TRec;   cc:tmemorystream;   jpg:TJPEGImage; begin   R