home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / PCTV3N3.ZIP / MDITOOL.ZIP / TOOLBAR.ZIP / TOOLBAR.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-05-29  |  13.8 KB  |  517 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Pascal for Windows                     }
  4. {   Demo program                                 }
  5. {   Copyright (c) 1992 by Borland International  }
  6. {                                                }
  7. {   Author: Danny Thorpe, QA Engineer            }
  8. {           Pascal Compiler Group                }
  9. {                                                }
  10. {************************************************}
  11.  
  12. unit Toolbar;
  13.  
  14. interface
  15.  
  16. {$R Toolbar.res}
  17.  
  18. uses Winprocs, Wintypes, WObjects, Strings;
  19.  
  20. const
  21.  
  22.   am_SetParentClientRect = wm_User + 120;
  23.  
  24. type
  25.                                                 
  26.  
  27.   PToolButton = ^TToolButton;
  28.   TToolButton = object(TObject)
  29.     Parent: PWindowsObject;
  30.     bmNormal, bmPressed, bmGlyph: HBitmap;
  31.     brGraying: HBrush;
  32.     Command: Word;
  33.     Capturing, IsPressed, IsEnabled: Boolean;
  34.     R: TRect;
  35.     GlyphSize: TPoint;
  36.     CapDC, MemDC: HDC;
  37.     constructor Init(AParent: PWindowsObject;
  38.                      X, Y: Integer;
  39.                      ACommand: Word;
  40.                      BitmapName: PChar);
  41.     destructor Done; virtual;
  42.     procedure Enable(NewState: Boolean);
  43.     function  GetWidth: Integer;
  44.     function  GetHeight: Integer;
  45.     function  HitTest(P: TPoint): Boolean; virtual; 
  46.     procedure InitButtonBitmaps(W, H: Integer); virtual;
  47.     procedure Paint(DC: HDC; var PS: TPaintStruct); virtual;
  48.     procedure PaintState(DC, MDC: HDC; Offset: Integer; bmButton: HBitmap); virtual;
  49.     procedure BeginCapture(P: TPoint);
  50.     procedure ContinueCapture(P: TPoint);
  51.     function  EndCapture(SendTo: HWnd; P: TPoint): Boolean;
  52.     procedure PressIn;  
  53.     procedure PressOut;
  54.   end;
  55.  
  56.  
  57.   PToolbar = ^TToolbar;
  58.   TToolbar = object(TWindow)
  59.     ResName: PChar;
  60.     Tools: TCollection;
  61.     Capture: PToolButton;
  62.     constructor Init(AParent: PWindowsObject; AName: PChar);
  63.     destructor Done; virtual;
  64.     function  CreateTool(Num: Integer; Origin: TPoint; Command: Word; BitmapName: PChar): PToolButton; virtual;
  65.     procedure EnableTool(Command: Word; NewState: Boolean); virtual;
  66.     procedure FreeResName;
  67.     function  GetClassName: PChar; virtual;
  68.     procedure GetWindowClass(var WC: TWndClass); virtual;
  69.     procedure SetResName(NewName: PChar);
  70.     procedure NextToolOrigin(Num: Integer; var Origin: TPoint; P: PToolButton); virtual;
  71.     procedure Paint(DC: HDC; var PS: TPaintStruct); virtual;
  72.     procedure ReadResource; virtual;
  73.     procedure SwitchTo(NewName: PChar);
  74.     procedure amSetParentClientRect(var Msg: TMessage); virtual wm_First + am_SetParentClientRect;
  75.     procedure wmLButtonDown(var Msg: TMessage); virtual wm_First + wm_LButtonDown;
  76.     procedure wmMouseMove(var Msg: TMessage); virtual wm_First + wm_MouseMove;
  77.     procedure wmLButtonUp(var Msg: TMessage); virtual wm_First + wm_LButtonUp;
  78.   end;
  79.  
  80.  
  81. implementation
  82.  
  83.  
  84. function Max(A,B: Integer): Integer;
  85. begin
  86.   if A > B then
  87.     Max := A
  88.   else
  89.     Max := B;
  90. end;
  91.  
  92. {------------ TToolbar ----------------------}
  93.  
  94. constructor TToolbar.Init(AParent: PWindowsObject; AName: PChar);
  95. begin
  96.   TWindow.Init(AParent, nil);
  97.   Attr.Style := ws_Child or ws_Visible or ws_Border;
  98.   SetFlags(wb_MDIChild, False);
  99.   DefaultProc := @DefWindowProc;
  100.   Attr.X := -1;
  101.   Attr.Y := -1;
  102.   Attr.W := 100;
  103.   Attr.H := 1;
  104.   Capture := nil;
  105.   ResName := nil;
  106.   SetResName(AName);
  107.   Tools.Init(8, 8);
  108.   ReadResource;
  109. end;
  110.  
  111.  
  112. destructor TToolbar.Done;
  113. begin
  114.   TWindow.Done;
  115.   Tools.Done;
  116.   FreeResName;
  117. end;
  118.  
  119.  
  120. procedure TToolbar.ReadResource;
  121.  
  122. type
  123.   ResRec = record
  124.     Num,
  125.     Bitmap,
  126.     Command: Word;
  127.   end;
  128.  
  129.   PResArray = ^TResArray;
  130.   TResArray = array [0..$FFF0 div sizeof(ResRec)] of ResRec;
  131.  
  132. var
  133.   ResIdHandle: THandle;
  134.   ResDataHandle: THandle;
  135.   ResDataPtr: PResArray;
  136.   x: word;
  137.   Origin: TPoint;
  138.   BitInfo: TBitmap;
  139.   P: PToolButton;
  140.  
  141. begin
  142.   ResIDHandle := FindResource(HInstance, ResName, 'ToolBarData');
  143.   ResDataHandle := LoadResource(HInstance, ResIDHandle);
  144.   ResDataPtr := LockResource(ResDataHandle);
  145.   if (ResIDHandle = 0) or (ResDataHandle = 0) or (ResDataPtr = nil) then
  146.   begin
  147.     Status := em_InvalidChild;
  148.     Exit;
  149.   end;
  150.  
  151.   x:= 0;
  152.   Origin.X := 0;
  153.   Origin.Y := 0;
  154.   while (ResDataPtr^[x].Num = x) do
  155.     with ResDataPtr^[x] do
  156.     begin
  157.       P := CreateTool(X, Origin, Command, PChar(Bitmap));
  158.       if P <> nil then
  159.       begin
  160.         NextToolOrigin(X, Origin, P);
  161.         Tools.Insert(P);
  162.       end;
  163.       Inc(X);
  164.     end;
  165.  
  166.   if (ResDataPtr^[X].Num <> 0) and (ResDataPtr^[X].Num <> X) then
  167.     Status := em_InvalidChild;
  168.  
  169.   UnlockResource(ResDataHandle);
  170.   FreeResource(ResDataHandle);
  171. end;
  172.  
  173.  
  174. { Override CreateTool to make Toolbar use a different kind of ToolButton object }
  175.  
  176. function TToolbar.CreateTool(Num: Integer; Origin: TPoint; Command: Word; BitmapName: PChar): PToolButton;
  177. begin
  178.   CreateTool := new(PToolButton, Init(@Self, Origin.X, Origin.Y, Command, BitmapName));
  179. end;
  180.  
  181. procedure TToolbar.EnableTool(Command: Word; NewState: Boolean);
  182.  
  183.   function FoundIt(P: PToolbutton): Boolean; far;
  184.   begin
  185.     FoundIt := P^.Command = Command;
  186.   end;
  187.  
  188. var
  189.   P: PToolbutton;
  190.  
  191. begin
  192.   P := Tools.FirstThat(@FoundIt);
  193.   if P <> nil then
  194.     P^.Enable(NewState);
  195. end;
  196.   
  197.  
  198. function TToolbar.GetClassName: PChar;
  199. begin
  200.   GetClassName := 'OWLToolbar';
  201. end;
  202.  
  203. procedure TToolbar.GetWindowClass(var WC: TWndClass);
  204. begin
  205.   TWindow.GetWindowClass(WC);
  206.   WC.hbrBackground := GetStockObject(LtGray_Brush);
  207. end;
  208.  
  209.  
  210. { NextToolOrigin sets the origin for the next tool button based upon the current tool's
  211.   size and the toolbar's primary orientation or layout system (horizontal, vertical,
  212.   palette.  This method is called in the Toolbar's constructor after each tool that is
  213.   added to the toolbar. }
  214.  
  215. procedure TToolbar.NextToolOrigin(Num: Integer; var Origin: TPoint; P: PToolButton);
  216. begin
  217.   Inc(Origin.X, P^.GetWidth);
  218.   Attr.H := Max(Attr.H, P^.GetHeight);
  219. end;
  220.  
  221.  
  222. procedure TToolbar.Paint(DC: HDC; var PS: TPaintStruct); 
  223.  
  224.   procedure PaintIt(Item: PToolButton); far;
  225.   begin
  226.     Item^.Paint(DC, PS);
  227.   end; 
  228.  
  229. begin
  230.   Tools.ForEach(@PaintIt);
  231. end;
  232.  
  233.  
  234. { FreeResName handles releasing memory, if necessary, occupied by a
  235.   PChar / integer resource identifier }
  236.  
  237. procedure TToolbar.FreeResName;
  238. begin
  239.   if HiWord(Longint(ResName)) <> 0 then
  240.     StrDispose(ResName);
  241. end;
  242.  
  243. { SetResName handles allocating memory, if necessary, to hold a PChar or
  244.   integer resource identifier. }
  245.  
  246. procedure TToolbar.SetResName(NewName: PChar);
  247. begin
  248.   FreeResName;
  249.   if HiWord(Longint(NewName)) <> 0 then
  250.     ResName := StrNew(NewName)
  251.   else
  252.     ResName := NewName;
  253. end;
  254.  
  255.  
  256. { Switch the Toolbar object to use a different toolbar resource. }
  257.  
  258. procedure TToolbar.SwitchTo(NewName: PChar);
  259. begin
  260.   Tools.Done;
  261.   Tools.Init(8,8);
  262.   SetResName(NewName);
  263.   ReadResource;
  264. end;
  265.  
  266. { AMSetParentClientRect is a message sent to us from the main window.  LParam points to
  267.   a TRect, which the main window will use to resize the MDI Client window.  You can
  268.   modify this rect to move the client window down (horizontal toolbar) or left or right
  269.   (vertical toolbar).  Note that other 'special' windows, such as a status line, may also
  270.   modify the rect before or after the toolbar is given its chance.  Do not assume
  271.   the rect always starts out as the main window's full client area.}
  272.  
  273. procedure TToolbar.AMSetParentClientRect( var Msg: TMessage);
  274. var R,S : TRect;
  275. begin
  276.   if (Msg.wParam =  SizeNormal) or (Msg.wParam = SizeFullScreen) then
  277.   begin
  278.     GetClientRect(HWindow, R);
  279.     GetClientRect(Parent^.HWindow, S);
  280.     if R.Right <> S.Right then
  281.       SetWindowPos(HWindow, 0, -1, -1, S.Right + 2, R.Bottom + 2, swp_NoZOrder or swp_NoRedraw);
  282.     if R.Right < S.Right then
  283.     begin
  284.       S.Left := R.Right;
  285.       S.Top := R.Top;
  286.       S.Bottom := R.Bottom+1;
  287.       InvalidateRect(HWindow, @S, True);
  288.     end;  
  289.     if PRect(Msg.LParam)^.Top < R.Bottom then
  290.       PRect(Msg.LParam)^.Top := R.Bottom+1;
  291.   end;
  292. end;
  293.  
  294.  
  295. procedure TToolbar.WMLButtonDown(var Msg: TMessage);
  296.  
  297.   function IsHit(Item: PToolButton): Boolean; far;
  298.   begin
  299.     IsHit := Item^.HitTest(TPoint(Msg.LParam));
  300.   end;
  301.  
  302. begin
  303.   Capture := Tools.FirstThat(@IsHit);
  304.   if Capture <> nil then
  305.     Capture^.BeginCapture(TPoint(Msg.LParam));
  306. end;
  307.  
  308. procedure TToolbar.wmMouseMove(var Msg: TMessage);
  309. begin
  310.   if (Capture <> nil) then
  311.     Capture^.ContinueCapture(TPoint(Msg.LParam));
  312. end;
  313.  
  314. procedure TToolbar.wmLButtonUp(var Msg: TMessage); 
  315. begin
  316.   if (Capture <> nil) then
  317.   begin
  318.     if Capture^.EndCapture(Parent^.HWindow, TPoint(Msg.LParam)) then
  319.       Capture := nil;  { DON'T dispose of the captured tool!! }
  320.   end;
  321. end;
  322.  
  323.  
  324. {------------ TToolButton --------------------------}
  325.  
  326. constructor TToolButton.Init(AParent: PWindowsObject;
  327.                              X, Y: Integer;
  328.                              ACommand: Word;
  329.                              BitmapName: PChar);
  330. var
  331.   BI: TBitmap;
  332.   GrayBM, OldBM: HBitmap;
  333.   OldPen: HPen;
  334. begin
  335.   TObject.Init;
  336.   Parent := AParent;
  337.   CapDC := 0;
  338.   MemDC := 0;
  339.   bmNormal := 0;
  340.   bmPressed := 0;
  341.   brGraying := 0;
  342.   IsPressed := False;
  343.   Capturing := False;
  344.   IsEnabled := True;
  345.   Command := ACommand;
  346.   bmGlyph := LoadBitmap(HInstance, BitmapName);
  347.   GetObject(bmGlyph, SizeOf(BI), @BI);
  348.   GlyphSize.X := BI.bmWidth;
  349.   GlyphSize.Y := BI.bmHeight;
  350.   InitButtonBitmaps(GlyphSize.X, GlyphSize.Y);
  351.   GetObject(bmNormal, SizeOf(BI), @BI);
  352.   SetRect(R, X, Y, X + BI.bmWidth, Y + BI.bmHeight);
  353. end;
  354.  
  355.  
  356. destructor TToolButton.Done;
  357. begin
  358.   if Capturing then
  359.   begin
  360.     DeleteDC(MemDC);
  361.     ReleaseDC(Parent^.HWindow, CapDC);
  362.     ReleaseCapture;
  363.   end;
  364.   if bmGlyph <> 0 then DeleteObject(bmGlyph);
  365.   if bmNormal <> 0 then DeleteObject(bmNormal);
  366.   if bmPressed <> 0 then DeleteObject(bmPressed);
  367.   if brGraying <> 0 then DeleteObject(brGraying);
  368.   TObject.Done;
  369. end;
  370.  
  371. procedure TToolButton.Enable(NewState: Boolean);
  372. begin
  373.   if (IsEnabled <> NewState) and (Parent^.HWindow <> 0) then
  374.     InvalidateRect(Parent^.HWindow, @R, False);
  375.   IsEnabled := NewState;
  376. end;
  377.  
  378. function TToolButton.GetWidth: Integer;
  379. begin
  380.   GetWidth := R.Right - R.Left;
  381. end;
  382.  
  383. function TToolButton.GetHeight: Integer;
  384. begin
  385.   GetHeight := R.Bottom - R.Top;
  386. end;
  387.  
  388. function TToolButton.HitTest(P: TPoint): Boolean;
  389. begin
  390.   HitTest := Boolean(PtInRect(R,P));
  391. end;
  392.  
  393. { InitButtonBitmaps loads the button images that the tool button glyphs
  394.   will be copied onto.  TToolButton assumes all the tool buttons on the toolbar
  395.   will be the same size.  If you want variable sized (width or height or both)
  396.   tool buttons, create a descendent of TToolButton and override this
  397.   method to create or stretch the button image to suite each tool's
  398.   glyph size.  Creating bitmaps for each toolbutton uses more memory
  399.   than several toolbuttons referencing the same bitmap resource.
  400.   String names are used to identify the bitmaps to avoid integer id
  401.   collisions with other bitmaps in the application.
  402. }
  403.  
  404. procedure TToolButton.InitButtonBitmaps(W, H: Integer);
  405. var
  406.   LBrush: TLogBrush;
  407.   DC,SourceDC,DestDC: HDC;
  408.   bmOld1, bmOld2: HBitmap;
  409. begin
  410.   bmNormal := LoadBitmap(HInstance, 'NormalToolButton');
  411.   bmPressed := LoadBitmap(HInstance, 'PressedToolButton');
  412.  
  413.   LBrush.lbStyle := bs_Pattern;
  414.   Word(LBrush.lbHatch) := LoadBitmap(HInstance, 'GrayingBitmap');
  415.   brGraying := CreateBrushIndirect(LBrush);
  416.   DeleteObject(Word(LBrush.lbHatch));
  417. end;
  418.  
  419.  
  420. procedure TToolButton.Paint(DC: HDC; var PS: TPaintStruct);
  421. var
  422.   M: HDC;
  423. begin
  424.   M := CreateCompatibleDC(DC);
  425.   PaintState(DC, M, 0, bmNormal);
  426.   DeleteDC(M); 
  427. end;
  428.  
  429. procedure TToolButton.PaintState(DC, MDC: HDC; Offset: Integer; bmButton: HBitmap);
  430. var
  431.   bmOld: HBitmap;
  432.   OldBrush: HBrush;
  433.   OldOrg: Longint;
  434. begin
  435.   bmOld := SelectObject(MDC, bmButton);
  436.   BitBlt(DC, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top,
  437.          MDC, 0, 0, SrcCopy);
  438.   SelectObject(MDC, bmGlyph);
  439.   if IsEnabled then
  440.     BitBlt(DC, R.Left+Offset+1, R.Top+1+Offset, GlyphSize.X, GlyphSize.Y,
  441.            MDC, 0, 0, SrcCopy)
  442.   else
  443.   begin
  444.     UnRealizeObject(brGraying);
  445.     OldBrush := SelectObject(DC, brGraying);
  446.     BitBlt(DC, R.Left+Offset+1, R.Top+Offset+1, GlyphSize.X, GlyphSize.Y,
  447.            MDC, 0, 0, $00A803A9 {DPSoa});
  448.     SelectObject(DC, OldBrush);
  449.   end;     
  450.   SelectObject(MDC, bmOld);
  451. end;
  452.  
  453. procedure TToolButton.PressIn;
  454. begin
  455.   if (not IsPressed) and IsEnabled then
  456.   begin
  457.     IsPressed := True;
  458.     PaintState(CapDC, MemDC, 1, bmPressed);
  459.   end;
  460. end;
  461.  
  462. procedure TToolButton.PressOut;
  463. begin
  464.   if IsPressed then
  465.   begin
  466.     IsPressed := False;
  467.     PaintState(CapDC, MemDC, 0, bmNormal);
  468.   end;
  469. end;
  470.  
  471. procedure TToolButton.BeginCapture(P: TPoint);
  472. begin
  473.   CapDC := GetDC(Parent^.HWindow);
  474.   MemDC := CreateCompatibleDC(CapDC);
  475.   IsPressed := False;
  476.   Capturing := True;
  477.   SetCapture(Parent^.HWindow);
  478.   if HitTest(P) then
  479.     PressIn;
  480. end;
  481.  
  482. procedure TToolButton.ContinueCapture(P: TPoint);
  483. begin
  484.   if HitTest(P) then
  485.     PressIn
  486.   else
  487.     PressOut;
  488. end;
  489.  
  490.  
  491. { The boolean function result of EndCapture indicates whether the tool button
  492.   has released the mouse capture or not.  The Toolbar should not clear its
  493.   capture field/state until the toolbutton says to.
  494.  
  495.   The SendTo parameter is the HWindow to notify that the tool button was clicked
  496.   upon, if such is the case.  This code emulates a menu command message, but
  497.   any message type could be used. }
  498.  
  499. function TToolButton.EndCapture(SendTo: HWnd; P: TPoint): Boolean;
  500. begin
  501.   if HitTest(P) then
  502.   begin
  503.     PressOut;
  504.     PostMessage(SendTo, wm_Command, Command, 0);
  505.   end;
  506.   EndCapture := True;
  507.   ReleaseCapture;
  508.   Capturing := False;
  509.   DeleteDC(MemDC);
  510.   ReleaseDC(Parent^.HWindow, CapDC);
  511.   MemDC := 0;
  512.   CapDC := 0;
  513. end;
  514.  
  515.  
  516. end.
  517.