我在使用 TApplication.ModalPopupMode=pmAuto 时遇到问题,我想知道我的问题是否是由我使用 pmAuto 或 delphi 中的错误引起的。
简单用例:
动作顺序:
我使用 ComboBox 作为示例,但我猜想在 DestroyWnd 过程中保存信息并在 CreateWnd 过程中恢复信息的任何控件都无法正常工作。我测试了 TListBox,它也显示相同的行为。
这并不是真正的错误,只是处理模态时各个窗口如何相互交互的一个怪癖。
Form3
首次创建时,TComboBox.CreateWnd()
在 DFM 流式传输期间调用。Form3.ShowModal()
第一次调用时,如果它是或不是,Form3
则调用自身。好的,所以被调用,保存项目,然后被调用,恢复项目。期间重新创建 的窗口并不理想,但这次可以了。RecreateWnd()
PopupMode
pmNone
Application.ModalPopupMode
pmNone
TComboBox.DestroyWnd()
TComboBox.CreateWnd()
TComboBox
ShowModal()
当Form3.ShowModal()
第二次调用时,TComboBox.CreateWnd()
会再次调用而无需先前调用TComboBox.DestroyWnd()
! 由于项目尚未保存,因此无法恢复。这就是为什么它TComboBox
是空的。
但为什么会出现这种情况呢?当Form2
被释放时,Form3
的窗口仍然与Form2
的窗口相关联。第一次调用将的窗口Form3.ShowModal
设置为的父/所有者窗口。当您关闭 a 时,它只是被隐藏,它的窗口仍然存在。因此,当和关闭时,它们仍然存在并链接在一起,然后当被销毁时,其所有子窗口和拥有的窗口都被销毁。 收到一条消息,将其重置为 0,而不通知其其余代码窗口正在被销毁。因此,没有机会保存其当前项目,因为没有被调用。 仅当 VCL 本身销毁窗口时调用,而不是当操作系统销毁窗口时调用。Form2
Form3
TForm
Form2
Form3
Form2
TComboBox
WM_NCDESTROY
Handle
TComboBox
DestroyWnd()
DestroyWnd()
现在,你该如何解决这个问题?在释放 之前,您必须销毁 的TComboBox
窗口,触发其DestroyWnd()
方法Form2
。诀窍是,只有在属性中启用TComboBox.DestroyWnd()
该标志时才会保存项目。您可以通过几种不同的方法来实现这一目标:csRecreating
TComboBox.ControlState
TWinControl.UpdateRecreatingFlag()
直接打电话TWinControl.DestroyHandle()
。它们都是protected
,因此您可以使用访问器类来访问它们:
type
TComboBoxAccess = class(TComboBox)
end;
Form2 := TForm2.Create(nil);
try
Form2.ShowModal;
finally
with TComboBoxAccess(Form3.ComboBox1) do
begin
UpdateRecreatingFlag(True);
DestroyHandle;
UpdateRecreatingFlag(False);
end;
Frm.Free;
end;
Form3.ShowModal;
Run Code Online (Sandbox Code Playgroud)直接打电话TWinControl.RecreateWnd()
。它也是protected
,因此您可以使用访问器类来访问它:
type
TComboBoxAccess = class(TComboBox)
end;
Form2 := TForm2.Create(nil);
try
Form2.ShowModal;
finally
TComboBoxAccess(Form3.ComboBox1).RecreateWnd;
Frm.Free;
end;
Form3.ShowModal;
Run Code Online (Sandbox Code Playgroud)
TComboBox
直到下一次需要窗口时(在后续的ShowModal()
.
向窗口发送TComboBox
一条CM_DESTROYHANDLE
消息,让我们TWinControl
为您处理一切:
Form2 := TForm2.Create(nil);
try
Form2.ShowModal;
finally
if Form3.ComboBox1.HandleAllocated then
SendMessage(Form3.ComboBox1.Handle, CM_DESTROYHANDLE, 1, 0);
Frm.Free;
end;
Form3.ShowModal;
Run Code Online (Sandbox Code Playgroud)
CM_DESTROYHANDLE
TWinControl.DestroyHandle()
在销毁子窗口时在内部使用。当TWinControl
组件收到该消息时,它会自行调用UpdateRecreatingFlag()
和DestroyHandle()
。
归档时间: |
|
查看次数: |
1045 次 |
最近记录: |