home *** CD-ROM | disk | FTP | other *** search
/ Delphi Anthology / aDELPHI.iso / Runimage / Delphi50 / Source / Vcl / toolwin.pas < prev    next >
Pascal/Delphi Source File  |  1999-08-11  |  11KB  |  392 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Borland Delphi Visual Component Library         }
  5. {                                                       }
  6. {       Copyright (c) 1995,99 Inprise Corporation       }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit ToolWin;
  11.  
  12. {$R-,H+,X+}
  13.  
  14. interface
  15.  
  16. uses Windows, Messages, Classes, Controls, Forms;
  17.  
  18. type
  19.  
  20. { TToolWindow }
  21.  
  22.   TEdgeBorder = (ebLeft, ebTop, ebRight, ebBottom);
  23.   TEdgeBorders = set of TEdgeBorder;
  24.  
  25.   TEdgeStyle = (esNone, esRaised, esLowered);
  26.  
  27.   TToolWindow = class(TWinControl)
  28.   private
  29.     FEdgeBorders: TEdgeBorders;
  30.     FEdgeInner: TEdgeStyle;
  31.     FEdgeOuter: TEdgeStyle;
  32.     procedure SetEdgeBorders(Value: TEdgeBorders);
  33.     procedure SetEdgeInner(Value: TEdgeStyle);
  34.     procedure SetEdgeOuter(Value: TEdgeStyle);
  35.     procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
  36.     procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT;
  37.     procedure CMBorderChanged(var Message: TMessage); message CM_BORDERCHANGED;
  38.     procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  39.   public
  40.     constructor Create(AOwner: TComponent); override;
  41.     property EdgeBorders: TEdgeBorders read FEdgeBorders write SetEdgeBorders default [ebLeft, ebTop, ebRight, ebBottom];
  42.     property EdgeInner: TEdgeStyle read FEdgeInner write SetEdgeInner default esRaised;
  43.     property EdgeOuter: TEdgeStyle read FEdgeOuter write SetEdgeOuter default esLowered;
  44.   end;
  45.  
  46. { TToolDragDockObject }
  47.  
  48.   TToolDockObject = class(TDragDockObject)
  49.   protected
  50.     procedure AdjustDockRect(ARect: TRect); override;
  51.     procedure DrawDragDockImage; override;
  52.     procedure EraseDragDockImage; override;
  53.   public
  54.     constructor Create(AControl: TControl); override;
  55.   end;
  56.  
  57. { TToolDockForm }
  58.  
  59.   TSizingOrientation = (soNone, soHorizontal, soVertical);
  60.  
  61.   TToolDockForm = class(TCustomDockForm)
  62.   private
  63.     FPrevWidth: Integer;
  64.     FPrevHeight: Integer;
  65.     FSizingAdjustH: Integer;
  66.     FSizingAdjustW: Integer;
  67.     FSizingOrientation: TSizingOrientation;
  68.     FUpdatingSize: Boolean;
  69.     procedure WMNCCreate(var Message: TWMNCCreate); message WM_NCCREATE;
  70.     procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
  71.     procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN;
  72.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  73.     procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
  74.   protected
  75.     function CanResize(var NewWidth, NewHeight: Integer): Boolean; override;
  76.     procedure CreateParams(var Params: TCreateParams); override;
  77.     procedure DoAddDockClient(Client: TControl; const ARect: TRect); override;
  78.   public
  79.     constructor Create(AOwner: TComponent); override;
  80.   end;
  81.  
  82. implementation
  83.  
  84. uses SysUtils;
  85.  
  86. { TToolWindow }
  87.  
  88. constructor TToolWindow.Create(AOwner: TComponent);
  89. begin
  90.   inherited Create(AOwner);
  91.   FEdgeBorders := [ebLeft, ebTop, ebRight, ebBottom];
  92.   FEdgeInner := esRaised;
  93.   FEdgeOuter := esLowered;
  94. end;
  95.  
  96. procedure TToolWindow.SetEdgeBorders(Value: TEdgeBorders);
  97. begin
  98.   if FEdgeBorders <> Value then
  99.   begin
  100.     FEdgeBorders := Value;
  101.     RecreateWnd;
  102.   end;
  103. end;
  104.  
  105. procedure TToolWindow.SetEdgeInner(Value: TEdgeStyle);
  106. begin
  107.   if FEdgeInner <> Value then
  108.   begin
  109.     FEdgeInner := Value;
  110.     RecreateWnd;
  111.   end;
  112. end;
  113.  
  114. procedure TToolWindow.SetEdgeOuter(Value: TEdgeStyle);
  115. begin
  116.   if FEdgeOuter <> Value then
  117.   begin
  118.     FEdgeOuter := Value;
  119.     RecreateWnd;
  120.   end;
  121. end;
  122.  
  123. procedure TToolWindow.WMNCCalcSize(var Message: TWMNCCalcSize);
  124. var
  125.   EdgeSize: Integer;
  126. begin
  127.   with Message.CalcSize_Params^ do
  128.   begin
  129.     InflateRect(rgrc[0], -BorderWidth, -BorderWidth);
  130.     EdgeSize := 0;
  131.     if EdgeInner <> esNone then Inc(EdgeSize, 1);
  132.     if EdgeOuter <> esNone then Inc(EdgeSize, 1);
  133.     with rgrc[0] do
  134.     begin
  135.       if ebLeft in FEdgeBorders then Inc(Left, EdgeSize);
  136.       if ebTop in FEdgeBorders then Inc(Top, EdgeSize);
  137.       if ebRight in FEdgeBorders then Dec(Right, EdgeSize);
  138.       if ebBottom in FEdgeBorders then Dec(Bottom, EdgeSize);
  139.     end;
  140.   end;
  141.   inherited;
  142. end;
  143.  
  144. procedure TToolWindow.WMNCPaint(var Message: TMessage);
  145. const
  146.   InnerStyles: array[TEdgeStyle] of Integer = (0, BDR_RAISEDINNER, BDR_SUNKENINNER);
  147.   OuterStyles: array[TEdgeStyle] of Integer = (0, BDR_RAISEDOUTER, BDR_SUNKENOUTER);
  148.   Ctl3DStyles: array[Boolean] of Integer = (BF_MONO, 0);
  149. var
  150.   DC: HDC;
  151.   RC, RW: TRect;
  152. begin
  153.   { Get window DC that is clipped to the non-client area }
  154.   DC := GetWindowDC(Handle);
  155.   try
  156.     Windows.GetClientRect(Handle, RC);
  157.     GetWindowRect(Handle, RW);
  158.     MapWindowPoints(0, Handle, RW, 2);
  159.     OffsetRect(RC, -RW.Left, -RW.Top);
  160.     ExcludeClipRect(DC, RC.Left, RC.Top, RC.Right, RC.Bottom);
  161.     { Draw borders in non-client area }
  162.     OffsetRect(RW, -RW.Left, -RW.Top);
  163.     DrawEdge(DC, RW, InnerStyles[FEdgeInner] or OuterStyles[FEdgeOuter],
  164.       Byte(FEdgeBorders) or Ctl3DStyles[Ctl3D] or BF_ADJUST);
  165.     { Erase parts not drawn }
  166.     IntersectClipRect(DC, RW.Left, RW.Top, RW.Right, RW.Bottom);
  167.     Windows.FillRect(DC, RW, Brush.Handle);
  168.   finally
  169.     ReleaseDC(Handle, DC);
  170.   end;
  171. end;
  172.  
  173. procedure TToolWindow.CMBorderChanged(var Message: TMessage);
  174. begin
  175.   RecreateWnd;
  176.   inherited;
  177. end;
  178.  
  179. procedure TToolWindow.CMCtl3DChanged(var Message: TMessage);
  180. begin
  181.   inherited;
  182.   if FEdgeBorders <> [] then RecreateWnd;
  183. end;
  184.  
  185. { TToolDockObject }
  186.  
  187. constructor TToolDockObject.Create(AControl: TControl);
  188. var
  189.   P: TPoint;
  190. begin
  191.   inherited Create(AControl);
  192.   if not AControl.Floating then
  193.   begin
  194.     GetCursorPos(P);
  195.     AControl.ManualFloat(Bounds(P.X - 10, P.Y - 10, AControl.UndockWidth,
  196.       AControl.UndockHeight));
  197.   end;
  198. end;
  199.  
  200. procedure TToolDockObject.AdjustDockRect(ARect: TRect);
  201. var
  202.   R: TRect;
  203. begin
  204. exit;
  205.   { if Control is floating then use its floating dock site's bounds }
  206.   if Control.Floating and (Control.HostDockSite <> nil) then
  207.   begin
  208.     R := Control.HostDockSite.BoundsRect;
  209.     if Control.HostDockSite.Parent <> nil then
  210.       MapWindowPoints(Control.HostDockSite.Parent.Handle, 0, R, 2);
  211.     if PtInRect(R, DragPos) then Exit;
  212.   end;
  213.   inherited AdjustDockRect(ARect)
  214. end;
  215.  
  216. procedure TToolDockObject.DrawDragDockImage;
  217. var
  218.   P: TPoint;
  219.   Form: TCustomForm;
  220. begin
  221.   if not Control.Floating then
  222.     inherited DrawDragDockImage
  223.   else
  224.   begin
  225.     Form := GetParentForm(Control);
  226.     if Form <> nil then
  227.     begin
  228.       P := Point(Control.Left, Control.Top);
  229.       if Control <> Form then
  230.         MapWindowPoints(Form.Handle, 0, P, 1);
  231.       Form.BoundsRect := Bounds(DockRect.Left + Form.Left - P.X,
  232.         DockRect.Top + Form.Top - P.Y,
  233.         DockRect.Right - DockRect.Left + Form.Width - Control.Width,
  234.         DockRect.Bottom - DockRect.Top + Form.Height - Control.Height);
  235.     end;
  236.   end;
  237. end;
  238.  
  239. procedure TToolDockObject.EraseDragDockImage;
  240. begin
  241.   if not Control.Floating then
  242.     inherited EraseDragDockImage
  243. end;
  244.  
  245. { TToolDockForm }
  246.  
  247. constructor TToolDockForm.Create(AOwner: TComponent);
  248. begin
  249.   inherited Create(AOwner);
  250.   BorderWidth := 1;
  251. end;
  252.  
  253. procedure TToolDockForm.CreateParams(var Params: TCreateParams);
  254. begin
  255.   inherited CreateParams(Params);
  256.   with Params do
  257.     Style := Style or WS_POPUP;
  258. end;
  259.  
  260. function TToolDockForm.CanResize(var NewWidth, NewHeight: Integer): Boolean;
  261. var
  262.   W, H, NcW, NcH: Integer;
  263. begin
  264.   Result := True;
  265.   if FUpdatingSize or (FSizingOrientation = soNone) or (DockClientCount = 0) or
  266.     (NewWidth = Width) and (NewHeight = Height) then Exit;
  267.   W := NewWidth;
  268.   H := NewHeight;
  269.   case FSizingOrientation of
  270.     soHorizontal: Inc(H, FSizingAdjustH);
  271.     soVertical: Inc(W, FSizingAdjustW);
  272.     soNone: Exit;
  273.   else
  274.     Result := False;
  275.     Exit;
  276.   end;
  277.   FPrevWidth := Width;
  278.   FPrevHeight := Height;
  279.   with DockClients[0] do
  280.   begin
  281.     NcW := Self.Width - Width;
  282.     NcH := Self.Height - Height;
  283.     FUpdatingSize := True;
  284.     try
  285.       SetBounds(Left, Top, W - NcW, H - NcH);
  286.     finally
  287.       FUpdatingSize := False;
  288.     end;
  289.     NewWidth := Width + NcW;
  290.     NewHeight := Height + NcH;
  291.   end;
  292.   Result := (Width <> NewWidth) or (Height <> NewHeight);
  293. end;
  294.  
  295. procedure TToolDockForm.DoAddDockClient(Client: TControl; const ARect: TRect);
  296. begin
  297.   inherited DoAddDockClient(Client, ARect);
  298.   Client.Align := alNone;
  299.   AutoSize := True;
  300. end;
  301.  
  302. procedure TToolDockForm.WMNCCreate(var Message: TWMNCCreate);
  303.  
  304.   procedure ModifySystemMenu;
  305.   var
  306.     SysMenu: HMENU;
  307.   begin
  308.     if (BorderStyle <> bsNone) and (biSystemMenu in BorderIcons) and
  309.       (FormStyle <> fsMDIChild) then
  310.     begin
  311.       { Show only the Make the system menu look like a dialog which has only Move and Close }
  312.       SysMenu := GetSystemMenu(Handle, False);
  313.       DeleteMenu(SysMenu, SC_TASKLIST, MF_BYCOMMAND);
  314.       DeleteMenu(SysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
  315.       DeleteMenu(SysMenu, SC_MINIMIZE, MF_BYCOMMAND);
  316.       DeleteMenu(SysMenu, SC_RESTORE, MF_BYCOMMAND);
  317.     end;
  318.   end;
  319.  
  320. begin
  321.   inherited;
  322.   if not (csDesigning in ComponentState) then ModifySystemMenu;
  323. end;
  324.  
  325. procedure TToolDockForm.WMNCHitTest(var Message: TWMNCHitTest);
  326. var
  327.   Bounds: TRect;
  328.   CX, CY: Integer;
  329. begin
  330.   inherited;
  331.   Bounds := BoundsRect;
  332.   CX := GetSystemMetrics(SM_CXFRAME);
  333.   CY := GetSystemMetrics(SM_CYFRAME);
  334.   InflateRect(Bounds, -CX, -CY);
  335.   with Message do
  336.     case Result of
  337.       HTTOPLEFT:
  338.         if YPos < Bounds.Top then
  339.           Result := HTTOP
  340.         else
  341.           Result := HTLEFT;
  342.       HTTOPRIGHT:
  343.         if YPos < Bounds.Top then
  344.           Result := HTTOP
  345.         else
  346.           Result := HTRIGHT;
  347.       HTCLIENT: Result := HTCAPTION;
  348.       HTBOTTOMLEFT:
  349.         if YPos > Bounds.Bottom then
  350.           Result := HTBOTTOM
  351.         else
  352.           Result := HTLEFT;
  353.       HTGROWBOX, HTBOTTOMRIGHT:
  354.         if YPos > Bounds.Bottom then
  355.           Result := HTBOTTOM
  356.         else
  357.           Result := HTRIGHT;
  358.     end;
  359. end;
  360.  
  361. procedure TToolDockForm.WMNCLButtonDown(var Message: TWMNCLButtonDown);
  362. begin
  363.   FSizingOrientation := soNone;
  364.   case Message.HitTest of
  365.     HTLEFT, HTRIGHT: FSizingOrientation := soHorizontal;
  366.     HTTOP, HTBOTTOM: FSizingOrientation := soVertical;
  367.   end;
  368.   inherited;
  369. end;
  370.  
  371. procedure TToolDockForm.WMSize(var Message: TWMSize);
  372. begin
  373.   inherited;
  374.   case FSizingOrientation of
  375.     soHorizontal: Inc(FSizingAdjustH, Height - FPrevHeight);
  376.     soVertical: Inc(FSizingAdjustW, Width - FPrevWidth);
  377.   end;
  378. end;
  379.  
  380. procedure TToolDockForm.WMSysCommand(var Message: TWMSysCommand);
  381. begin
  382.   if Message.CmdType and $FFF0 = SC_SIZE then
  383.   begin
  384.     FSizingAdjustW := 0;
  385.     FSizingAdjustH := 0;
  386.   end;
  387.   inherited;
  388.   FSizingOrientation := soNone;
  389. end;
  390.  
  391. end.
  392.