delphi - pmAuto ModalPopupMode proper use or bug workaround -
i'm having problems using tapplication.modalpopupmode=pmauto , wondering if problems caused usage of pmauto or bug in delphi.
simple use case:
- form1(mainform) , form3 permanent forms. (created in dpr)
- form2 created when needed , freed afterward.
- form3 contains tcombobox x items.
sequence of actions :
- form1 create , show form2 modal.
- form2 show form3 modal.
- close form3
- close , free form2
- show form3 <---- tcombobox contains 0 items.
i use combobox example, guess controls saves information in destroywnd procedure , restore in createwnd procedure isn't working right. tested tlistbox , displays same behavior too.
- is known fact 1 shouldn't mix permanent , temporary form when modalpopupmode pmauto?
- if not, there known workaround problem?
- if it's bug, fixed in more recent version of delphi? (i'm using xe4)
it not bug, quirk in how various windows interact each other when dealing modality.
when form3
first created, tcombobox.createwnd()
called during dfm streaming. when form3.showmodal()
called first time, form3
calls recreatewnd()
on if popupmode
pmnone
, application.modalpopupmode
not pmnone
. ok, tcombobox.destroywnd()
gets called, saving items, tcombobox.createwnd()
gets called, restoring items. recreating tcombobox
's window during showmodal()
not ideal, works time.
when form3.showmodal()
called second time, tcombobox.createwnd()
called again without previous call tcombobox.destroywnd()
! since items have not been saved, cannot restored. why tcombobox
empty.
but why happen? when form2
freed, form3
's window still associated form2
's window. first call form3.showmodal
set form2
's window form3
's parent/owner window. when close tform
, merely hidden, window still exists. so, when form2
, form3
closed, still exist , linked together, , when form2
destroyed, of child , owned windows destroyed. tcombobox
receives wm_ncdestroy
message, resetting handle
0 without notifying rest of code window being destroyed. thus, tcombobox
not have chance save current items because destroywnd()
not called. destroywnd()
called when vcl destroying window, not when os destroys it.
now, how can fix this? have destroy tcombobox
's window, triggering destroywnd()
method, before freeing form2
. trick tcombobox.destroywnd()
save items if csrecreating
flag enabled in tcombobox.controlstate
property. there few different ways can accomplish that:
call
twincontrol.updaterecreatingflag()
,twincontrol.destroyhandle()
directly. bothprotected
, can use accessor class reach them:type tcomboboxaccess = class(tcombobox) end; form2 := tform2.create(nil); try form2.showmodal; tcomboboxaccess(form3.combobox1) begin updaterecreatingflag(true); destroyhandle; updaterecreatingflag(false); end; frm.free; end; form3.showmodal;
call
twincontrol.recreatewnd()
directly.protected
, can use accessor class reach it:type tcomboboxaccess = class(tcombobox) end; form2 := tform2.create(nil); try form2.showmodal; tcomboboxaccess(form3.combobox1).recreatewnd; frm.free; end; form3.showmodal;
the
tcombobox
window not created until next time needed, in subsequentshowmodal()
.send
tcombobox
windowcm_destroyhandle
message , lettwincontrol
handle you:form2 := tform2.create(nil); try form2.showmodal; if form3.combobox1.handleallocated sendmessage(form3.combobox1.handle, cm_destroyhandle, 1, 0); frm.free; end; form3.showmodal;
cm_destroyhandle
used internallytwincontrol.destroyhandle()
when destroying child windows. whentwincontrol
component receives message, callsupdaterecreatingflag()
,destroyhandle()
on itself.
Comments
Post a Comment