delphi - Why does CM_CONTROLLISTCHANGE performs for indirect parent controls? -


i noticed if have main container/parent (mainpanel), adding child panel (childpanel), perform cm_controllistchange on mainpanel (in twincontrol.insertcontrol()) fine.

but if insert child control (childbutton) childpanel, cm_controllistchange fired again main mainpanel!

why that? expecting cm_controllistchange fire childpanel when inserting childbutton childpanel.

mcve

unit unit1;  interface  uses   windows, messages, sysutils, classes, graphics, controls, forms, dialogs,   extctrls, stdctrls;  type   tmainpanel = class(extctrls.tcustompanel)   private     procedure cmcontrollistchange(var message: tcmcontrollistchange); message cm_controllistchange;   end;    tform1 = class(tform)     button1: tbutton;     memo1: tmemo;     procedure button1click(sender: tobject);   private   public     mainpanel: tmainpanel;   end;  var   form1: tform1;  implementation  {$r *.dfm}  procedure tmainpanel.cmcontrollistchange(var message: tcmcontrollistchange); begin   if message.inserting   begin     form1.memo1.lines.add('tmainpanel.cmcontrollistchange: inserting ' + message.control.classname);     // parent nil     if message.control.parent = nil form1.memo1.lines.add('*** parent=nil');   end;   inherited; end;  procedure tform1.button1click(sender: tobject); var   childpanel: tpanel;   childbutton: tbutton; begin   freeandnil(mainpanel);    mainpanel := tmainpanel.create(self);   mainpanel.setbounds(0, 0, 200, 200);   mainpanel.parent := self;    childpanel := tpanel.create(self);   childpanel.parent := mainpanel;    childbutton := tbutton.create(self);   childbutton.parent := childpanel; // why cm_controllistchange in "mainpanel"? end;  end. 

dfm

object form1: tform1   left = 192   top = 114   width = 685   height = 275   caption = 'form1'   color = clbtnface   font.charset = default_charset   font.color = clwindowtext   font.height = -11   font.name = 'ms shell dlg 2'   font.style = []   oldcreateorder = false   pixelsperinch = 96   textheight = 13   object button1: tbutton     left = 592     top = 8     width = 75     height = 25     caption = 'button1'     taborder = 0     onclick = button1click   end   object memo1: tmemo     left = 456     top = 40     width = 209     height = 193     taborder = 1   end end 

p.s: don't know if matters, i'm on delphi 5.

this question easy answer using debugger. have done quite readily. enable debug dcus , set breakpoint inside if statement in tmainpanel.cmcontrollistchange.

the first time breakpoint fires when child panel inserted. expect, immediate child of main panel being added, child panel. second time breakpoint fires point of interest. that's when child of child panel added.

when breakpoint fires, call stack this:

 tmainpanel.cmcontrollistchange((45100, $22420ec, true, 0)) tcontrol.wndproc((45100, 35922156, 1, 0, 8428, 548, 1, 0, 0, 0)) twincontrol.wndproc((45100, 35922156, 1, 0, 8428, 548, 1, 0, 0, 0)) twincontrol.cmcontrollistchange((45100, 35922156, 1, 0, 8428, 548, 1, 0, 0, 0)) tcontrol.wndproc((45100, 35922156, 1, 0, 8428, 548, 1, 0, 0, 0)) twincontrol.wndproc((45100, 35922156, 1, 0, 8428, 548, 1, 0, 0, 0)) tcontrol.perform(45100,35922156,1) twincontrol.insertcontrol($22420ec) tcontrol.setparent($2243dd4) tform1.button1click(???) 

at point can inspect call stack double clicking on each item. i'd start @ tform1.button1click confirms indeed responding childbutton.parent := childpanel. work way list.

two items come twincontrol.insertcontrol , when double click on item find:

perform(cm_controllistchange, integer(acontrol), integer(true)); 

here, acontrol button, , self child panel. let's continue far twincontrol.cmcontrollistchange. now, message handled, , still have self being child panel. body of function is:

procedure twincontrol.cmcontrollistchange(var message: tmessage); begin   if fparent <> nil fparent.windowproc(message); end; 

and answer puzzle. vcl propagates message parent chain. call leads top of call stack, tmainpanel.cmcontrollistchange, self main panel, fparent in call twincontrol.cmcontrollistchange.

i know have pointed @ twincontrol.cmcontrollistchange , have answered question directly. want make point such questions quite readily resolved relatively simple debugging.

note have debugged delphi 6 closest readily available version delphi 5 have, principles outlined here, , answer remain valid in versions.


Comments

Popular posts from this blog

networking - Vagrant-provisioned VirtualBox VM is not reachable from Ubuntu host -

c# - ASP.NET Core - There is already an object named 'AspNetRoles' in the database -

ruby on rails - ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true -