home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 1997 May / pcpro0597.iso / code / visuprog / ExpBtn.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-02-04  |  9.8 KB  |  351 lines

  1. unit ExpBtn;
  2.  
  3. {  Internet Explorer style 'Active Button' written by Dave Jewell, February 1997.
  4.  
  5.    Todo: popup menu }
  6.  
  7. interface
  8.  
  9. uses
  10.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  11.   Forms, Dialogs, Menus;
  12.  
  13. type
  14.   TExpBtnState = (bsInactive, bsActive, bsDown, bsDownAndOut);
  15.   TGlyphPosition = (bsTop, bsBottom, bsLeft, bsRight);
  16.  
  17.   TExplorerButton = class(TCustomControl)
  18.   private
  19.     { Private declarations }
  20.     fCaption: String;
  21.     fInactive: TBitmap;
  22.     fActive: TBitmap;
  23.     fDisabled: TBitmap;
  24.     fState: TExpBtnState;
  25.     fMouseExit: TNotifyEvent;
  26.     fMouseEnter: TNotifyEvent;
  27.     fTransparentColor: TColor;
  28.     fGlyphPosition: TGlyphPosition;
  29.     procedure DrawFrame;
  30.     procedure SetCaption (const Val: String);
  31.     procedure SetInactiveGlyph (Val: TBitmap);
  32.     procedure SetActiveGlyph (Val: TBitmap);
  33.     procedure SetDisabledGlyph (Val: TBitmap);
  34.     function CurrentGlyph: TBitmap;
  35.     procedure SetTransparentColor (Val: TColor);
  36.     procedure SetGlyphPosition (Val: TGlyphPosition);
  37.     procedure Layout (var txtRect, bitRect: TRect);
  38.   protected
  39.     { Protected declarations }
  40.     procedure Paint; override;
  41.     procedure WMLButtonDown (var Message: TWMLButtonDown); message wm_LButtonDown;
  42.     procedure WMMouseMove (var Message: TWMMouseMove); message wm_MouseMove;
  43.     procedure WMLButtonUp (var Message: TWMLButtonUp); message wm_LButtonUp;
  44.     procedure CMEnabledChanged (var Message: TMessage); message cm_EnabledChanged;
  45.   public
  46.     { Public declarations }
  47.     constructor Create (AOwner: TComponent); override;
  48.     destructor Destroy; override;
  49.   published
  50.     { Published declarations }
  51.     property Color;
  52.     property Font;
  53.     property Enabled;
  54.     property ParentFont;
  55.     property PopupMenu;
  56.     property ShowHint;
  57.     property ParentShowHint;
  58.     property Visible;
  59.     property OnClick;
  60.     property Align;
  61.     property OnDblClick;
  62.     property OnMouseDown;
  63.     property OnMouseMove;
  64.     property OnMouseUp;
  65.     property Caption: String read fCaption write SetCaption;
  66.     property GlyphInactive: TBitmap read fInactive write SetInactiveGlyph;
  67.     property GlyphActive: TBitmap read fActive write SetActiveGlyph;
  68.     property GlyphDisabled: TBitmap read fDisabled write SetDisabledGlyph;
  69.     property Position: TGlyphPosition read fGlyphPosition write SetGlyphPosition default bsTop;
  70.     property TransparentColor: TColor read fTransparentColor write SetTransparentColor default clOlive;
  71.     property OnMouseExit: TNotifyEvent read fMouseExit write fMouseExit;
  72.     property OnMouseEnter: TNotifyEvent read fMouseEnter write fMouseEnter;
  73.   end;
  74.  
  75. procedure Register;
  76.  
  77. implementation
  78.  
  79. { TExplorerButton }
  80.  
  81. constructor TExplorerButton.Create (AOwner: TComponent);
  82. begin
  83.     Inherited Create (AOwner);
  84.     fInactive := TBitmap.Create;
  85.     fActive := TBitmap.Create;
  86.     fDisabled := TBitmap.Create;
  87.     fState := bsInactive;
  88.     fGlyphPosition := bsTop;
  89.     fTransparentColor := clOlive;
  90.     Width := 50; Height := 40;
  91. end;
  92.  
  93. destructor TExplorerButton.Destroy;
  94. begin
  95.     fInactive.Free;
  96.     fActive.Free;
  97.     fDisabled.Free;
  98.     Inherited Destroy;
  99. end;
  100.  
  101. procedure TExplorerButton.CMEnabledChanged (var Message: TMessage);
  102. begin
  103.     Inherited;
  104.     Invalidate;
  105. end;
  106.  
  107. procedure TExplorerButton.SetInactiveGlyph (Val: TBitmap);
  108. begin
  109.     fInactive.Assign (Val);
  110.     Invalidate;
  111. end;
  112.  
  113. procedure TExplorerButton.SetActiveGlyph (Val: TBitmap);
  114. begin
  115.     fActive.Assign (Val);
  116.     Invalidate;
  117. end;
  118.  
  119. procedure TExplorerButton.SetDisabledGlyph (Val: TBitmap);
  120. begin
  121.     fDisabled.Assign (Val);
  122.     Invalidate;
  123. end;
  124.  
  125. procedure TExplorerButton.SetCaption (const Val: String);
  126. begin
  127.     if fCaption <> Val then
  128.     begin
  129.         fCaption := Val;
  130.         Invalidate;
  131.     end;
  132. end;
  133.  
  134. procedure TExplorerButton.SetTransparentColor (Val: TColor);
  135. begin
  136.     if fTransparentColor <> Val then
  137.     begin
  138.         fTransparentColor := Val;
  139.         Invalidate;
  140.     end;
  141. end;
  142.  
  143. procedure TExplorerButton.SetGlyphPosition (Val: TGlyphPosition);
  144. begin
  145.     if fGlyphPosition <> Val then
  146.     begin
  147.         fGlyphPosition := Val;
  148.         Invalidate;
  149.     end;
  150. end;
  151.  
  152. function TExplorerButton.CurrentGlyph: TBitmap;
  153. begin
  154.     { Default to inactive glyph - use others if present }
  155.     Result := fInactive;
  156.     if (fState in [bsActive, bsDown]) and (not fActive.Empty) then Result := fActive;
  157.     if (not Enabled) and (not fDisabled.Empty) then Result := fDisabled;
  158. end;
  159.  
  160. procedure TExplorerButton.DrawFrame;
  161. var
  162.     rClient: TRect;
  163.     State: TExpBtnState;
  164.     LT, BR: TColor;
  165. begin
  166.     State := fState;
  167.     rClient := ClientRect;
  168.     { If we're designing, draw component in 'Active' state }
  169.     if csDesigning in ComponentState then State := bsActive;
  170.     { Only Active and Down states have a border }
  171.     if State in [bsDown, bsActive] then with Canvas do
  172.     begin
  173.         if State = bsActive then
  174.         begin
  175.             LT := clBtnHighlight; BR := clBtnShadow;
  176.         end
  177.         else
  178.         begin
  179.             LT := clBtnShadow; BR := clBtnHighlight;
  180.         end;
  181.  
  182.         with rClient do
  183.         begin
  184.             Pen.Color := LT;
  185.             MoveTo (Right - 1, 0); LineTo (0, 0);
  186.             LineTo (0, Bottom - 1);
  187.             Pen.Color := BR;
  188.             MoveTo (1, Bottom - 1);
  189.             LineTo (Right - 1, Bottom - 1);
  190.             MoveTo (Right - 1, 1);
  191.             LineTo (Right - 1, Bottom);
  192.         end;
  193.     end;
  194. end;
  195.  
  196. procedure TExplorerButton.Layout (var txtRect, bitRect: TRect);
  197. var
  198.     hBit, vBit, hTxt, vTxt: Integer;
  199. begin
  200.     hBit := bitRect.Right - bitRect.Left;
  201.     vBit := bitRect.Bottom - bitRect.Top;
  202.     hTxt := txtRect.Right - txtRect.Left;
  203.     vTxt := txtRect.Bottom - txtRect.Top;
  204.  
  205.     case fGlyphPosition of
  206.         bsTop, bsBottom:
  207.         begin
  208.             bitRect.Left := (Width - hBit) div 2;
  209.             txtRect.Left := (Width - hTxt) div 2;
  210.             bitRect.Top := (Height - (vBit + vTxt)) div 2;
  211.             txtRect.Top := bitRect.Top + vBit;
  212.         end;
  213.  
  214.         bsLeft, bsRight:
  215.         begin
  216.             bitRect.Top := (Height - vBit) div 2;
  217.             txtRect.Top := (Height - vTxt) div 2;
  218.             bitRect.Left := (Width - (hBit + hTxt)) div 2;
  219.             txtRect.Left := bitRect.Left + hBit;
  220.         end;
  221.     end;
  222.  
  223.     bitRect.Right := bitRect.Left + hBit;
  224.     bitRect.Bottom := bitRect.Top + vBit;
  225.     txtRect.Right := txtRect.Left + hTxt;
  226.     txtRect.Bottom := txtRect.Top + vTxt;
  227.  
  228.     { If button down, draw text and glyph down and to the right }
  229.     if fState = bsDown then
  230.     begin
  231.         OffsetRect (bitRect, 1, 1);
  232.         OffsetRect (txtRect, 1, 1);
  233.     end;
  234. end;
  235.  
  236. procedure TExplorerButton.Paint;
  237. var
  238.     Glyph: TBitmap;
  239.     txtRect, bitRect, glyphRect: TRect;
  240. begin
  241.     with Canvas do
  242.     begin
  243.         { Fill control background }
  244.         Brush.Color := Color;
  245.         Brush.Style := bsSolid;
  246.         FillRect (ClientRect);
  247.         { Draw control frame - if applicable }
  248.         DrawFrame;
  249.         { Figure out size of text and display bitmaps }
  250.         Font := Self.Font;
  251.         Glyph := CurrentGlyph;
  252.         txtRect := Rect (0, 0, TextWidth (Caption), TextHeight (Caption));
  253.         bitRect := Rect (0, 0, Glyph.Width, Glyph.Height);
  254.         glyphRect := bitRect;
  255.         { Now calculate position of text and bitmap }
  256.         if fGlyphPosition in [bsTop, bsLeft] then Layout (txtRect, bitRect)
  257.         else Layout (bitRect, txtRect);
  258.  
  259.         { First, draw the caption }
  260.         Brush.Style := bsClear;
  261.         if Enabled then TextRect (txtRect, txtRect.left, txtRect.top, fCaption) else
  262.         begin
  263.             Font.Color := clBtnShadow;
  264.             TextRect (txtRect, txtRect.left, txtRect.top, fCaption);
  265.             OffsetRect (txtRect, 1, 1);
  266.             Font.Color := clBtnHighlight;
  267.             TextRect (txtRect, txtRect.left, txtRect.top, fCaption);
  268.         end;
  269.  
  270.         { Finally, draw the glyph }
  271.         Brush.Color := Color;
  272.         BrushCopy (bitRect, Glyph, glyphRect, fTransparentColor);
  273.     end;
  274. end;
  275.  
  276. procedure TExplorerButton.WMLButtonDown (var Message: TWMLButtonDown);
  277. var
  278.     InControl: Boolean;
  279. begin
  280.     Inherited;
  281.     InControl := PtInRect (GetClientRect, Message.Pos);
  282.     if InControl then
  283.     begin
  284.         MouseCapture := True;
  285.         fState := bsDown;
  286.         Invalidate;
  287.     end;
  288. end;
  289.  
  290. procedure TExplorerButton.WMMouseMove (var Message: TWMMouseMove);
  291. var
  292.     InControl: Boolean;
  293. begin
  294.     Inherited;
  295.     InControl := PtInRect (GetClientRect, Message.Pos);
  296.     if (fState = bsDown) and (not InControl) then
  297.     begin
  298.         fState := bsDownAndOut; Invalidate;
  299.     end;
  300.  
  301.     if (fState = bsDownAndOut) and InControl then
  302.     begin
  303.         fState := bsDown; Invalidate;
  304.     end;
  305.  
  306.     case fState of
  307.         bsInActive:  if InControl then
  308.                      begin
  309.                          fState := bsActive;
  310.                          if Assigned (fMouseEnter) then fMouseEnter (Self);
  311.                          MouseCapture := True;
  312.                          Invalidate;
  313.                      end;
  314.         bsActive:    if not InControl then
  315.                      begin
  316.                          fState := bsInActive;
  317.                          if Assigned (fMouseExit) then fMouseExit (Self);
  318.                          MouseCapture := False;
  319.                          Invalidate;
  320.                      end;
  321.     end;
  322. end;
  323.  
  324. procedure TExplorerButton.WMLButtonUp (var Message: TWMLButtonUp);
  325. var
  326.     InControl: Boolean;
  327. begin
  328.     Inherited;
  329.     InControl := PtInRect (GetClientRect, Message.Pos);
  330.  
  331.     if InControl then
  332.     begin
  333.         fState := bsActive;
  334.         MouseCapture := True;
  335.     end
  336.     else
  337.     begin
  338.         fState := bsInactive;
  339.         MouseCapture := False;
  340.     end;
  341.  
  342.     Invalidate;
  343. end;
  344.  
  345. procedure Register;
  346. begin
  347.     RegisterComponents('Pilgrim''s Progress', [TExplorerButton]);
  348. end;
  349.  
  350. end.
  351.