www.pudn.com > @@VCLSkin24.rar > uDockForm.pas


unit uDockForm; 
 
interface 
 
uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus, 
  ExtCtrls, StdCtrls, ComCtrls; 
 
type 
  TDockableForm = class(TForm) 
    Button1: TButton; 
    CheckBox1: TCheckBox; 
    UpDown1: TUpDown; 
    procedure FormDockOver(Sender: TObject; Source: TDragDockObject; X, 
      Y: Integer; State: TDragState; var Accept: Boolean); 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
    procedure FormShow(Sender: TObject); 
  private 
    function ComputeDockingRect(var DockRect: TRect; MousePos: TPoint): TAlign; 
    procedure CMDockClient(var Message: TCMDockClient); message CM_DOCKCLIENT; 
  public 
  end; 
 
 
implementation 
 
{$R *.dfm} 
 
uses uTabHost, uConjoinHost, uMain; 
 
procedure TDockableForm.FormDockOver(Sender: TObject; 
  Source: TDragDockObject; X, Y: Integer; State: TDragState; 
  var Accept: Boolean); 
var 
  ARect: TRect; 
begin 
  Accept := (Source.Control is TDockableForm); 
  //Draw dock preview depending on where the cursor is relative to our client area 
  if Accept and (ComputeDockingRect(ARect, Point(X, Y)) <> alNone) then 
    Source.DockRect := ARect; 
end; 
 
function TDockableForm.ComputeDockingRect(var DockRect: TRect; MousePos: TPoint): TAlign; 
var 
  DockTopRect, 
  DockLeftRect, 
  DockBottomRect, 
  DockRightRect, 
  DockCenterRect: TRect; 
begin 
  Result := alNone; 
  //divide form up into docking "Zones" 
  DockLeftRect.TopLeft := Point(0, 0); 
  DockLeftRect.BottomRight := Point(ClientWidth div 5, ClientHeight); 
 
  DockTopRect.TopLeft := Point(ClientWidth div 5, 0); 
  DockTopRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight div 5); 
 
  DockRightRect.TopLeft := Point(ClientWidth div 5 * 4, 0); 
  DockRightRect.BottomRight := Point(ClientWidth, ClientHeight); 
 
  DockBottomRect.TopLeft := Point(ClientWidth div 5, ClientHeight div 5 * 4); 
  DockBottomRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight); 
 
  DockCenterRect.TopLeft := Point(ClientWidth div 5, ClientHeight div 5); 
  DockCenterRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight div 5 * 4); 
 
  //Find out where the mouse cursor is, to decide where to draw dock preview. 
  if PtInRect(DockLeftRect, MousePos) then 
    begin 
      Result := alLeft; 
      DockRect := DockLeftRect; 
      DockRect.Right := ClientWidth div 2; 
    end 
  else 
    if PtInRect(DockTopRect, MousePos) then 
      begin 
        Result := alTop; 
        DockRect := DockTopRect; 
        DockRect.Left := 0; 
        DockRect.Right := ClientWidth; 
        DockRect.Bottom := ClientHeight div 2; 
      end 
    else 
      if PtInRect(DockRightRect, MousePos) then 
        begin 
          Result := alRight; 
          DockRect := DockRightRect; 
          DockRect.Left := ClientWidth div 2; 
        end 
      else 
        if PtInRect(DockBottomRect, MousePos) then 
          begin 
            Result := alBottom; 
            DockRect := DockBottomRect; 
            DockRect.Left := 0; 
            DockRect.Right := ClientWidth; 
            DockRect.Top := ClientHeight div 2; 
         end 
        else 
          if PtInRect(DockCenterRect, MousePos) then 
          begin 
            Result := alClient; 
            DockRect := DockCenterRect; 
          end; 
  if Result = alNone then Exit; 
 
  //DockRect is in screen coordinates. 
  DockRect.TopLeft := ClientToScreen(DockRect.TopLeft); 
  DockRect.BottomRight := ClientToScreen(DockRect.BottomRight); 
end; 
 
procedure TDockableForm.FormClose(Sender: TObject; 
  var Action: TCloseAction); 
begin 
  //the action taken depends on how the form is docked. 
 
  if (HostDockSite is TConjoinDockHost) then 
  begin 
    //remove the form's caption from the conjoin dock host's caption list 
    TConjoinDockHost(HostDockSite).UpdateCaption(Self); 
 
    //if we're the last visible form on a conjoined form, hide the form 
    if HostDockSite.VisibleDockClientCount <= 1 then 
      HostDockSite.Hide; 
  end; 
 
  //if docked to a panel, tell the panel to hide itself. If there are other 
  //visible dock clients on the panel, it ShowDockPanel won't allow it to 
  //be hidden 
  if (HostDockSite is TPanel) then 
    MainForm.ShowDockPanel(HostDockSite as TPanel, False, nil); 
 
  Action := caHide; 
end; 
 
procedure TDockableForm.CMDockClient(var Message: TCMDockClient); 
var 
  ARect: TRect; 
  DockType: TAlign; 
  Host: TForm; 
  Pt: TPoint; 
begin 
  //Overriding this message allows the dock form to create host forms 
  //depending on the mouse position when docking occurs. If we don't override 
  //this message, the form will use VCL's default DockManager. 
 
  //NOTE: the only time ManualDock can be safely called during a drag 
  //operation is we override processing of CM_DOCKCLIENT. 
 
  if Message.DockSource.Control is TDockableForm then 
  begin 
 
    //Find out how to dock (Using a TAlign as the result of ComputeDockingRect) 
    Pt.x := Message.MousePos.x; 
    Pt.y := Message.MousePos.y; 
    DockType := ComputeDockingRect(ARect, Pt); 
 
    //if we are over a dockable form docked to a panel in the 
    //main window, manually dock the dragged form to the panel with 
    //the correct orientation. 
    if (HostDockSite is TPanel) then 
    begin 
      Message.DockSource.Control.ManualDock(HostDockSite, nil, DockType); 
      Exit; 
    end; 
 
    //alClient => Create a TabDockHost and manually dock both forms to the PageControl 
    //owned by the TabDockHost. 
    if DockType = alClient then 
    begin 
      Host := TTabDockHost.Create(Application); 
      Host.BoundsRect := Self.BoundsRect; 
      Self.ManualDock(TTabDockHost(Host).PageControl1, nil, alClient); 
      Message.DockSource.Control.ManualDock(TTabDockHost(Host).PageControl1, nil, alClient); 
      Host.Visible := True; 
    end 
    //if DockType <> alClient, create the ConjoinDockHost and manually dock both 
    //forms to it. Be sure to make dockable forms non-dockable when hosted by 
    // ConjoinDockForm, since it is using the VCL default DockManager. 
    else begin 
      Host := TConjoinDockHost.Create(Application); 
      Host.BoundsRect := Self.BoundsRect; 
      Self.ManualDock(Host, nil, alNone); 
      Self.DockSite := False; 
      Message.DockSource.Control.ManualDock(Host, nil, DockType); 
      TDockableForm(Message.DockSource.Control).DockSite := False; 
      Host.Visible := True; 
    end; 
  end; 
end; 
 
procedure TDockableForm.FormShow(Sender: TObject); 
begin 
  if HostDockSite is TConjoinDockHost then 
    TConjoinDockHost(HostDockSite).UpdateCaption(nil); 
  if MainForm.skindata1.active then 
     MainForm.skindata1.skinform(handle); 
end; 
 
end.