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
tcomboboxwindow not created until next time needed, in subsequentshowmodal().send
tcomboboxwindowcm_destroyhandlemessage , lettwincontrolhandle 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_destroyhandleused internallytwincontrol.destroyhandle()when destroying child windows. whentwincontrolcomponent receives message, callsupdaterecreatingflag(),destroyhandle()on itself.
Comments
Post a Comment