home *** CD-ROM | disk | FTP | other *** search
/ PC World Plus! (NZ) 2001 June / HDC50.iso / Runimage / Delphi50 / Demos / Docking / DOCKFORM.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-11  |  6.4 KB  |  198 lines

  1. unit DockForm;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus,
  7.   ExtCtrls, StdCtrls;
  8.  
  9. type
  10.   TDockableForm = class(TForm)
  11.     Memo1: TMemo;
  12.     procedure FormDockOver(Sender: TObject; Source: TDragDockObject; X,
  13.       Y: Integer; State: TDragState; var Accept: Boolean);
  14.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  15.     procedure FormShow(Sender: TObject);
  16.   private
  17.     function ComputeDockingRect(var DockRect: TRect; MousePos: TPoint): TAlign;
  18.     procedure CMDockClient(var Message: TCMDockClient); message CM_DOCKCLIENT;
  19.   public
  20.   end;
  21.  
  22.  
  23. implementation
  24.  
  25. {$R *.DFM}
  26.  
  27. uses ComCtrls, TabHost, ConjoinHost, Main;
  28.  
  29. procedure TDockableForm.FormDockOver(Sender: TObject;
  30.   Source: TDragDockObject; X, Y: Integer; State: TDragState;
  31.   var Accept: Boolean);
  32. var
  33.   ARect: TRect;
  34. begin
  35.   Accept := (Source.Control is TDockableForm);
  36.   //Draw dock preview depending on where the cursor is relative to our client area
  37.   if Accept and (ComputeDockingRect(ARect, Point(X, Y)) <> alNone) then
  38.     Source.DockRect := ARect;
  39. end;
  40.  
  41. function TDockableForm.ComputeDockingRect(var DockRect: TRect; MousePos: TPoint): TAlign;
  42. var
  43.   DockTopRect,
  44.   DockLeftRect,
  45.   DockBottomRect,
  46.   DockRightRect,
  47.   DockCenterRect: TRect;
  48. begin
  49.   Result := alNone;
  50.   //divide form up into docking "Zones"
  51.   DockLeftRect.TopLeft := Point(0, 0);
  52.   DockLeftRect.BottomRight := Point(ClientWidth div 5, ClientHeight);
  53.  
  54.   DockTopRect.TopLeft := Point(ClientWidth div 5, 0);
  55.   DockTopRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight div 5);
  56.  
  57.   DockRightRect.TopLeft := Point(ClientWidth div 5 * 4, 0);
  58.   DockRightRect.BottomRight := Point(ClientWidth, ClientHeight);
  59.  
  60.   DockBottomRect.TopLeft := Point(ClientWidth div 5, ClientHeight div 5 * 4);
  61.   DockBottomRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight);
  62.  
  63.   DockCenterRect.TopLeft := Point(ClientWidth div 5, ClientHeight div 5);
  64.   DockCenterRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight div 5 * 4);
  65.  
  66.   //Find out where the mouse cursor is, to decide where to draw dock preview.
  67.   if PtInRect(DockLeftRect, MousePos) then
  68.     begin
  69.       Result := alLeft;
  70.       DockRect := DockLeftRect;
  71.       DockRect.Right := ClientWidth div 2;
  72.     end
  73.   else
  74.     if PtInRect(DockTopRect, MousePos) then
  75.       begin
  76.         Result := alTop;
  77.         DockRect := DockTopRect;
  78.         DockRect.Left := 0;
  79.         DockRect.Right := ClientWidth;
  80.         DockRect.Bottom := ClientHeight div 2;
  81.       end
  82.     else
  83.       if PtInRect(DockRightRect, MousePos) then
  84.         begin
  85.           Result := alRight;
  86.           DockRect := DockRightRect;
  87.           DockRect.Left := ClientWidth div 2;
  88.         end
  89.       else
  90.         if PtInRect(DockBottomRect, MousePos) then
  91.           begin
  92.             Result := alBottom;
  93.             DockRect := DockBottomRect;
  94.             DockRect.Left := 0;
  95.             DockRect.Right := ClientWidth;
  96.             DockRect.Top := ClientHeight div 2;
  97.          end
  98.         else
  99.           if PtInRect(DockCenterRect, MousePos) then
  100.           begin
  101.             Result := alClient;
  102.             DockRect := DockCenterRect;
  103.           end;
  104.   if Result = alNone then Exit;
  105.  
  106.   //DockRect is in screen coordinates.
  107.   DockRect.TopLeft := ClientToScreen(DockRect.TopLeft);
  108.   DockRect.BottomRight := ClientToScreen(DockRect.BottomRight);
  109. end;
  110.  
  111. procedure TDockableForm.FormClose(Sender: TObject;
  112.   var Action: TCloseAction);
  113. begin
  114.   //the action taken depends on how the form is docked.
  115.  
  116.   if (HostDockSite is TConjoinDockHost) then
  117.   begin
  118.     //remove the form's caption from the conjoin dock host's caption list
  119.     TConjoinDockHost(HostDockSite).UpdateCaption(Self);
  120.  
  121.     //if we're the last visible form on a conjoined form, hide the form
  122.     if HostDockSite.VisibleDockClientCount <= 1 then
  123.       HostDockSite.Hide;
  124.   end;
  125.  
  126.   //if docked to a panel, tell the panel to hide itself. If there are other
  127.   //visible dock clients on the panel, it ShowDockPanel won't allow it to
  128.   //be hidden
  129.   if (HostDockSite is TPanel) then
  130.     MainForm.ShowDockPanel(HostDockSite as TPanel, False, nil);
  131.  
  132.   Action := caHide;
  133. end;
  134.  
  135. procedure TDockableForm.CMDockClient(var Message: TCMDockClient);
  136. var
  137.   ARect: TRect;
  138.   DockType: TAlign;
  139.   Host: TForm;
  140.   Pt: TPoint;
  141. begin
  142.   //Overriding this message allows the dock form to create host forms
  143.   //depending on the mouse position when docking occurs. If we don't override
  144.   //this message, the form will use VCL's default DockManager.
  145.  
  146.   //NOTE: the only time ManualDock can be safely called during a drag
  147.   //operation is we override processing of CM_DOCKCLIENT.
  148.  
  149.   if Message.DockSource.Control is TDockableForm then
  150.   begin
  151.  
  152.     //Find out how to dock (Using a TAlign as the result of ComputeDockingRect)
  153.     Pt.x := Message.MousePos.x;
  154.     Pt.y := Message.MousePos.y;
  155.     DockType := ComputeDockingRect(ARect, Pt);
  156.  
  157.     //if we are over a dockable form docked to a panel in the
  158.     //main window, manually dock the dragged form to the panel with
  159.     //the correct orientation.
  160.     if (HostDockSite is TPanel) then
  161.     begin
  162.       Message.DockSource.Control.ManualDock(HostDockSite, nil, DockType);
  163.       Exit;
  164.     end;
  165.  
  166.     //alClient => Create a TabDockHost and manually dock both forms to the PageControl
  167.     //owned by the TabDockHost.
  168.     if DockType = alClient then
  169.     begin
  170.       Host := TTabDockHost.Create(Application);
  171.       Host.BoundsRect := Self.BoundsRect;
  172.       Self.ManualDock(TTabDockHost(Host).PageControl1, nil, alClient);
  173.       Message.DockSource.Control.ManualDock(TTabDockHost(Host).PageControl1, nil, alClient);
  174.       Host.Visible := True;
  175.     end
  176.     //if DockType <> alClient, create the ConjoinDockHost and manually dock both
  177.     //forms to it. Be sure to make dockable forms non-dockable when hosted by
  178.     // ConjoinDockForm, since it is using the VCL default DockManager.
  179.     else begin
  180.       Host := TConjoinDockHost.Create(Application);
  181.       Host.BoundsRect := Self.BoundsRect;
  182.       Self.ManualDock(Host, nil, alNone);
  183.       Self.DockSite := False;
  184.       Message.DockSource.Control.ManualDock(Host, nil, DockType);
  185.       TDockableForm(Message.DockSource.Control).DockSite := False;
  186.       Host.Visible := True;
  187.     end;
  188.   end;
  189. end;
  190.  
  191. procedure TDockableForm.FormShow(Sender: TObject);
  192. begin
  193.   if HostDockSite is TConjoinDockHost then
  194.     TConjoinDockHost(HostDockSite).UpdateCaption(nil);
  195. end;
  196.  
  197. end.
  198.