MMBmpBtn.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:38k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49(0)351-8037944               =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/index.html               =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 04.01.99 - 16:56:24 $                                        =}
  24. {========================================================================}
  25. unit MMBmpBtn;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29.     Windows,
  30.     SysUtils,
  31.     Messages,
  32.     Classes,
  33.     Graphics,
  34.     Controls,
  35.     CommCtrl,
  36.     ExtCtrls,
  37.     Menus,
  38.     Forms,
  39.     Buttons,
  40.     MMObj,
  41.     MMUtils,
  42.     MMBmpLst,
  43.     MMObsrv;
  44. type
  45.     TMMButtonStyle   = (bsRegular,bsIndent,bsLight,bsDark,bsMono,bsExplorer,bsHighLight,bsNone);
  46.     TMMButtonState   = (bsUp,bsDown,bsExclusive);
  47.     TMMTextAlign     = (ttaTopLeft,ttaTop,ttaTopRight,ttaRight,ttaBottomRight,
  48.                         ttaBottom,ttaBottomLeft,ttaLeft,ttaCenter);
  49.     TMMGetGylphIndex = procedure(Sender: TObject; IsDown: Boolean; var Index: integer) of object;
  50.     {-- TMMBitmapButton -------------------------------------------------------}
  51.     TMMBitmapButton = class(TMMCustomBitmapListControl)
  52.     private
  53.        FAutoSize       : Boolean;
  54.        FIsDown         : Boolean;
  55.        FTextAlign      : TMMTextAlign;
  56.        FCaption        : TCaption;
  57.        FAutoGray       : Boolean;
  58.        FShowDisabled   : Boolean;
  59.        FMouseDown      : Boolean;
  60.        FMouseInside    : Boolean;
  61.        FShowPressed    : Boolean;
  62.        FSpacing        : integer;
  63.        FTempGlyph      : TBitmap;
  64.        FFreeTempGlyph  : Boolean;
  65.        FSaveBitmap     : TBitmap;
  66.        FState          : TMMButtonState;
  67.        FBorderSize     : Cardinal;
  68.        FNumGlyphs      : integer;
  69.        FStyle          : TMMButtonStyle;
  70.        FInButton       : Boolean;
  71.        FWordWrap       : Boolean;
  72.        FStayDown       : Boolean;
  73.        FDownIndentH    : integer;
  74.        FDownIndentV    : integer;
  75.        FSwitch         : Boolean;
  76.        FDoubleBuffer   : Boolean;
  77.        FAllowRightMouse: Boolean;
  78.        {$IFDEF BUILD_ACTIVEX}
  79.        FTimer          : TTimer;
  80.        {$ENDIF}
  81.        FOnGetGlyphIndex: TMMGetGylphIndex;
  82.        FOnMouseEnter   : TNotifyEvent;
  83.        FOnMouseExit    : TNotifyEvent;
  84.        procedure SetDoubleBuffer(Value: Boolean);
  85.        procedure SetAutoSize(Value: Boolean);
  86.        procedure SetAutoGray(aValue: Boolean);
  87.        procedure SetShowDisabled(aValue: Boolean);
  88.        procedure SetStayDown(aValue: Boolean);
  89.        procedure SetWordWrap(aValue: Boolean);
  90.        procedure SetSpacing(aValue: integer);
  91.        procedure SetTextAlign(aValue: TMMTextAlign);
  92.        procedure SetCaption(aValue: TCaption);
  93.        procedure SetNumGlyphs(aValue: integer);
  94.        procedure SetButtonStyle(aValue: TMMButtonStyle);
  95.        procedure SetBorderWidth(aValue: Cardinal);
  96.        procedure SetDownIndent(index, aValue: integer);
  97.        procedure DetectNumGlyphs;
  98.        function  GetSrcRect(index: integer): TRect;
  99.        procedure PrepareGlyphs;
  100.        {$IFDEF BUILD_ACTIVEX}
  101.        procedure DoMouseTimer(Sender: TObject);
  102.        {$ENDIF}
  103.        function  InBtn(X,Y: Integer): Boolean;
  104.        procedure DrawTheText(Canvas: TCanvas; aRect: TRect);
  105.        procedure DrawTheBitmap(Canvas: TCanvas; aRect:TRect);
  106.        procedure DrawTheButton(Canvas: TCanvas);
  107.        procedure PaintButton(Canvas: TCanvas);
  108.        procedure CMMouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
  109.        procedure CMMouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
  110.        procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
  111.        procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  112.        procedure CMTransColorChanged(var Message: TMessage); message CM_TRANSCOLORCHANGED;
  113.     protected
  114.        procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  115.        procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  116.        procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  117.        procedure Paint; override;
  118.        procedure Loaded; override;
  119.        procedure BitmapChanged; override;
  120.     public
  121.        constructor Create(AOwner: TComponent); override;
  122.        destructor  Destroy; override;
  123.        procedure SetBounds(aLeft, aTop, aWidth, aHeight: integer); override;
  124.        procedure RedrawButton;
  125.        property State: TMMButtonState read FState;
  126.     published
  127.        property OnClick;
  128.        property OnMouseDown;
  129.        property OnMouseMove;
  130.        property OnMouseUp;
  131.        property OnDragDrop;
  132.        property OnDragOver;
  133.        property OnEndDrag;
  134.        property OnStartDrag;
  135.        property OnGetGlyphIndex: TMMGetGylphIndex read FOnGetGlyphIndex write FOnGetGlyphIndex;
  136.        property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
  137.        property OnMouseExit:  TNotifyEvent read FOnMouseExit  write FOnMouseExit;
  138.        property Enabled;
  139.        property Font;
  140.        property ParentFont;
  141.        property ParentShowHint;
  142.        property ShowHint;
  143.        property Visible;
  144.        property Color;
  145.        property DragCursor;
  146.        property ParentColor;
  147.        property PopupMenu;
  148.        property Transparent default True;
  149.        property TransparentColor;
  150.        property TransparentMode;
  151.        property BitmapList;
  152.        property BitmapIndex;
  153.        property AutoSize: Boolean read FAutoSize write SetAutoSize default False;
  154.        property AutoGray: Boolean read FAutoGray write SetAutoGray default True;
  155.        property ShowDisabled: Boolean read FShowDisabled write SetShowDisabled default True;
  156.        property BorderWidth: Cardinal read FBorderSize write SetBorderWidth default 1;
  157.        property Caption: TCaption read FCaption write SetCaption;
  158.        property Down: Boolean read FStayDown write SetStayDown default False;
  159.        property DownIndentHoriz: integer index 0 read FDownIndentH write SetDownIndent default 1;
  160.        property DownIndentVert: integer index 1 read FDownIndentV write SetDownIndent default 1;
  161.        property ButtonStyle: TMMButtonStyle read FStyle write SetButtonStyle default bsExplorer;
  162.        property NumGlyphs: integer read FNumGlyphs write SetNumGlyphs default 1;
  163.        property ShowPressed: Boolean read FShowPressed write FShowPressed default True;
  164.        property Switch: Boolean read FSwitch write FSwitch default False;
  165.        property Spacing: integer read FSpacing write SetSpacing default 2;
  166.        property TextAlign: TMMTextAlign read FTextAlign write SetTextAlign default ttaCenter;
  167.        property WordWrap: Boolean read FWordWrap write SetWordWrap default False;
  168.        property DoubleBuffer: Boolean read FDoubleBuffer write SetDoubleBuffer default False;
  169.        property AllowRightMouse: Boolean read FAllowRightMouse write FAllowRightMouse default False;
  170.   end;
  171. implementation
  172. {------------------------------------------------------------------------------}
  173. procedure CreateMonoBitmap(Bitmap: TBitmap; R,G,B: integer);
  174. var
  175.    i,j: integer;
  176.    Clr: Longint;
  177. begin
  178.    { create a grayed version of a color bitmap }
  179.    if not Bitmap.Empty then
  180.    with Bitmap do
  181.    for i := 0 to Width do
  182.    begin
  183.       for j := 0 to Height do
  184.       begin
  185.          Clr := Canvas.Pixels[i,j];
  186.          Clr := (GetRValue(Clr)*R + GetGValue(Clr)*G + GetBValue(Clr)*B) div (R+G+B);
  187.          Canvas.Pixels[i,j] := RGB(Clr,Clr,Clr);
  188.       end;
  189.    end;
  190. end;
  191. {------------------------------------------------------------------------------}
  192. procedure CreateDisabledBitmap(Bitmap: TBitmap);
  193. const
  194.      ROP_DSPDxax = $00E20746;
  195. var
  196.    MonoBmp,TmpImage: TBitmap;
  197.    W,H: integer;
  198. begin
  199.    { create a disabled bitmap from a regular one, works best when bitmap  }
  200.    { has been reduced to a few colors.                                    }
  201.    if not Bitmap.Empty then
  202.    begin
  203.       MonoBmp  := TBitmap.Create;
  204.       TmpImage := TBitmap.Create;
  205.       try
  206.          W := Bitmap.Width;
  207.          H := Bitmap.Height;
  208.          with TmpImage do
  209.          begin
  210.             Width := W;
  211.             Height := H;
  212.             Canvas.Brush.Color := clBtnFace;
  213.          end;
  214.          with MonoBmp do
  215.          begin
  216.             Assign(Bitmap);
  217.             Canvas.Font.Color := clWhite;
  218.             Canvas.Brush.Color := clBlack;
  219.             Monochrome := True;
  220.          end;
  221.          with TmpImage.Canvas do
  222.          begin
  223.             Brush.Color := clBtnFace;
  224.             FillRect(Rect(0,0,W,H));
  225.             Brush.Color := clBtnHighLight;
  226.             SetTextColor(Handle, clBlack);
  227.             SetBkColor(Handle, clWhite);
  228.             BitBlt(Handle, 1, 1, W+1, H+1,MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
  229.             Brush.Color := clBtnShadow;
  230.             SetTextColor(Handle, clBlack);
  231.             SetBkColor(Handle, clWhite);
  232.             BitBlt(Handle, 0, 0, W, H,MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
  233.          end;
  234.          Bitmap.Assign(TmpImage);
  235.       finally
  236.          MonoBmp.Free;
  237.          TmpImage.Free;
  238.       end;
  239.    end;
  240. end;
  241. {------------------------------------------------------------------------------}
  242. procedure CreateBWBitmap(Bitmap: TBitmap);
  243. var
  244.    i,j,W,H: integer;
  245.    Clr: TColor; Col: Longint;
  246. begin
  247.    { create a disabled bitmap by changing all colors to either black or }
  248.    { Clr and then running it through DisabledBitmap                     }
  249.    if not Bitmap.Empty then
  250.    begin
  251.       W   := Bitmap.Width;
  252.       H   := Bitmap.Height;
  253.       Clr := Bitmap.Canvas.Pixels[0,0];// TODO: ev. hier unterstes Pixel nehmen
  254.       for i := 0 to W do
  255.       begin
  256.          for j := 0 to H do
  257.          begin
  258.             Col := Bitmap.Canvas.Pixels[i,j];
  259.             if (Col <> clWhite) and (Col <> Clr) then
  260.                 Col := clBlack
  261.             else
  262.                 Col := Clr;
  263.             Bitmap.Canvas.Pixels[i,j] := Col;
  264.          end;
  265.       end;
  266.       CreateDisabledBitmap(Bitmap);
  267.    end;
  268. end;
  269. {== TMMBitmapButton ===========================================================}
  270. constructor TMMBitmapButton.Create(AOwner: TComponent);
  271. begin
  272.    FTempGlyph      := nil;
  273.    FFreeTempGlyph  := False;
  274.    FSaveBitmap     := nil;
  275.    inherited Create(AOwner);
  276.    ControlStyle    := ControlStyle - [csOpaque,csDoubleClicks,csClickEvents];
  277.    FNumGlyphs      := 1;
  278.    FState          := bsUp;
  279.    FMouseInside    := False;
  280.    FAutoGray       := True;
  281.    FShowDisabled   := True;
  282.    FShowPressed    := True;
  283.    FBorderSize     := 1;
  284.    FStayDown       := False;
  285.    FSpacing        := 2;
  286.    FMouseDown      := False;
  287.    FTextAlign      := ttaCenter;
  288.    FInButton       := False;
  289.    FWordwrap       := False;
  290.    FStyle          := bsExplorer;
  291.    FIsDown         := False;
  292.    FDownIndentH    := 1;
  293.    FDownIndentV    := 1;
  294.    FSwitch         := False;
  295.    FDoubleBuffer   := False;
  296.    FAllowRightMouse:= False;
  297.    Transparent   := True;
  298.    SetBounds(0,0,40,40);
  299. end;
  300. {-- TMMBitmapButton -----------------------------------------------------------}
  301. destructor TMMBitmapButton.Destroy;
  302. begin
  303.    if (FSaveBitmap <> nil) then
  304.    begin
  305.       FSaveBitmap.Free;
  306.       FSaveBitmap := nil;
  307.    end;
  308.    if FFreeTempGlyph and (FTempGlyph <> nil) then
  309.    begin
  310.       FTempGlyph.Free;
  311.       FTempGlyph := nil;
  312.       FFreeTempGlyph := False;
  313.    end;
  314.    {$IFDEF BUILD_ACTIVEX}
  315.    if (FTimer <> nil) then
  316.    begin
  317.       FTimer.Free;
  318.       FTimer := nil;
  319.    end;
  320.    {$ENDIF}
  321.    inherited Destroy;
  322. end;
  323. {-- TMMBitmapButton -----------------------------------------------------------}
  324. procedure TMMBitmapButton.BitmapChanged;
  325. begin
  326.    if BitmapValid then DetectNumGlyphs;
  327.    PrepareGlyphs;
  328.    inherited BitmapChanged;
  329. end;
  330. {-- TMMBitmapButton -----------------------------------------------------------}
  331. procedure TMMBitmapButton.SetBounds(aLeft, aTop, aWidth, aHeight: integer);
  332. begin
  333.    if ((Width <> aWidth) or (Height <> aHeight)) and (FSaveBitmap <> nil) then
  334.    begin
  335.       FSaveBitmap.Width  := aWidth;
  336.       FSaveBitmap.Height := 2*aHeight;
  337.    end;
  338.    inherited SetBounds(aLeft, aTop, aWidth, aHeight);
  339. end;
  340. {-- TMMBitmapButton -----------------------------------------------------------}
  341. procedure TMMBitmapButton.SetDoubleBuffer(Value: Boolean);
  342. begin
  343.    if (Value <> FDoubleBuffer) or (Value and (FSaveBitmap = nil)) then
  344.    begin
  345.       FDoubleBuffer := Value;
  346.       if not FDoubleBuffer then
  347.       begin
  348.          if (FSaveBitmap <> nil) then
  349.          begin
  350.             FSaveBitmap.Free;
  351.             FSaveBitmap := nil;
  352.             Repaint;
  353.          end;
  354.       end
  355.       else if not (csDesigning in ComponentState) and
  356.               not (csReading in ComponentState) and
  357.               not (csLoading in ComponentState) then
  358.       begin
  359.          if (FSaveBitmap = nil) then
  360.          begin
  361.             FSaveBitmap := TBitmap.Create;
  362.             FSaveBitmap.Width  := Width;
  363.             FSaveBitmap.Height := 2*Height;
  364.             Repaint;
  365.          end;
  366.       end;
  367.    end;
  368. end;
  369. {-- TMMBitmapButton -----------------------------------------------------------}
  370. procedure TMMBitmapButton.PrepareGlyphs;
  371. var
  372.    Bmp,Glyph: TBitmap;
  373.    TmpWidth,Cnt: integer;
  374.    Dest,Source: TRect;
  375. begin
  376.    if (csLoading in ComponentState) or
  377.       (csReading in ComponentState) or
  378.       (csDestroying in ComponentState) then exit;
  379.    if (Bitmap <> nil) and not Bitmap.Empty then
  380.    begin
  381.       Glyph := Bitmap;
  382.       TmpWidth := Glyph.Width div FNumGlyphs;
  383.       if AutoSize and (TmpWidth > 0) and (Glyph.Height > 0) then
  384.          SetBounds(Left, Top, TmpWidth, Glyph.Height);
  385.       Cnt := FNumGlyphs;
  386.       if (FNumGlyphs = 1) or
  387.          (((ButtonStyle = bsExplorer) or (ButtonStyle = bsHighLight)) and FAutoGray) then
  388.             inc(Cnt,2);
  389.       if (Cnt > FNumGlyphs) then
  390.       begin
  391.          if (FTempGlyph = nil) or not FFreeTempGlyph then
  392.          begin
  393.             FTempGlyph := TBitmap.Create;
  394.             FFreeTempGlyph := True;
  395.          end;
  396.          FTempGlyph.Width := Cnt*TmpWidth;
  397.          FTempGlyph.Height := Glyph.Height;
  398.          FTempGlyph.HandleType := Bitmap.HandleType;
  399.          { create the Temp Glyph }
  400.          FTempGlyph.Canvas.Draw(0,0,Glyph);
  401.          Bmp := TBitmap.Create;
  402.          try
  403.             Bmp.Width := TmpWidth;
  404.             Bmp.Height := Glyph.Height;
  405.             Dest := GetSrcRect(FNumGlyphs);
  406.             Source := GetSrcRect(0);
  407.             Bmp.Canvas.CopyRect(Source,Glyph.Canvas,Source);
  408.             { create the disabled and grayed bitmaps too }
  409.             CreateMonoBitmap(Bmp,11,59,30);
  410.             FTempGlyph.Canvas.CopyRect(Dest,Bmp.Canvas,Source);
  411.             Dest := GetSrcRect(FNumGlyphs+1);
  412.             Bmp.Canvas.CopyRect(Source,Glyph.Canvas,Source);
  413.             CreateBWBitmap(Bmp);
  414.             FTempGlyph.Canvas.CopyRect(Dest,Bmp.Canvas,Source);
  415.          finally
  416.             Bmp.Free;
  417.          end;
  418.       end
  419.       else
  420.       begin
  421.          if (FTempGlyph <> nil) and FFreeTempGlyph then
  422.          begin
  423.             FTempGlyph.Free;
  424.             FTempGlyph := nil;
  425.          end;
  426.          FFreeTempGlyph := False;
  427.          FTempGlyph := Glyph;
  428.       end;
  429.       Invalidate;
  430.    end;
  431. end;
  432. {-- TMMBitmapButton -----------------------------------------------------------}
  433. procedure TMMBitmapButton.Loaded;
  434. begin
  435.    inherited Loaded;
  436.    PrepareGlyphs;
  437.    SetDoubleBuffer(FDoubleBuffer);
  438. end;
  439. {-- TMMBitmapButton -----------------------------------------------------------}
  440. function TMMBitmapButton.GetSrcRect(index: integer): TRect;
  441. begin
  442.    Result.Left := index * (Bitmap.Width div FNumGlyphs);
  443.    Result.Top := 0;
  444.    Result.Right := (index+1) * (Bitmap.Width div FNumGlyphs);
  445.    Result.Bottom := Bitmap.Height;
  446. end;
  447. {-- TMMBitmapButton -----------------------------------------------------------}
  448. procedure TMMBitmapButton.DetectNumGlyphs;
  449. begin
  450.    if (csLoading in ComponentState) or
  451.       (csReading in ComponentState) or
  452.       (csDestroying in ComponentState) then exit;
  453.    if BitmapValid and (Bitmap.Height > 0) and (FNumGlyphs = 1) then
  454.    with Bitmap do
  455.    begin
  456.       if Width mod Height = 0 then
  457.       begin
  458.          FNumGlyphs := Min(Width div Height,4);
  459.       end;
  460.    end;
  461. end;
  462. {-- TMMBitmapButton -----------------------------------------------------------}
  463. procedure TMMBitmapButton.SetNumGlyphs(aValue: integer);
  464. begin
  465.    if (FNumGlyphs <> aValue) then
  466.    begin
  467.       FNumGlyphs := Max(aValue,1);
  468.       PrepareGlyphs;
  469.    end;
  470. end;
  471. {-- TMMBitmapButton -----------------------------------------------------------}
  472. procedure TMMBitmapButton.SetAutoSize(Value: Boolean);
  473. begin
  474.    FAutoSize := Value;
  475.    PrepareGlyphs;
  476. end;
  477. {-- TMMBitmapButton -----------------------------------------------------------}
  478. procedure TMMBitmapButton.SetAutoGray(aValue: Boolean);
  479. begin
  480.    if (aValue <> FAutoGray) then
  481.    begin
  482.       FAutoGray := aValue;
  483.       PrepareGlyphs;
  484.    end;
  485. end;
  486. {-- TMMBitmapButton -----------------------------------------------------------}
  487. procedure TMMBitmapButton.SetShowDisabled(aValue: Boolean);
  488. begin
  489.    if (aValue <> FShowDisabled) then
  490.    begin
  491.       FShowDisabled := aValue;
  492.       Invalidate;
  493.    end;
  494. end;
  495. {-- TMMBitmapButton -----------------------------------------------------------}
  496. procedure TMMBitmapButton.SetButtonStyle(aValue: TMMButtonStyle);
  497. begin
  498.    if (FStyle <> aValue) then
  499.    begin
  500.       FStyle := aValue;
  501.       PrepareGlyphs;
  502.    end;
  503. end;
  504. {-- TMMBitmapButton -----------------------------------------------------------}
  505. procedure TMMBitmapButton.SetCaption(aValue: TCaption);
  506. begin
  507.    if (FCaption <> aValue) then
  508.    begin
  509.       FCaption := aValue;
  510.       Invalidate;
  511.    end;
  512. end;
  513. {-- TMMBitmapButton -----------------------------------------------------------}
  514. procedure TMMBitmapButton.SetBorderWidth(aValue: Cardinal);
  515. begin
  516.    if (FBorderSize <> aValue) then
  517.    begin
  518.       FBorderSize := aValue;
  519.       Invalidate;
  520.    end;
  521. end;
  522. {-- TMMBitmapButton -----------------------------------------------------------}
  523. procedure TMMBitmapButton.SetStayDown(aValue: Boolean);
  524. begin
  525.    if (FStayDown <> aValue) then
  526.    begin
  527.       FStayDown := aValue;
  528.       if FStayDown then
  529.       begin
  530.          FMouseDown := True;
  531.          FState := bsDown;
  532.       end
  533.       else
  534.       begin
  535.          FMouseDown := False;
  536.          FState := bsUp;
  537.       end;
  538.       Refresh;
  539.    end;
  540. end;
  541. {-- TMMBitmapButton -----------------------------------------------------------}
  542. procedure TMMBitmapButton.SetWordWrap(aValue: Boolean);
  543. begin
  544.    if (FWordWrap <> aValue) then
  545.    begin
  546.       FWordwrap := aValue;
  547.       Invalidate;
  548.    end;
  549. end;
  550. {-- TMMBitmapButton -----------------------------------------------------------}
  551. procedure TMMBitmapButton.SetSpacing(aValue: integer);
  552. begin
  553.    if (aValue <> FSpacing) then
  554.    begin
  555.       FSpacing := aValue;
  556.       Invalidate;
  557.    end;
  558. end;
  559. {-- TMMBitmapButton -----------------------------------------------------------}
  560. procedure TMMBitmapButton.SetTextAlign(aValue: TMMTextAlign);
  561. begin
  562.    if (FTextAlign <> aValue) then
  563.    begin
  564.       FTextAlign := aValue;
  565.       Invalidate;
  566.    end;
  567. end;
  568. {-- TMMBitmapButton -----------------------------------------------------------}
  569. procedure TMMBitmapButton.SetDownIndent(index, aValue: integer);
  570. begin
  571.    aValue := Max(aValue,0);
  572.    case index of
  573.        0: if FDownIndentH = aValue then exit else FDownIndentH := aValue;
  574.        1: if FDownIndentV = aValue then exit else FDownIndentV := aValue;
  575.    end;
  576.    Invalidate;
  577. end;
  578. {-- TMMBitmapButton -----------------------------------------------------------}
  579. procedure TMMBitmapButton.CMDialogChar(var Message: TCMDialogChar);
  580. begin
  581.    { Handle speedkeys (Alt + key) }
  582.    with Message do
  583.    if IsAccel(CharCode, FCaption) and Enabled then
  584.    begin
  585.       Click;
  586.       Result := 1;
  587.    end
  588.    else inherited;
  589. end;
  590. {-- TMMBitmapButton -----------------------------------------------------------}
  591. procedure TMMBitmapButton.CMTransColorChanged(var message: TMessage);
  592. begin
  593.    PrepareGlyphs;
  594.    inherited;
  595. end;
  596. {-- TMMBitmapButton -----------------------------------------------------------}
  597. procedure TMMBitmapButton.CMEnabledChanged(var Message: TMessage);
  598. begin
  599.    if not Enabled then
  600.    begin
  601.       FState     := bsUp;
  602.       FMousedown := False;
  603.       FIsDown    := False;
  604.       FInButton  := False;
  605.    end;
  606.    Repaint;
  607. end;
  608. {-- TMMBitmapButton -----------------------------------------------------------}
  609. procedure TMMBitmapButton.CMMouseEnter(var Msg: TMessage);
  610. begin
  611.    if Enabled and not FStayDown then
  612.    begin
  613.       FInButton := True;
  614.       if (ButtonStyle = bsExplorer) or (ButtonStyle = bsHighLight) then RedrawButton;
  615.       if Assigned(FOnMouseEnter) then FOnMouseEnter(Self);
  616.    end;
  617. end;
  618. {-- TMMBitmapButton -----------------------------------------------------------}
  619. procedure TMMBitmapButton.CMMouseLeave(var msg: TMessage);
  620. begin
  621.    if Enabled and not FStayDown then
  622.    begin
  623.       FInButton := False;
  624.       if (ButtonStyle = bsExplorer) or (ButtonStyle = bsHighLight) then RedrawButton;
  625.       if Assigned(FOnMouseExit) then FOnMouseExit(Self);
  626.    end;
  627. end;
  628. {-- TMMBitmapButton -----------------------------------------------------------}
  629. function TMMBitmapButton.InBtn(X, Y: Integer): Boolean;
  630. begin
  631.    Result := PtInRect(ClientRect,Point(X,Y));
  632. end;
  633. {-- TMMBitmapButton -----------------------------------------------------------}
  634. procedure TMMBitmapButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  635. var
  636.    Pt: TPoint;
  637.    Msg: TMsg;
  638. begin
  639.    if (Button = mbLeft) or (AllowRightMouse and (Button = mbRight)) then
  640.    begin
  641.       if not Enabled or FIsDown then exit;
  642.       MouseCapture := True;
  643.       FIsDown := True;
  644.       if InBtn(X,Y) then
  645.       begin
  646.          FMouseDown := True;
  647.          FState := bsDown;
  648.          RedrawButton;
  649.       end;
  650.       inherited MouseDown(Button,Shift,X,Y);
  651.       if Assigned(PopUpMenu) and PopupMenu.AutoPopup then
  652.       begin
  653.          { calc where to put menu }
  654.          Pt := ClientToScreen(Point(0, Height+2));
  655.          PopupMenu.PopupComponent := Self;
  656.          PopUpMenu.Popup(Pt.X, Pt.Y);
  657.          { wait 'til menu is done }
  658.          while PeekMessage(Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) do;
  659.          { release button }
  660.          MouseUp(Button,Shift,X,Y);
  661.          MouseCapture := False;
  662.       end;
  663.    end
  664.    else inherited MouseDown(Button,Shift,X,Y);
  665. end;
  666. {-- TMMBitmapButton -----------------------------------------------------------}
  667. procedure TMMBitmapButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  668. begin
  669.    if (Button = mbLeft) or (AllowRightMouse and (Button = mbRight)) then
  670.    begin
  671.       if not Enabled or not FIsDown then exit;
  672.       FIsDown := False;
  673.       FMouseDown := False;
  674.       if not FStayDown then FState := bsUp;
  675.       FInButton := InBtn(X,Y);
  676.       if not Switch then
  677.       begin
  678.          RedrawButton;
  679.       end
  680.       else if FInButton then
  681.       begin
  682.          SetStayDown(not FStayDown);
  683.       end;
  684.       inherited MouseUp(Button,Shift,X,Y);
  685.       MouseCapture := False;
  686.       if FInButton then Click;
  687.    end
  688.    else inherited MouseUp(Button,Shift,X,Y);
  689. end;
  690. {$IFDEF BUILD_ACTIVEX}
  691. {-- TMMBitmapButton -----------------------------------------------------------}
  692. procedure TMMBitmapButton.DoMouseTimer(Sender: TObject);
  693. var
  694.    P: TPoint;
  695. begin
  696.   GetCursorPos(P);
  697.   if (FindDragTarget(P, True) <> Self) then
  698.   begin
  699.      FTimer.Free;
  700.      FTimer := nil;
  701.      Perform(CM_MOUSELEAVE, 0, 0);
  702.   end;
  703. end;
  704. {$ENDIF}
  705. {-- TMMBitmapButton -----------------------------------------------------------}
  706. procedure TMMBitmapButton.MouseMove(Shift: TShiftState; X, Y: Integer);
  707. begin
  708.    {$IFDEF BUILD_ACTIVEX}
  709.    if InBtn(X,Y) then
  710.    begin
  711.       if (FTimer = nil) then
  712.       begin
  713.          FTimer := TTimer.Create(Self);
  714.          FTimer.Interval := 50;
  715.          FTimer.OnTimer := DoMouseTimer;
  716.          Perform(CM_MOUSEENTER, 0, 0);
  717.       end;
  718.    end;
  719.    {$ENDIF}
  720.    inherited MouseMove(Shift,X,Y);
  721.    if FMouseDown and not FStayDown then
  722.    begin
  723.       if not InBtn(X,Y) then
  724.       begin
  725.          if FState = bsDown then { mouse has slid off, so release }
  726.          begin
  727.             FState := bsUp;
  728.             RedrawButton;
  729.          end;
  730.       end
  731.       else
  732.       begin
  733.          if FState = bsUp then { mouse has slid back on, so push }
  734.          begin
  735.             FState := bsDown;
  736.             RedrawButton;
  737.          end;
  738.       end;
  739.    end;
  740. end;
  741. {-- TMMBitmapButton -----------------------------------------------------------}
  742. procedure TMMBitmapButton.RedrawButton;
  743. begin
  744.    if not Visible then exit;
  745.    if (csDesigning in ComponentState) then Repaint
  746.    else
  747.    begin
  748.       if (FSaveBitmap <> nil) then
  749.       begin
  750.          { first copy the background to our bitmap }
  751.          FSaveBitmap.Canvas.CopyRect(Rect(0,0,Width,Height),
  752.                                      FSaveBitmap.Canvas,
  753.                                      Rect(0,Height,Width,2*Height));
  754.          { now draw the button to the bitmap }
  755.          PaintButton(FSaveBitmap.Canvas);
  756.          { copy to screen }
  757.          Canvas.Draw(0,0,FSaveBitmap);
  758.       end
  759.       else PaintButton(Canvas);
  760.    end;
  761. end;
  762. {-- TMMBitmapButton -----------------------------------------------------------}
  763. procedure TMMBitmapButton.DrawTheText(Canvas: TCanvas; aRect: TRect);
  764. var
  765.    Flags,MidX,MidY: Integer;
  766.    DC: THandle;
  767.    TmpRect:TRect;
  768. begin
  769.    Canvas.Font := Self.Font;
  770.    DC := Canvas.Handle; { reduce calls to GetHandle }
  771.    if FWordWrap then
  772.       Flags := DT_WORDBREAK or DT_END_ELLIPSIS
  773.    else
  774.       Flags := DT_SINGLELINE or DT_END_ELLIPSIS;
  775.    TmpRect := Rect(0,0,Width,Height);
  776.    { calculate width and height of text: }
  777.    DrawText(DC, PChar(FCaption), Length(FCaption), TmpRect, Flags or DT_CALCRECT);
  778.    MidY := TmpRect.Bottom - TmpRect.Top;
  779.    MidX := TmpRect.Right-TmpRect.Left;
  780.    Flags := DT_CENTER or DT_END_ELLIPSIS;
  781.    case TextAlign of
  782.       ttaTop        : OffsetRect(TmpRect,Width div 2-MidX div 2,aRect.Top - MidY - Spacing);
  783.       ttaTopLeft    : OffsetRect(TmpRect,Spacing,aRect.Top - MidY - Spacing);
  784.       ttaTopRight   : OffsetRect(TmpRect,Width - TmpRect.Right - Spacing,aRect.Top - MidY - Spacing);
  785.       ttaBottom     : OffsetRect(TmpRect,Width div 2-MidX div 2,aRect.Bottom + Spacing);
  786.       ttaBottomLeft : OffsetRect(TmpRect,Spacing,aRect.Bottom + Spacing);
  787.       ttaBottomRight: OffsetRect(TmpRect,Width - MidX - Spacing,aRect.Bottom + Spacing);
  788.       ttaCenter     : OffsetRect(TmpRect,Width div 2 - MidX div 2,Height div 2 - MidY div 2);
  789.       ttaRight      : OffsetRect(TmpRect,Width  - MidX - Spacing,Height div 2 - MidY div 2);
  790.       ttaLeft       : OffsetRect(TmpRect,Spacing,Height div 2 - MidY div 2);
  791.    end;
  792.    if FWordWrap then
  793.       Flags := Flags or DT_WORDBREAK or DT_NOCLIP
  794.    else
  795.       Flags := Flags or DT_SINGLELINE or DT_NOCLIP;
  796.    if ((FState = bsDown) and FShowPressed) then
  797.        OffsetRect(TmpRect,FDownIndentH,FDownIndentV);
  798.    SetBkMode(DC,Windows.TRANSPARENT);
  799.    if not Enabled then
  800.    begin
  801.       { draw disabled text }
  802.       SetTextColor(DC,ColorToRGB(clBtnHighLight));
  803.       OffsetRect(TmpRect,1,1);
  804.       DrawText(DC, PChar(FCaption), Length(FCaption), TmpRect, Flags);
  805.       OffsetRect(TmpRect,-1,-1);
  806.       SetTextColor(DC,ColorToRGB(clBtnShadow));
  807.    end
  808.    else SetTextColor(DC,Self.Font.Color);
  809.    DrawText(DC, PChar(FCaption), Length(FCaption), TmpRect, Flags);
  810. end;
  811. {-- TMMBitmapButton -----------------------------------------------------------}
  812. procedure TMMBitmapButton.DrawTheBitmap(Canvas: TCanvas; aRect:TRect);
  813. var
  814.    index: integer;
  815.    SrcRect: TRect;
  816. begin
  817.    if BitmapValid and (FTempGlyph <> nil) then
  818.    begin
  819.      Index := -1;
  820.      if assigned(FOnGetGlyphIndex) then
  821.      begin
  822.         FOnGetGlyphIndex(Self, FState = bsDown, Index);
  823.      end;
  824.      if (Index = -1) then
  825.      begin
  826.         Index := 0;
  827.         case FNumGlyphs of   {normal,disabled,down,down }
  828.            2: if not Enabled then Index := 1;
  829.            3: if not Enabled then
  830.                  Index := 1
  831.               else if (FState = bsDown) then
  832.                  Index := 2;
  833.            4: if not Enabled then
  834.                  Index := 1
  835.               else if FStayDown then
  836.                  Index := 3
  837.               else if (FState = bsDown) then
  838.                  Index := 2;
  839.         end;
  840.         { do we need the grayed bitmap ? }
  841.         if ((ButtonStyle = bsExplorer) or (ButtonStyle = bsHighLight)) and Enabled then
  842.         begin
  843.            if not FStayDown and not FInButton and FShowDisabled then
  844.            begin
  845.               if FAutoGray then
  846.                  Index := FNumGlyphs
  847.               else if (FNumGlyphs > 1) then
  848.                  Index := 1;
  849.            end;
  850.         end;
  851.         { do we need the disabled bitmap ? }
  852.         if not Enabled and (FNumGlyphs = 1) then Index := FNumGlyphs+1;
  853.      end;
  854.      SrcRect := GetSrcRect(index);
  855.      if ((FState = bsDown) and FShowPressed) then
  856.           OffsetRect(aRect,FDownIndentH,FDownIndentV);
  857.      if Transparent then
  858.      begin
  859.         DrawTransparentBitmapEx(Canvas.Handle, FTempGlyph.Handle,
  860.                                 aRect.Left, aRect.Top,
  861.                                 SrcRect,
  862.                                 GetTransparentColor);
  863.      end
  864.      else
  865.      begin
  866.         DrawTransparentBitmapEx(Canvas.Handle, FTempGlyph.Handle,
  867.                                 aRect.Left, aRect.Top,
  868.                                 SrcRect,
  869.                                 GetTransparentColorEx(FTempGlyph.Handle,Point(Index*Bitmap.Width div FNumGlyphs,FTempGlyph.Height)));
  870.      end;
  871.    end;
  872. end;
  873. {-- TMMBitmapButton -----------------------------------------------------------}
  874. procedure TMMBitmapButton.DrawTheButton(Canvas: TCanvas);
  875. var
  876.    Dest: TRect;
  877.    TmpWidth,TmpHeight: integer;
  878. begin
  879.    with Canvas do
  880.    begin
  881.       TmpWidth := 0;
  882.       TmpHeight := 0;
  883.       { find glyph bounding rect - adjust according to textalignment}
  884.       if BitmapValid then
  885.       begin
  886.          TmpWidth := Bitmap.Width div NumGlyphs;
  887.          if TmpWidth <= 0 then TmpWidth := Bitmap.Width;
  888.          TmpHeight := Bitmap.Height;
  889.       end;
  890.       { do top }
  891.       if TextAlign in [ttaBottomLeft,ttaBottom,ttaBottomRight] then
  892.          Dest.Top := Spacing
  893.       else if TextAlign in [ttaTopLeft,ttaTop,ttaTopRight] then
  894.          Dest.Top := Height - TmpHeight - Spacing
  895.       else
  896.          Dest.Top :=  (Height - TmpHeight) div 2;
  897.       if (TextAlign = ttaLeft) then               { left }
  898.           Dest.Left := Width - TmpWidth- Spacing
  899.       else if TextAlign = ttaRight then           { right }
  900.           Dest.Left := Spacing
  901.       else                                        { center }
  902.           Dest.Left := (Width - TmpWidth) div 2;
  903.       Dest.Bottom:= Dest.Top + TmpHeight;
  904.       Dest.Right := Dest.Left + TmpWidth;
  905.       if BitmapValid then DrawTheBitmap(Canvas,Dest);
  906.       { finally, do the caption }
  907.       if Length(FCaption) > 0 then DrawTheText(Canvas,Dest);
  908.    end;
  909. end;
  910. {-- TMMBitmapButton -----------------------------------------------------------}
  911. procedure TMMBitmapButton.PaintButton(Canvas: TCanvas);
  912. var
  913.    TmpRect: TRect;
  914. begin
  915.    TmpRect := Rect(0,0,Width,Height);
  916.    { draw the outline }
  917.    with Canvas do
  918.    begin
  919.       Brush.Color := Color;
  920.       Pen.Color   := clBlack;
  921.       Pen.Width   := BorderWidth;
  922.       case ButtonStyle of
  923.         bsNone,
  924.         bsHighLight:
  925.         begin
  926.            if not Transparent then
  927.               FillRect(Rect(0,0,Width,Height));
  928.            if (csDesigning in ComponentState) then
  929.            begin
  930.               Brush.Style := bsClear;
  931.               Pen.Style   := psDot;
  932.               Pen.Width   := 1;
  933.               Rectangle(TmpRect.Left,TmpRect.Top,TmpRect.Right,TmpRect.Bottom);
  934.               Pen.Style := psSolid;
  935.               Brush.Style := bsSolid;
  936.            end;
  937.         end;
  938.         bsExplorer:
  939.         begin
  940.            if not Transparent then
  941.               FillRect(Rect(0,0,Width,Height));
  942.            if (csDesigning in ComponentState) then
  943.               Frame3D(Canvas,TmpRect,clBtnHighLight,clBtnShadow,1);
  944.         end;
  945.         bsRegular:
  946.         begin
  947.            { draw outline }
  948.            Pen.Color := clBlack;
  949.            if not Transparent then
  950.               Rectangle(1,1,Width,Height)
  951.            else
  952.            begin
  953.               TmpRect := Rect(1,1,Width,Height);
  954.               Frame3D(Canvas,TmpRect,clBlack,clBlack,BorderWidth);
  955.            end;
  956.         end;
  957.         bsIndent:
  958.         begin
  959.            { draw outline }
  960.            Pen.Color := clBtnShadow;
  961.            if not Transparent then
  962.               Rectangle(0,0,Width-1,Height-1)
  963.            else
  964.            begin
  965.               TmpRect := Rect(0,0,Width-1,Height-1);
  966.               Frame3D(Canvas,TmpRect,clBtnShadow,clBtnShadow,BorderWidth)
  967.            end;
  968.            TmpRect := Rect(1,1,Width,Height);
  969.            Frame3D(Canvas,TmpRect,clBtnHighLight,clBtnHighLight,BorderWidth);
  970.         end;
  971.         bsLight:
  972.         begin
  973.            if not Transparent then
  974.               FillRect(Rect(0,0,Width,Height));
  975.            if (csDesigning in ComponentState) then
  976.               Frame3D(Canvas,TmpRect,clBtnHighLight,clBtnShadow,1);
  977.         end;
  978.         bsDark:
  979.         begin
  980.            if not Transparent then
  981.               FillRect(Rect(0,0,Width,Height));
  982.            if (csDesigning in ComponentState) then
  983.               Frame3D(Canvas,TmpRect,clBtnFace,cl3DDkShadow,1);
  984.         end;
  985.         bsMono:
  986.         begin
  987.            if not Transparent then
  988.               FillRect(Rect(0,0,Width,Height));
  989.            if (csDesigning in ComponentState) then
  990.               Frame3D(Canvas,TmpRect,clBtnHighLight,cl3DDkShadow,1);
  991.         end;
  992.       end;
  993.       TmpRect := Rect(1,1,Width-1,Height-1);
  994.       if (FState = bsDown) then
  995.       begin
  996.          if not (ButtonStyle = bsNone) or (ButtonStyle = bsHighLight) then
  997.          begin
  998.             InflateRect(TmpRect,1,1);
  999.             case ButtonStyle of
  1000.                 bsRegular : if ShowPressed then
  1001.                             begin
  1002.                                Frame3D(Canvas,TmpRect,clBlack,clBtnHighLight,BorderWidth);
  1003.                                Frame3D(Canvas,TmpRect,clBtnShadow,clBtnFace,BorderWidth);
  1004.                             end;
  1005.                 bsExplorer: if FInButton or FStayDown then
  1006.                             begin
  1007.                                if ShowPressed then
  1008.                                   Frame3D(Canvas,TmpRect,clBtnShadow,clBtnHighLight,BorderWidth)
  1009.                                else
  1010.                                   Frame3D(Canvas,TmpRect,clBtnHighLight,clBtnShadow,BorderWidth);
  1011.                             end;
  1012.                 bsIndent  : if ShowPressed then
  1013.                             begin
  1014.                                Frame3D(Canvas,TmpRect,clBlack,clBtnHighLight,BorderWidth);
  1015.                                Frame3D(Canvas,TmpRect,clBtnShadow,clBtnFace,BorderWidth);
  1016.                             end;
  1017.                 bsLight   : if ShowPressed then
  1018.                                Frame3D(Canvas,TmpRect,clBtnShadow,clBtnHighLight,1);
  1019.                 bsDark    : if ShowPressed then
  1020.                                Frame3D(Canvas,TmpRect,cl3DDkShadow,clBtnFace,1);
  1021.                 bsMono    : if ShowPressed then
  1022.                                Frame3D(Canvas,TmpRect,cl3DDkShadow,clBtnHighLight,1);
  1023.             end;
  1024.          end;
  1025.       end;
  1026.       if (FState = bsUp) then
  1027.       begin
  1028.          InflateRect(TmpRect,1,1);
  1029.          case ButtonStyle of
  1030.              bsRegular :
  1031.              begin
  1032.                 Frame3D(Canvas,TmpRect,clBtnHighLight,clBlack,BorderWidth);
  1033.                 Frame3D(Canvas,TmpRect,clBtnFace,clBtnShadow,BorderWidth);
  1034.              end;
  1035.              bsExplorer: if FInButton then
  1036.                             Frame3D(Canvas,TmpRect,clBtnHighLight,clBtnShadow,BorderWidth);
  1037.              bsIndent  : Frame3D(Canvas,TmpRect,clBtnShadow,clBtnHighLight,BorderWidth);
  1038.              bsLight   : Frame3D(Canvas,TmpRect,clBtnHighLight,clBtnShadow,1);
  1039.              bsDark    : Frame3D(Canvas,TmpRect,clBtnFace,cl3DDkShadow,1);
  1040.              bsMono    : Frame3D(Canvas,TmpRect,clBtnHighLight,cl3DDkShadow,1);
  1041.          end;
  1042.       end;
  1043.    end;
  1044.    { repaint rest }
  1045.    IntersectClipRect(Canvas.Handle,0,0,Width,Height);
  1046.    DrawTheButton(Canvas);
  1047.    //ExcludeClipRect(Canvas.Handle,0,0,Width,Height);
  1048. end;
  1049. {-- TMMBitmapButton -----------------------------------------------------------}
  1050. procedure TMMBitmapButton.Paint;
  1051. begin
  1052.    if not (csDesigning in ComponentState) and (FSaveBitmap <> nil) then
  1053.    begin
  1054.       { save the actual background }
  1055.       FSaveBitmap.Canvas.CopyRect(Rect(0,Height,Width,2*Height),Canvas,ClientRect);
  1056.    end;
  1057.    PaintButton(Canvas);
  1058. end;
  1059. end.