Search code examples
delphioverflowcomponentsdelphi-7

Delphi - scroll group of components on block overflow


I looked through such components like GroupBox, Panel, ScrollBox, ListBox, but nothing of them is what i am looking for.

What i want is a component that will have a fixed size, no visible borders, preferaly non-color background and will allow to hide contained components if they overflow this component.

Here is an example of what i want to implement in my Delphi project: http://jsfiddle.net/jgems3Ls/1/

Delphi hierarchy idea:

 #non-visible component
 #non-visible component
+---------------------+
|  visible component  |
|  visible component  |  //TOverflowBox(?) borders
|  visible component  |
+---------------------+
 #non-visible component

Unfortunately, googling didnt give me a single hint on how can i do that


Solution

  • Found a solution with using TPanel.

    There are two things to start with:

    1. My form has custom image as background
    2. Panel settings and child components are set at run-time

    Since TPanel doesn't has transparency property, i needed to find a way to keep form image instead of grey panel background. The solution was quite obvious: put form image in panel as new component with required left and top offset in order to make it look good. Example code would be:

    P := Panel1;
    P.Width := 300;
    P.Height := 200;
    P.Left := 100;
    P.Top := 50;
    
    //panel background
    I := Image1;  //its width and height equal to forms ClientWidth and ClientHeight
    I.Left := -100;
    I.Top := -50;
    

    Next problem was panel border, which can easily be removed by P.BevelOuter := bvNone.

    To make panel components scroll, i used form MouseWheel event.

    procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState;
      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
    var P: TPanel;
        B: boolean;
    begin
      B := true;
      case global_navigation(location, sub_location) of //returns current visible panel
        0: B := false;  //no visible panels
        1: P := Form1.Panel1;           
        ...
      end;
    
      //now we need to check if cursor is in panel area
      if B then
        if (PtInRect(P.ClientRect, P.ScreenToClient(Mouse.CursorPos))) then
          if WheelDelta > 0 then                     //if we scroll up
            for i := (P.ControlCount - 1) downto 1 do
              P.Controls[i].Top := P.Controls[i].Top + 10
         else                                        //if we scroll down
            for i := (P.ControlCount - 1) downto 1 do
              P.Controls[i].Top := P.Controls[i].Top - 10;
    end;
    

    Looping through panel components is done downto 1, not downto 0 because the very first component that panel contains is image used as background, which i dont want to move.