Wednesday, 15 June 2011

delphi - Freeing focused custom control dynamically causes crash -



delphi - Freeing focused custom control dynamically causes crash -

a custom command wrote implicated in crash when destroyed. it hard pin downwards exact circumstances , might factor command parented 3rd party control.

edit 8 oct 2014 i've got much improve sscce illustrates crash using tmediaplayer (from delphi vcl) on tform. i've deleted lot of wrote before. please see edit history that. (it turns out cm_exit in former phone call stack red-herring.)

here's sscce:

unit unit1; interface uses system.classes, vcl.controls, vcl.forms, vcl.menus, vcl.mplayer; type tform1 = class(tform) mainmenu: tmainmenu; crashmenuitem: tmenuitem; procedure crashmenuitemclick(sender: tobject); procedure formshow(sender: tobject); private fcontrol : tmediaplayer; end; var form1: tform1; implementation uses vcl.dialogs; {$r *.dfm} procedure tform1.crashmenuitemclick(sender: tobject); begin showmessage('message'); fcontrol.free; end; procedure tform1.formshow(sender: tobject); begin fcontrol := tmediaplayer.create(form1); fcontrol.parent := form1; end; end.

the phone call showmessage before freeing command crucial.

after dismissing dialog, tmediaplayer command gets wm_setfocus. it's destructor called. inherited tcustomcontrol.destroy frees canvas , inherited twincontrol.destroy calls twincontrol.removefocus, gets wm_killfocus. tmediaplayer.wmkillfocus calls paint directly, tries utilize freed canvas , crashes.

(previously had custom command cmfocuschanged called invalidate. effect same phone call stack rather more involved.)

my original 3 questions, ngln has answered below:

am doing wrong simply calling freeandnil(fmycontrol)? must unparent before destroying it? doesn't seem necessary other controls, more hide underlying bug. should command have in destructor prepare twincontrol knows not seek repaint it? is there perhaps bug in 3rd party parent control? case command should not receive wm_printclient message 1 time has started destroyed? (the 3rd party command seems create explicit phone call inherited twincontrol.update when receives cm_exit consequence of command losing focus.)

but real question remains: there wrong code in sscce, or there bug in delphi vcl?

(incidentally, same problem occur descendent of tcustomcontrol. used tmediaplayer convenience.)

am doing wrong simply calling freeandnil(fmycontrol)?

no, every command should able freed @ given time, long references command cleared (nilled) , instance's code isn't run anymore.

must unparent before destroying it? doesn't seem necessary other controls, more hide underlying bug.

no, indeed no need to.

should command have in destructor prepare twincontrol knows not seek repaint it?

no, there no need to. vcl has build in already. testing purposes or (temporary) workaround, seek override paintwindow if not (csdestroying in componentstate) then.

is there perhaps bug in 3rd party parent control? case command should not receive wm_printclient message 1 time has started destroyed? (the 3rd party command seems create explicit phone call inherited twincontrol.update when receives cm_exit consequence of command losing focus.)

the parent command indeed receives cm_exit, because had focussed control, , has not anymore (ie. form.activecontrol = nil). that's normal behaviour. why parent sends wm_printclient command (how know request comes parent? seems start @ update call.) not know. rule out possibility of buggy parent, retry case different parent.

update (due question edit): tmediaplayer.wmkillfocus calls paint directly... procedure tmediaplayer.wmkillfocus(var message: twmkillfocus); begin paint; end;

that taboo! bug in vcl. paint should never called straight other request painting via wm_paint message. have submitted study on qc.

(previously had custom command cmfocuschanged called invalidate. effect same phone call stack rather more involved.)

...

(incidentally, same problem occur descendent of tcustomcontrol. used tmediaplayer convenience.)

that not case test here in d7 , xe2.

delphi delphi-xe2

No comments:

Post a Comment