home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / DELPHI32 / FORM_UTL / MINMAX / MINMAX.ZIP / MinMax.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1996-08-30  |  10.8 KB  |  292 lines

  1. { -------------------------------------------------------------------------------------}
  2. { A "MinMax Form Sizer" component for Delphi32.                                        }
  3. { Copyright 1996, Patrick Brisacier.  All Rights Reserved.                             }
  4. { This component can be freely used and distributed in commercial and private          }
  5. { environments, provided this notice is not modified in any way.                       }
  6. { -------------------------------------------------------------------------------------}
  7. { Feel free to contact us if you have any questions, comments or suggestions at        }
  8. { PBrisacier@mail.dotcom.fr (Patrick Brisacier)                                        }
  9. { -------------------------------------------------------------------------------------}
  10. { Thanks to Brad Stowers (bstowers@pobox.com) for his help.                            }
  11. { -------------------------------------------------------------------------------------}
  12. { Date last modified:  08/20/96                                                        }
  13. { -------------------------------------------------------------------------------------}
  14.  
  15. { -------------------------------------------------------------------------------------}
  16. { TMinMax v1.01                                                                        }
  17. { -------------------------------------------------------------------------------------}
  18. { Description:                                                                         }
  19. {   A component that allows you to minimize and maximize forms size. You can also      }
  20. {   allow user to resize or not a running form.                                        }
  21. { Properties:                                                                          }
  22. {  property MaxSize: TMinMaxPoint;                                                     }
  23. {  property MaxPosition: TMinMaxPoint;                                                 }
  24. {  property MinTrackSize: TMinMaxPoint;                                                }
  25. {  property MaxTrackSize: TMinMaxPoint;                                                }
  26. {  property Options: TMinMaxOptions;                                                   }
  27. {                                                                                      }
  28. { See example contained in example.zip file for more details.                          }
  29. { -------------------------------------------------------------------------------------}
  30. { Revision History:                                                                    }
  31. { 1.00:  + Initial release                                                             }
  32. { 1.01:  + Problem corrected in the HookWndProc by Brad Stowers (bstowers@pobox.com)   }
  33. { -------------------------------------------------------------------------------------}
  34.  
  35. unit MinMax;
  36.  
  37. interface
  38.  
  39. uses
  40.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  41.   DsgnIntf, TypInfo, ExtCtrls;
  42.  
  43. type
  44.   TMinMaxOption = (opAllowResize, opMaxPosition, opMaxSize, opMaxTrackSize, opMinTrackSize);
  45.   TMinMaxOptions = set of TMinMaxOption;
  46.  
  47.   TMinMaxPoint = class(TPersistent)
  48.   private
  49.     FX, FY: LongInt;
  50.   public
  51.     function GetTPoint: TPoint;
  52.     procedure Assign(Source: TPersistent); override;
  53.   published
  54.     property X: LongInt
  55.              read FX write FX;
  56.     property Y: LongInt
  57.              read FY write FY;
  58.   end;
  59.  
  60.   TMinMax = class(TCustomControl)
  61.   private
  62.     { DΘclarations privΘes }
  63.     FMaxSize: TMinMaxPoint;
  64.     FMaxPosition: TMinMaxPoint;
  65.     FMinTrackSize: TMinMaxPoint;
  66.     FMaxTrackSize: TMinMaxPoint;
  67.     FOptions: TMinMaxOptions;
  68.     OldWndProc: TFarProc;
  69.     NewWndProc: Pointer;
  70.     procedure HookParent;
  71.     procedure UnhookParent;
  72.     procedure HookWndProc(var Message: TMessage);
  73.   protected
  74.     { DΘclarations protΘgΘes }
  75.     procedure Paint; override;
  76.     procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  77.     procedure Loaded; override;
  78.     procedure SetParent(Value: TWinControl); override;
  79.   public
  80.     { DΘclarations publiques }
  81.     constructor Create(AOwner: TComponent); override;
  82.     destructor Destroy; override;
  83.   published
  84.     { DΘclarations publiΘes }
  85.     property MaxSize: TMinMaxPoint
  86.              read FMaxSize write FMaxSize;
  87.     property MaxPosition: TMinMaxPoint
  88.              read FMaxPosition write FMaxPosition;
  89.     property MinTrackSize: TMinMaxPoint
  90.              read FMinTrackSize write FMinTrackSize;
  91.     property MaxTrackSize: TMinMaxPoint
  92.              read FMaxTrackSize write FMaxTrackSize;
  93.     property Options: TMinMaxOptions
  94.              read FOptions write FOptions;
  95.   end;
  96.  
  97. procedure Register;
  98.  
  99. implementation
  100.  
  101. var
  102.   aBitmap: TBitmap;
  103.   Loaded: Boolean;
  104.  
  105. procedure LoadBitmap;
  106. begin
  107.   if Loaded then exit;
  108.   Loaded := True;
  109.   if aBitmap = nil then aBitmap := TBitmap.Create;
  110.   try
  111.     aBitmap.LoadFromResourceName(HInstance, 'TMINMAX');
  112.   except
  113.     on E:Exception do ShowMessage(E.Message);
  114.   end;
  115. end;
  116.  
  117. function TMinMaxPoint.GetTPoint: TPoint;
  118. begin
  119.   Result := Point(FX, FY);
  120. end;
  121.  
  122. procedure TMinMaxPoint.Assign(Source: TPersistent);
  123. begin
  124.   FX := (Source as TMinMaxPoint).X;
  125.   FY := (Source as TMinMaxPoint).Y;
  126. end;
  127.  
  128.  
  129. constructor TMinMax.Create(AOwner: TComponent);
  130. begin
  131.   inherited Create(AOwner);
  132.   { set default value }
  133.   FOptions := [opAllowResize, opMaxSize, opMaxPosition, opMinTrackSize, opMaxTrackSize];
  134.   { Initialize variables }
  135.   NewWndProc := nil;
  136.   OldWndProc := nil;
  137.   FMaxSize := TMinMaxPoint.Create;
  138.   FMaxPosition := TMinMaxPoint.Create;
  139.   FMinTrackSize := TMinMaxPoint.Create;
  140.   FMaxTrackSize := TMinMaxPoint.Create;
  141. end;
  142.  
  143. destructor TMinMax.Destroy;
  144. begin
  145.   { Always make sure that the hook is removed. }
  146.   UnhookParent;
  147.   FMaxSize.Free;
  148.   FMaxPosition.Free;
  149.   FMinTrackSize.Free;
  150.   FMaxTrackSize.Free;
  151.   inherited Destroy;
  152. end;
  153.  
  154. procedure TMinMax.Paint;
  155. var
  156.   MonRect, BitmapRect: TRect;
  157. begin
  158.   if csDesigning in ComponentState then begin
  159.     MonRect := Rect(0,0,Width,Height);
  160.     Frame3D(Canvas, MonRect, clBtnHighlight, clBlack, 1);
  161.     Frame3D(Canvas, MonRect, clBtnFace, clBtnShadow, 1);
  162.     Canvas.Brush.color := clBtnFace;
  163.     Canvas.FillRect(MonRect);
  164.     BitmapRect := Bounds(0,0,aBitmap.Width, aBitmap.Height);
  165.     MonRect := Bounds((Width - aBitmap.Width) div 2,
  166.                       (Height - aBitmap.Height) div 2,
  167.                       aBitmap.Width, aBitmap.Height);
  168.     Canvas.BrushCopy(MonRect, aBitmap, BitmapRect, aBitmap.TransparentColor);
  169.   end;
  170.   inherited Paint;
  171. end;
  172.  
  173. procedure TMinMax.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  174. begin
  175.   if csDesigning in ComponentState then
  176.   begin
  177.     AWidth := 28;
  178.     AHeight := 28;
  179.   end;
  180.   inherited SetBounds(ALeft, ATop, AWidth, AHeight);
  181. end;
  182.  
  183. procedure TMinMax.Loaded;
  184. begin
  185.   if csDesigning in ComponentState then LoadBitmap
  186.   else Visible := False;
  187.   inherited Loaded;
  188. end;
  189.  
  190. { This procedure is used to get the parent's window procedure, save it,      }
  191. { and replace it with our own.  This allows see all of the parent's messages }
  192. { before it does.                                                            }
  193. procedure TMinMax.HookParent;
  194. begin
  195.   { If there is no parent, we can't hook it. }
  196.   if Parent = NIL then exit;
  197.   { Get the old window procedure via API call and store it. }
  198.   OldWndProc := TFarProc(GetWindowLong(Parent.Handle, GWL_WNDPROC));
  199.   { Convert our object method into something Windows knows how to call }
  200.   NewWndProc := MakeObjectInstance(HookWndProc);
  201.   { Install it as the new Parent window procedure }
  202.   SetWindowLong(Parent.Handle, GWL_WNDPROC, LongInt(NewWndProc));
  203. end;
  204.  
  205. { Remove our window function and reinstall the original. }
  206. procedure TMinMax.UnhookParent;
  207. begin
  208.   { We must have a parent, and we must have already hooked it. }
  209.   if (Parent <> NIL) and assigned(OldWndProc) then
  210.     { Set back to original window procedure }
  211.     SetWindowLong(Parent.Handle, GWL_WNDPROC, LongInt(OldWndProc));
  212.   { If we have created a window procedure via MakeObjectInstance, }
  213.   { it must be disposed of.                                       }
  214.   if assigned(NewWndProc) then
  215.     FreeObjectInstance(NewWndProc);
  216.   { Reset variables to NIL }
  217.   NewWndProc := NIL;
  218.   OldWndProc := NIL;
  219. end;
  220.  
  221. { The window procedure that is installed into our parent. }
  222. procedure TMinMax.HookWndProc(var Message: TMessage);
  223. var
  224.   Test: LResult;
  225. begin
  226.   { If there's no parent, something has really gone wrong. }
  227.   if Parent = NIL then exit;
  228.   with Message do begin
  229.     { If Parent gets a WM_SIZE message, it has been resized }
  230.     if (Msg = WM_GETMINMAXINFO) then begin
  231.       if opMaxSize in FOptions then
  232.         PMinMaxInfo(LParam)^.ptMaxSize := FMaxSize.GetTPoint;
  233.       if opMaxPosition in FOptions then
  234.         PMinMaxInfo(LParam)^.ptMaxPosition := FMaxPosition.GetTPoint;
  235.       if opAllowResize in FOptions then begin
  236.         if opMinTrackSize in FOptions then
  237.           PMinMaxInfo(LParam)^.ptMinTrackSize := FMinTrackSize.GetTPoint;
  238.         if opMaxTrackSize in FOptions then
  239.           PMinMaxInfo(LParam)^.ptMaxTrackSize := FMaxTrackSize.GetTPoint;
  240.       end
  241.       else begin
  242.         PMinMaxInfo(LParam)^.ptMinTrackSize := Point(Parent.Width,Parent.Height);
  243.         PMinMaxInfo(LParam)^.ptMaxTrackSize := Point(Parent.Width,Parent.Height);
  244.       end;
  245.     end;
  246.     { message WM_INITMENUPOPUP }
  247.     if (Msg = WM_INITMENUPOPUP) and not (opAllowResize in Options) then
  248.     begin
  249.       if TWMInitMenuPopup(Message).SystemMenu then
  250.          EnableMenuItem(TWMInitMenuPopup(Message).MenuPopup, SC_SIZE,MF_BYCOMMAND or MF_GRAYED);
  251.     end;
  252.     { ALWAYS call the old window procedure so the parent can process its   }
  253.     { messages.  Thanks to Gary Frerking for pointing me at CallWindowProc }
  254.     { I was trying to call the function directly, which died horribly.     }
  255.     Result := CallWindowProc(OldWndProc, Parent.Handle, Msg, wParam, lParam);
  256.  
  257.     // From Brad:
  258.     //   WM_NCHITTEST needs to be processed after calling the old window's proc.
  259.     { message WM_NCHitTest }
  260.     if (Msg = WM_NCHitTest) and not (opAllowResize in Options) then begin
  261.       if Result in [HTLEFT, HTRIGHT, HTBOTTOM, HTBOTTOMRIGHT,
  262.             HTBOTTOMLEFT, HTTOP, HTTOPRIGHT, HTTOPLEFT] then
  263.         Result:= HTNOWHERE;
  264.     end;
  265.   end;
  266. end;
  267.  
  268. { A Parent has been assigned or changed.  Unhook old parent and install }
  269. { hook in new parent.                                                   }
  270. procedure TMinMax.SetParent(Value: TWinControl);
  271. begin
  272.   { UnhookParent knows if the current parent has been hooked or not }
  273.   UnhookParent;
  274.   { Set Parent to the new value }
  275.   inherited SetParent(Value);
  276.   { Hook the new parent's window procedure }
  277.   HookParent;
  278. end;
  279.  
  280.  
  281. procedure Register;
  282. begin
  283.   RegisterComponents('SystΦme', [TMinMax]);
  284. end;
  285.  
  286. initialization
  287.   aBitmap := nil;
  288.   Loaded := False;
  289. finalization
  290.   aBitmap.Free;
  291. end.
  292.