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:

  1. call twincontrol.updaterecreatingflag() , twincontrol.destroyhandle() directly. both protected, 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; 
  2. 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 subsequent showmodal().

  3. send tcombobox window cm_destroyhandle message , let twincontrol 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 internally twincontrol.destroyhandle() when destroying child windows. when twincontrol component receives message, calls updaterecreatingflag() , destroyhandle() on itself.


Comments

Popular posts from this blog

html - Firefox flex bug applied to buttons? -

html - Missing border-right in select on Firefox -

c# - two queries in same method -