Windows 什么外部事件触发TCustomForm.RecreateWnd?
一个特定的VCL应用程序很少崩溃,而且显然是自发崩溃的,我强烈怀疑这是因为主窗体的窗口句柄是为了响应操作系统的某些外部触发器而重新创建的 我确实知道,如果主窗体的窗口句柄要更改,那么问题肯定会随之而来(因为后台线程向这个句柄发送消息) 但我想知道,在我着手修改代码以修复它之前,如何重现这个bug,只要这样我才能确认这是导致崩溃的合理原因,症状与报告的症状相符,并且代码更改确实修复了它。(另外,如果操作系统无法触发对Windows 什么外部事件触发TCustomForm.RecreateWnd?,windows,delphi,delphi-xe2,Windows,Delphi,Delphi Xe2,一个特定的VCL应用程序很少崩溃,而且显然是自发崩溃的,我强烈怀疑这是因为主窗体的窗口句柄是为了响应操作系统的某些外部触发器而重新创建的 我确实知道,如果主窗体的窗口句柄要更改,那么问题肯定会随之而来(因为后台线程向这个句柄发送消息) 但我想知道,在我着手修改代码以修复它之前,如何重现这个bug,只要这样我才能确认这是导致崩溃的合理原因,症状与报告的症状相符,并且代码更改确实修复了它。(另外,如果操作系统无法触发对TCustomForm.RecreateWnd的调用,我需要找到崩溃的其他解释。是
TCustomForm.RecreateWnd
的调用,我需要找到崩溃的其他解释。是的,我可以将CM\u RecreateWnd
发布到主窗体,但这就引出了问题。)
(我知道,将消息从后台线程发布到VCL线程的正确方法是使用AllocateHWnd
——这是我建议的解决方案,仅为此目的创建一个隐藏消息窗口。)
我在TCustomListView
的派生版本中看到了类似的错误,其中重新创建的
是通过将桌面样式从Windows XP更改为Windows Classic触发的。但是我还没有找到这样一种方法来触发TCustomForm
上的重新创建wnd
。(我花了相当长的时间通读VCL代码,一定是遗漏了什么。)
摘要:
在来自操作系统的什么刺激下,VCL会在TCustomForm
上调用RecreateWnd
?(如果Windows 7有什么不同的话,我对它特别感兴趣。)
如果操作系统有这样的刺激,我可以证明它是否会导致观察到的症状。如果确实没有,那么我可以证明重新创建窗口不是原因。如果您的表单属于另一个正在被销毁的窗口,Windows将销毁该表单 这将导致窗体的句柄被销毁
但是由于您的表单仍然存在,Delphi将在下次重新创建句柄。我无法备份它,但我看到每次应用另一个VCL样式时窗口句柄都会发生更改。请查看VCL的源代码。那就是我要去的地方start@DavidHeffernan我已经花了整个上午阅读VCL源代码,要么我遗漏了什么,要么操作系统没有触发表单上的重新创建。我希望有人知道答案。你有证据表明窗户娱乐是个问题吗?你有一个madexcept日志或类似的,我想?覆盖CreateWindowHandle并创建一个日志,以及应用程序启动和退出。这样,您就不必猜测窗口是否已重新创建。这是假设它是主要形式,需要调整,否则。好的观点。这种机制在VCL源代码中并不明确。如果所有者表单是Delphi应用程序对象呢?我猜在流程的正常生命周期内不会被破坏和重新创建。@IanGoldby这是真的。Windows从不(无法)调用
重新创建wnd
。当需要重新创建窗口句柄时,将在内部调用该方法。VCL源代码中充斥着需要重新创建表单句柄的情况(例如,您更改表单样式
,边框样式
,BiDiMode
,边框图标
,位置
。)但在所有这些情况下,都是VCL自己做的。关键是VCL做这件事是为了响应开发人员的应用程序代码中的某些内容,而不是响应那些在外部发生(例如用户更改桌面样式)。诸如停靠/取消停靠、重新设置父子关系、窗口样式更改、VCL样式更改等都将触发窗口的重新创建。此外,任何对窗口的外部破坏都会将所属控件的句柄重置为0,并破坏所有子窗口,同时将子控件句柄重置为0。