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