home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / ISSUE21 / COLORBUT / COLORBUT.ZIP / ColorButton.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-02-26  |  17.5 KB  |  600 lines

  1. unit ColorButton;
  2.  
  3. ///////////////////////////////////////////////////////////////////////////////
  4. //                                                                           //
  5. //        ///////////////////////////////////////////////////////////        //
  6. //        //                                                       //        //
  7. //        //               ColorButton Component 3.0               //        //
  8. //        //                for Borland Delphi 2.xx                //        //
  9. //        //                                                       //        //
  10. //        //      Written by  Jonathan Grant and Peter Steele      //        //
  11. //        //     Copyright ⌐ 1995-1997 Information Expressions     //        //
  12. //        //                                                       //        //
  13. //        ///////////////////////////////////////////////////////////        //
  14. //                                                                           //
  15. //      Improvements/enhancements in version 3.0...                          //
  16. //                                                                           //
  17. //         1. Capabitity for multi-line text.                                //
  18. //         2. Raised/lowered text styles.                                    //
  19. //         3. Button can be 'multi-state'.                                   //
  20. //                                                                           //
  21. ///////////////////////////////////////////////////////////////////////////////
  22.  
  23. interface
  24.  
  25. uses
  26.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, Buttons;
  27.  
  28. type
  29.   TAlignment = (alTopLeft, alTopCenter, alTopRight,
  30.                 alMiddleLeft, alMiddleCenter, alMiddleRight,
  31.                 alBottomLeft, alBottomCenter, alBottomRight);
  32.  
  33.   TButtonBevel = (bbLowered, bbNone, bbRaised);
  34.  
  35.   TFontStyle   = (fnNormal, fnRaised, fnLowered);
  36.  
  37.   TButtonStyles = (bsAutoSize, bsCenter, bsStretch, bsShowFocus, bsSpeedKey, bsMultiState, bsMultiLine);
  38.   TButtonStyle = set of TButtonStyles;
  39.  
  40.   TButtonState = (bsUp, bsDown, bsDisabled);
  41.  
  42.   TColorButton = class(TCustomControl)
  43.   private
  44.     FAlignment:       TAlignment;
  45.     FBevelStyle:      TButtonBevel;
  46.     FBevelSize:       Integer;
  47.  
  48.     FColor:           TColor;
  49.     FShadowColor:     TColor;
  50.     FHighlightColor:  TColor;
  51.  
  52.     FPicture:         TPicture;
  53.     FSpacing:         Integer;
  54.     FStyle:           TButtonStyle;
  55.     FFontStyle:       TFontStyle;
  56.  
  57.     FFocused:         Boolean;
  58.     FState:           TButtonState;
  59.  
  60.     procedure SetAlignment(Value: TAlignment);
  61.     procedure SetBevelStyle(Value: TButtonBevel);
  62.     procedure SetBevelSize(Value: Integer);
  63.     procedure SetCaption(var Message: TMessage); message CM_TEXTCHANGED;
  64.     procedure SetColor(Value: TColor);
  65.     procedure SetEnabled(var Message: TMessage); message CM_ENABLEDCHANGED;
  66.     procedure SetFocusOff(var Message: TMessage); message CM_LOSTFOCUS;
  67.     procedure SetFocusOn(var Message: TMessage); message CM_GOTFOCUS;
  68.     procedure SetFont(var Message: TMessage); message CM_FONTCHANGED;
  69.     procedure SetFontStyle(Value: TFontStyle);
  70.     procedure SetPicture(Value: TPicture);
  71.     procedure SetSize(var Message: TMessage); message WM_SIZE;
  72.     procedure SetSpacing(Value: Integer);
  73.     procedure SetStyle(Value: TButtonStyle);
  74.  
  75.     function  GetValue: Boolean;
  76.     procedure SetValue(Value: Boolean);
  77.  
  78.     procedure DoEnter; override;
  79.     procedure DoExit; override;
  80.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  81.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  82.     procedure KeyAccel(var Message: TCMDialogChar); message CM_DIALOGCHAR;
  83.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  84.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  85.   public
  86.     constructor Create(AOwner: TComponent); override;
  87.     destructor Destroy; override;
  88.     procedure Loaded; override;
  89.     procedure Paint; override;
  90.   published
  91.     property Alignment: TAlignment read FAlignment write SetAlignment default alMiddleCenter;
  92.     property BevelStyle: TButtonBevel read FBevelStyle write SetBevelStyle default bbRaised;
  93.     property BevelSize: Integer read FBevelSize write SetBevelSize default 2;
  94.     property Caption;
  95.     property Color: TColor read FColor write SetColor default clBtnFace;
  96.     property Cursor;
  97.     property DragCursor;
  98.     property DragMode;
  99.     property Enabled;
  100.     property Font;
  101.     property FontStyle: TFontStyle read FFontStyle write SetFontStyle;
  102.     property Height;
  103.     property Left;
  104.     property Name;
  105.     property Picture: TPicture read FPicture write SetPicture;
  106.     property Spacing: Integer read FSpacing write SetSpacing default 2;
  107.     property Style: TButtonStyle read FStyle write SetStyle default [bsCenter, bsShowFocus, bsSpeedKey, bsMultiLine];
  108.     property Tag;
  109.     property TabOrder;
  110.     property TabStop;
  111.     property Top;
  112.     property Value: Boolean read GetValue write SetValue default False;
  113.     property Width;
  114.  
  115.     property OnClick;
  116.     property OnDblClick;
  117.     property OnDragDrop;
  118.     property OnDragOver;
  119.     property OnEndDrag;
  120.     property OnEnter;
  121.     property OnExit;
  122.     property OnKeyDown;
  123.     property OnKeyPress;
  124.     property OnKeyUp;
  125.     property OnMouseDown;
  126.     property OnMouseMove;
  127.     property OnMouseUp;
  128.     property OnStartDrag;
  129.   end;
  130.  
  131. procedure Register;
  132.  
  133. function Smallest(X, Y: Integer): Integer;
  134. function Largest(X, Y: Integer): Integer;
  135.  
  136. function GetHighlightColor(BaseColor: TColor): TColor;
  137. function GetShadowColor(BaseColor: TColor): TColor;
  138.  
  139.  
  140. implementation
  141.  
  142. procedure Register;
  143. begin
  144.   RegisterComponents('Extra', [TColorButton]);
  145. end;
  146.  
  147. //
  148. // Global procedures and functions
  149. ///////////////////////////////////////////////////////////////////////////////
  150.  
  151. function Smallest(X, Y: Integer): Integer;
  152. begin
  153.     if (X < Y) then Result := X else Result := Y;
  154. end;
  155.  
  156. function Largest(X, Y: Integer): Integer;
  157. begin
  158.     if (X > Y) then Result := X else Result := Y;
  159. end;
  160.  
  161. function GetHighlightColor(BaseColor: TColor): TColor;
  162. begin
  163.     Result := RGB(
  164.       Smallest(GetRValue(ColorToRGB(BaseColor)) + 64, 255),
  165.     Smallest(GetGValue(ColorToRGB(BaseColor)) + 64, 255),
  166.     Smallest(GetBValue(ColorToRGB(BaseColor)) + 64, 255)
  167.       );
  168. end;
  169.  
  170. function GetShadowColor(BaseColor: TColor): TColor;
  171. begin
  172.     Result := RGB(
  173.       Largest(GetRValue(ColorToRGB(BaseColor)) - 64, 0),
  174.     Largest(GetGValue(ColorToRGB(BaseColor)) - 64, 0),
  175.     Largest(GetBValue(ColorToRGB(BaseColor)) - 64, 0)
  176.       );
  177. end;   
  178.  
  179. //
  180. // ColorButton procedures and functions
  181. ///////////////////////////////////////////////////////////////////////////////
  182.  
  183. constructor TColorButton.Create(AOwner: TComponent);
  184. begin
  185.   inherited Create(AOwner);
  186.  
  187.   FAlignment  := alMiddleCenter;
  188.   FBevelStyle := bbRaised;
  189.   FBevelSize  := 2;
  190.   FSpacing    := 2;
  191.   FStyle      := [bsCenter, bsShowFocus, bsSpeedKey, bsMultiLine];
  192.   FFontStyle  := fnNormal;
  193.  
  194.   FColor          := clBtnFace;
  195.   FShadowColor    := clBtnShadow;
  196.   FHighlightColor := clBtnHighlight;
  197.  
  198.   FPicture     := TPicture.Create;
  199.  
  200.   FFocused     := False;
  201.   FState       := bsUp;
  202.  
  203.   Width       := 75;
  204.   Height      := 25;
  205.   Enabled     := True;
  206.   TabStop     := True;
  207. end;
  208.  
  209. destructor TColorButton.Destroy;
  210. begin
  211.   FPicture.Free;
  212.  
  213.   inherited Destroy;
  214. end;
  215.  
  216. procedure TColorButton.Loaded;
  217. begin
  218.   inherited Loaded;
  219.  
  220.   if Enabled then FState := bsUp else FState := bsDisabled;
  221.  
  222.   FShadowColor    := GetShadowColor(FColor);
  223.   FHighlightColor := GetHighlightColor(FColor);
  224.  
  225.   Repaint;
  226. end;
  227.  
  228. procedure TColorButton.Paint;
  229.  
  230.   procedure DrawCaption(xOffset, yOffset: Integer);
  231.   var
  232.     Buffer: array[0..255] of Char;
  233.     DrawRect: TRect;
  234.     DrawTop, DrawHeight: Integer;
  235.     DrawOptions: Integer;
  236.   begin
  237.     StrPCopy(Buffer, Caption);
  238.  
  239.     // Figure out drawing options
  240.     if (bsMultiLine in FStyle) then DrawOptions := DT_WORDBREAK else DrawOptions := DT_SINGLELINE;
  241.     if not (bsSpeedKey in FStyle) then Inc(DrawOptions, DT_NOPREFIX);
  242.     case FAlignment of
  243.       alTopLeft,   alMiddleLeft,   alBottomLeft  : Inc(DrawOptions, DT_LEFT);
  244.       alTopCenter, alMiddleCenter, alBottomCenter: Inc(DrawOptions, DT_CENTER);
  245.       alTopRight,  alMiddleRight,  alBottomRight : Inc(DrawOptions, DT_RIGHT);
  246.     end;
  247.  
  248.     // Calculate text height
  249.     DrawRect := Rect(FBevelSize + FSpacing, FBevelSize + FSpacing, Width - (FBevelSize + FSpacing), Height - (FBevelSize + FSpacing));
  250.     DrawHeight := DrawText(Canvas.Handle, Buffer, Length(Caption), DrawRect, DrawOptions + DT_CALCRECT);
  251.  
  252.     // Calculate text drawing position (vertical)
  253.     DrawRect := Rect(FBevelSize + FSpacing, FBevelSize + FSpacing, Width - (FBevelSize + FSpacing), Height - (FBevelSize + FSpacing));
  254.     case FAlignment of
  255.       alTopLeft,    alTopCenter,    alTopRight   : DrawTop := DrawRect.Top;
  256.       alMiddleLeft, alMiddleCenter, alMiddleRight: DrawTop := ((Height - FBevelSize) - DrawHeight) div 2;
  257.       alBottomLeft, alBottomCenter, alBottomRight: DrawTop := DrawRect.Bottom - DrawHeight;
  258.     end;
  259.     DrawRect := Rect(DrawRect.Left, DrawTop, DrawRect.Right, DrawTop + DrawHeight);
  260.  
  261.     // Offset the text if button is pressed
  262.     // if (FState = bsDown) then begin
  263.     //   if (FBevelStyle = bbRaised) then OffsetRect(DrawRect, FBevelSize, FBevelSize);
  264.     //   if (FBevelStyle = bbLowered) then OffsetRect(DrawRect, -FBevelSize, -FBevelSize);
  265.     // end;
  266.  
  267.     OffsetRect(DrawRect, xOffset, yOffset);
  268.  
  269.     // Draw the text
  270.     DrawText(Canvas.Handle, Buffer, Length(Caption), DrawRect, DrawOptions);
  271.   end;
  272.  
  273.  
  274. var
  275.   Client, Picture: TRect;
  276.   FontBase: TColor;
  277. begin
  278.     if not Enabled and not (csDesigning in ComponentState) then FState := bsDisabled
  279.   else if FState = bsDisabled then FState := bsUp;
  280.  
  281.     if ((not (FPicture.Graphic = nil)) and (bsAutoSize in FStyle)) then begin
  282.     Width := FPicture.Width + (FBevelSize * 2);
  283.     Height := FPicture.Height + (FBevelSize * 2);
  284.   end;
  285.  
  286.   Client := Bounds(0, 0, Width, Height);
  287.   Canvas.Font.Assign(Font);
  288.  
  289.   with inherited Canvas do begin
  290.     // Clear the background
  291.     Brush.Color := FColor;
  292.  
  293.     FillRect(Client);
  294.     // Draw the button bevel
  295.     if not (FBevelStyle = bbNone) then begin
  296.       if ((FState = bsDown) xor (FBevelStyle = bbLowered)) then
  297.           Frame3D(Canvas, Client, FShadowColor, FHighlightColor, FBevelSize)
  298.       else
  299.           Frame3D(Canvas, Client, FHighLightColor, FShadowColor, FBevelSize);
  300.     end;
  301.  
  302.     // Draw the focus
  303.     if (FFocused and (bsShowFocus in FStyle)) and Enabled then
  304.         DrawFocusRect(Rect(Client.Left + FSpacing - 1, Client.Top + FSpacing - 1,
  305.         Client.Right - FSpacing + 1, Client.Bottom - FSpacing + 1));
  306.  
  307.     // Draw the picture
  308.     if (FPicture.Graphic <> nil) then begin
  309.         if (bsStretch in FStyle) then
  310.              Picture := Rect(
  311.             FBevelSize + FSpacing, FBevelSize + FSpacing, Width - (FBevelSize + FSpacing), Height - (FBevelSize + FSpacing))
  312.          else if (bsCenter in FStyle) then
  313.              Picture := Bounds(
  314.                (Width - FPicture.Width) div 2, (Height - FPicture.Height) div 2,
  315.              FPicture.Width, FPicture.Height
  316.              )
  317.         else
  318.              case FAlignment of
  319.                alTopLeft, alTopCenter, alTopRight:
  320.                  Picture := Bounds(
  321.                    (Width - FPicture.Width) div 2,
  322.                  ((Height - (FBevelSize + FSpacing)) - FPicture.Height),
  323.                    FPicture.Width, FPicture.Height
  324.                  );
  325.              alMiddleLeft:
  326.                  Picture := Bounds(
  327.                    ((Width - (FBevelSize + FSpacing)) - FPicture.Width),
  328.                 (Height - FPicture.Height) div 2,
  329.                    FPicture.Width, FPicture.Height
  330.                  );
  331.              alMiddleCenter:
  332.                  Picture := Bounds(
  333.                    (Width - FPicture.Width) div 2,
  334.                      (Height - FPicture.Height) div 2,
  335.                      FPicture.Width, FPicture.Height
  336.                      );
  337.              alMiddleRight:
  338.                  Picture := Bounds(
  339.                    (FBevelSize + FSpacing),
  340.                  (Height - FPicture.Height) div 2,
  341.                    FPicture.Width, FPicture.Height
  342.                        );
  343.           alBottomLeft, alBottomCenter, alBottomRight:
  344.                  Picture := Bounds(
  345.                    (Width - FPicture.Width) div 2,
  346.                 (FBevelSize + FSpacing),
  347.                    FPicture.Width, FPicture.Height
  348.                 );
  349.           end;
  350.  
  351.         StretchDraw(Picture, FPicture.Graphic);
  352.     end
  353.     else begin
  354.          Brush.Color := FColor;
  355.          FillRect(Rect(FBevelSize, FBevelSize, Width - FBevelSize, Height - FBevelSize));
  356.     end;
  357.  
  358.     // Draw the caption
  359.     if (Caption <> '') then begin
  360.       Brush.Style := bsClear;
  361.       if ((not Enabled) and (not (csDesigning in ComponentState))) then begin
  362.         Font.Color := FHighlightColor; DrawCaption(1, 1);
  363.         Font.Color := FShadowColor; DrawCaption(0, 0);
  364.       end
  365.       else begin
  366.         case FFontStyle of
  367.         fnRaised: begin
  368.           FontBase := Font.Color;
  369.           Font.Color := FHighlightColor; DrawCaption(-1, -1);
  370.           Font.Color := FShadowColor; DrawCaption(1, 1);
  371.           Font.Color := FontBase; DrawCaption(0, 0);
  372.         end;
  373.         fnLowered: begin
  374.           FontBase := Font.Color;
  375.           Font.Color := FHighlightColor; DrawCaption(1, 1);
  376.           Font.Color := FShadowColor; DrawCaption(-1, -1);
  377.           Font.Color := FontBase; DrawCaption(0, 0);
  378.         end;
  379.         else
  380.           DrawCaption(0, 0);
  381.         end;
  382.       end;
  383.     end;
  384.   end;
  385. end;
  386.  
  387. procedure TColorButton.DoEnter;
  388. begin
  389.   FFocused := True;
  390.   Repaint;
  391.  
  392.   inherited DoEnter;
  393. end;
  394.  
  395. procedure TColorButton.DoExit;
  396. begin
  397.   FFocused := False;
  398.   Repaint;
  399.  
  400.   inherited DoExit;
  401. end;
  402.  
  403. procedure TColorButton.KeyDown(var Key: Word; Shift: TShiftState);
  404. begin
  405.   inherited KeyDown(Key, Shift);
  406.  
  407.   if (Key = VK_SPACE) and Enabled then begin
  408.     if (bsMultiState in FStyle) then begin
  409.       if FState = bsDown then FState := bsUp
  410.       else FState := bsDown;
  411.     end else FState := bsDown;
  412.     Repaint;
  413.   end;
  414. end;
  415.  
  416. procedure TColorButton.KeyUp(var Key: Word; Shift: TShiftState);
  417. begin
  418.   inherited KeyUp(Key, Shift);
  419.  
  420.   if (Key = VK_SPACE) and Enabled then begin
  421.     if not (bsMultiState in FStyle) then begin
  422.       FState := bsUp;
  423.       Repaint;
  424.     end;
  425.     Click;
  426.   end;
  427.  
  428.   if (Key = VK_RETURN) and Enabled then begin
  429.     if (bsMultiState in FStyle) then begin
  430.       FState := bsDown;
  431.       Repaint;
  432.     end;
  433.     Click;
  434.   end;
  435. end;
  436.  
  437. procedure TColorButton.KeyAccel(var Message: TCMDialogChar);
  438. begin
  439.   with Message do begin
  440.     if IsAccel(CharCode, Caption) and Enabled then begin
  441.       Click;
  442.       Result := 1;
  443.     end else inherited;
  444.   end;
  445. end;
  446.  
  447. procedure TColorButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  448. begin
  449.   inherited MouseDown(Button, Shift, X, Y);
  450.  
  451.   if Enabled then begin
  452.     if (bsMultiState in FStyle) then begin
  453.       if FState = bsDown then FState := bsUp
  454.       else FState := bsDown;
  455.     end else FState := bsDown;
  456.  
  457.     Repaint;
  458.   end;
  459. end;
  460.  
  461. procedure TColorButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  462. begin
  463.   inherited MouseUp(Button, Shift, X, Y);
  464.  
  465.   if Enabled then begin
  466.     if not (bsMultiState in FStyle) then begin
  467.       FState := bsUp;
  468.       Repaint;
  469.     end;
  470.   end;
  471. end;
  472.  
  473. procedure TColorButton.SetAlignment(Value: TAlignment);
  474. begin
  475.   if (FAlignment <> Value) then begin
  476.     FAlignment := Value;
  477.     Repaint;
  478.   end;
  479. end;
  480.  
  481. procedure TColorButton.SetBevelStyle(Value: TButtonBevel);
  482. begin
  483.   if (FBevelStyle <> Value) then begin
  484.     FBevelStyle := Value;
  485.     Repaint;
  486.   end;
  487. end;
  488.  
  489. procedure TColorButton.SetBevelSize(Value: Integer);
  490. begin
  491.   if (Value < 1) then Value := 1;
  492.  
  493.   if (FBevelSize <> Value) then begin
  494.     FBevelSize := Value;
  495.     Repaint;
  496.   end;
  497. end;
  498.  
  499. procedure TColorButton.SetCaption(var Message: TMessage);
  500. begin
  501.   Repaint;
  502. end;
  503.  
  504. procedure TColorButton.SetColor(Value: TColor);
  505. begin
  506.   FShadowColor    := GetShadowColor(Value);
  507.   FHighLightColor := GetHighlightColor(Value);
  508.  
  509.   FColor := Value;
  510.  
  511.   Repaint;
  512. end;
  513.  
  514. procedure TColorButton.SetEnabled(var Message: TMessage);
  515. begin
  516.   inherited;
  517.  
  518.   if Enabled then FState := bsUp else FState := bsDisabled;
  519.   Repaint;
  520. end;
  521.  
  522. procedure TColorButton.SetFocusOff(var Message: TMessage);
  523. begin
  524.   inherited;
  525.  
  526.   FFocused := False;
  527.   Repaint;
  528. end;
  529.  
  530. procedure TColorButton.SetFocusOn(var Message: TMessage);
  531. begin
  532.   inherited;
  533.  
  534.   FFocused := True;
  535.   Repaint;
  536. end;
  537.  
  538. procedure TColorButton.SetFont(var Message: TMessage);
  539. begin
  540.   inherited;
  541.  
  542.   Repaint;
  543. end;
  544.  
  545. procedure TColorButton.SetFontStyle(Value: TFontStyle);
  546. begin
  547.   if (FFontStyle <> Value) then begin
  548.     FFontStyle := Value;
  549.     Repaint;
  550.   end;
  551. end;
  552.  
  553. procedure TColorButton.SetPicture(Value: TPicture);
  554. begin
  555.   if (FPicture <> Value) then begin
  556.     FPicture.Assign(Value);
  557.     Repaint;
  558.   end;
  559. end;
  560.  
  561. procedure TColorButton.SetSize(var Message: TMessage);
  562. begin
  563.   Repaint;
  564. end;
  565.  
  566. procedure TColorButton.SetSpacing(Value: Integer);
  567. begin
  568.   if (Value < 0) then Value := 0;
  569.  
  570.   if (FSpacing <> Value) then begin
  571.     FSpacing := Value;
  572.     Repaint;
  573.   end;
  574. end;
  575.  
  576. procedure TColorButton.SetStyle(Value: TButtonStyle);
  577. begin
  578.   if (FStyle <> Value) then begin
  579.     FStyle := Value;
  580.  
  581.     Repaint;
  582.   end;
  583. end;
  584.  
  585. function TColorButton.GetValue: Boolean;
  586. begin
  587.   Result := (FState = bsDown);
  588. end;
  589.  
  590. procedure TColorButton.SetValue(Value: Boolean);
  591. begin
  592.   if (bsMultiState in FStyle) then begin
  593.     if Value then FState := bsDown
  594.     else FState := bsUp;
  595.     Repaint;
  596.   end;
  597. end;
  598.  
  599. end.
  600.