Search code examples
delphivcldelphi-2010tcategorypanelgroup

Why TCategoryPanel.controls[i].className always "TCategoryPanelSurface?


On a form I put down 1 x TCategoryPanelGroup object and added 3 TCategoryPanel to it. In a routine, I need to go through each of TCategoryPanel and through each object onto those panel to produce an output.

So, here is the code ... why into the second FOR instead of giving me classname of each component (i.e. TButton, TLabel, etc) it gives out a TCategoryPanelSurface?

Short question: How can I access each controls from each TCategoryPanel?


procedure TForm1.Button2Click(Sender: TObject);
    var i,i2 : integer;

    begin
      for i := 0 to CategoryPanelGroup1.ControlCount-1 do
      begin
        showMessage((CategoryPanelGroup1.Controls[i] as TCategoryPanel).caption ) ;

        for i2 := 0 to (CategoryPanelGroup1.Controls[i] as TCategoryPanel).ControlCount-1 do
        begin

          showMessage((CategoryPanelGroup1.Controls[i] as TCategoryPanel).Controls[i2].ClassName);
        end;
      end;
    end;

Solution

  • You are looping through the Group's underlying TWinControl.Controls[] list when you should be looping through its TCategoryPanelGroup.Panels list instead.

    As for why you are seeing a TCategoryPanelSurface appear, TCategoryPanel creates that object as a direct child of itself in its constructor. Any control you place into the Panel afterwards is actually a child of that TCategoryPanelSurface object, not a child of the TCategoryPanel itself. That is why your looping never sees those controls.

    Unfortunately, TCategoryPanel does not expose direct access to its TCategoryPanelSurface object. So, in order to loop through its children, you have to first be able to access it. There are two possible ways to do that:

    1)

    procedure TForm1.Button2Click(Sender: TObject);
    var
      i, j: integer;
      panel: TCategoryPanel;
      surface: TCategoryPanelSurface;
    begin
      for i := 0 to CategoryPanelGroup1.Panels.Count-1 do
      begin
        panel := TCategoryPanel(CategoryPanelGroup1.Panels[i]);
        ShowMessage(panel.Caption);
        surface := panel.Controls[0] as TCategoryPanelSurface;
        for j := 0 to surface.ControlCount-1 do
        begin
          ShowMessage(surface.Controls[j].ClassName);
        end;
      end; 
    end; 
    

    2)

    type
      TCategoryPanelAccess = class(TCategoryPanelAccess)
      end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    var
      i, j: integer;
      panel: TCategoryPanel;
      surface: TCategoryPanelSurface;
    begin
      for i := 0 to CategoryPanelGroup1.Panels.Count-1 do
      begin
        panel := TCategoryPanel(CategoryPanelGroup1.Panels[i]);
        ShowMessage(panel.Caption);
        surface := TCategoryPanelAccess(panel).FPanelSurface;
        for j := 0 to surface.ControlCount-1 do
        begin
          ShowMessage(surface.Controls[j].ClassName);
        end;
      end; 
    end;