Home > Blockchain >  Delphi-docking form hides panel
Delphi-docking form hides panel

Time:12-16

I have a problem that docking form hides some other components inside of panel.

This is simple example of my problem: I have Panel1 with DockSite set to True. Inside Panel1 is Panel2. Panel2 alignts to client (Align=alClient). Inside Panel2 is memo field that is also aligned to client. It overlaps the entire Panel1. I have another form (Form2) that I want to dock to Panel1. But it overlaps entire Panel1 and hides memo filed. I want to overlap only part of Panel1 (width of the form) and move Panel2 to the rigth or to te left.

Main form:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Panel1: TPanel;
    Panel2: TPanel;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Unit2;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Show;
end;

end.


object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 333
  ClientWidth = 754
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -12
  Font.Name = 'Segoe UI'
  Font.Style = []
  PixelsPerInch = 96
  TextHeight = 15
  object Button1: TButton
    Left = 288
    Top = 271
    Width = 153
    Height = 41
    Caption = 'Show dockable form'
    TabOrder = 0
    OnClick = Button1Click
  end
  object Panel1: TPanel
    Left = 8
    Top = 8
    Width = 729
    Height = 257
    Caption = 'Panel1'
    DockSite = True
    TabOrder = 1
    object Panel2: TPanel
      Left = 1
      Top = 1
      Width = 727
      Height = 255
      Align = alClient
      Caption = 'Panel2'
      TabOrder = 0
      ExplicitLeft = 360
      ExplicitTop = 8
      ExplicitWidth = 337
      ExplicitHeight = 241
      object Memo1: TMemo
        Left = 1
        Top = 1
        Width = 725
        Height = 253
        Align = alClient
        Lines.Strings = (
          'Memo1')
        TabOrder = 0
        ExplicitWidth = 216
        ExplicitHeight = 144
      end
    end
  end
end

Docking form:

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    Label1: TLabel;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

end.

object Form2: TForm2
  Left = 0
  Top = 0
  Caption = 'Form2'
  ClientHeight = 103
  ClientWidth = 273
  Color = clBtnFace
  DragKind = dkDock
  DragMode = dmAutomatic
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -12
  Font.Name = 'Segoe UI'
  Font.Style = []
  PixelsPerInch = 96
  TextHeight = 15
  object Label1: TLabel
    Left = 22
    Top = 24
    Width = 227
    Height = 45
    Caption = 'Dockable form'
    DragKind = dkDock
    DragMode = dmAutomatic
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -33
    Font.Name = 'Segoe UI'
    Font.Style = []
    ParentFont = False
  end
end

CodePudding user response:

The dynamics soon become difficult to master with changing dock sites and alignment changes, but I think the following will do what you ask for.

Change the hierarchy of Form1 to the following and note that Panel2 and Memo1 both are childs of Panel1. Panel2 will act as the docking target. I have set Panel2.Width to 8, to have a visual area where to drop Form2. Here are the essential properties:

object Form1: TForm1
  object Button1: TButton
  object Panel1: TPanel
    Caption = 'Panel1'
    object Panel2: TPanel
      Width = 8
      Align = alRight
      Caption = 'Panel2'
      DockSite = True
      OnDockDrop = Panel2DockDrop
      OnDockOver = Panel2DockOver
      OnUnDock = Panel2UnDock
    end
    object Memo1: TMemo
      Align = alClient
    end
  end
end

When Form2 is dragged over Panel2 the OnDockOver event is triggered. Panel2 sets its width to half the width of Panel1, which in turn reduces the Memo1 width with the same amount. (Change as you need)

procedure TForm1.Panel2DockOver(Sender: TObject; Source: TDragDockObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Panel2.Width := Panel1.Width div 2;
end;

When Form2 is dropped on Panel2, the DockRect of the form is set to the rect of Panel2.

procedure TForm1.Panel2DockDrop(Sender: TObject; Source: TDragDockObject; X, Y: Integer);
begin
  Source.DockRect := Rect(Panel2.Width, Panel2.Top, Panel2.Width, Panel2.Height);
end;

When Form2 is undocked from Panel2 it reduces its width to the 8 pixels, which again widen the Memo1 to its original width.

procedure TForm1.Panel2UnDock(Sender: TObject; Client: TControl; NewTarget: TWinControl;
  var Allow: Boolean);
begin
  Panel2.Width := 8;
end;

Here's the complete .dfm of Form1:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 333
  ClientWidth = 425
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -12
  Font.Name = 'Segoe UI'
  Font.Style = []
  OldCreateOrder = True
  PixelsPerInch = 96
  TextHeight = 15
  object Button1: TButton
    Left = 120
    Top = 284
    Width = 153
    Height = 41
    Caption = 'Show dockable form'
    TabOrder = 0
    OnClick = Button1Click
  end
  object Panel1: TPanel
    Left = 8
    Top = 8
    Width = 400
    Height = 257
    Caption = 'Panel1'
    TabOrder = 1
    object Panel2: TPanel
      Left = 391
      Top = 1
      Width = 8
      Height = 255
      Align = alRight
      Caption = 'Panel2'
      DockSite = True
      TabOrder = 0
      OnDockDrop = Panel2DockDrop
      OnDockOver = Panel2DockOver
      OnUnDock = Panel2UnDock
      ExplicitLeft = 394
    end
    object Memo1: TMemo
      Left = 1
      Top = 1
      Width = 390
      Height = 255
      Align = alClient
      Lines.Strings = (
        'Memo1')
      TabOrder = 1
      ExplicitWidth = 725
      ExplicitHeight = 253
    end
  end
end

enter image description here

enter image description here

  • Related