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.
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 callingfreeandnil(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.
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