⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transbtn.pas

📁 透明按钮 透明按钮 透明按钮
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{ A speedbutton kind o button with regular,inset,explorer and no border styles }
{ by Peter Th鰎nqvist Jan 1997                                        }
{ 15 mar 1997: fixed MouseEnter/ MouseExit omission                   }
{ 7 apr 1997: fixed stupid bug in MouseMove handler (thanks to Magnus Myhrberg) }
{ 19 April 1997: Added Explorer style button and run-time mov(e?)able.
    (thanks to Alejandro Llorca)																			 }
{ 2 May 1997: added support for unfocused bitmap (fsExplorer) and
              disabled bitmap                                         }
{ 19 May 1997: added support for Down, Wordwrap and PopUpMenu         }
{ 16 june 1997: added CMEnabledChanged handler so button will go up   }
{ when disabled programmatically and also fixed csDoubleClicks bug (both by Sebastien Gandon) }
unit TransBtn;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,  CommCtrl,
  ExtCtrls,Menus, Forms;


type
  TNumGlyphs = 1..4;
  TFrameStyle = (fsRegular,fsIndent,fsExplorer,fsNone,fsLight,fsDark,fsMono);
  TButtonState=(bsUp,bsDown,bsExclusive);
  TTextAlign=(ttaTopLeft,ttaTop,ttaTopRight,ttaRight,ttaBottomRight,
              ttaBottom,ttaBottomLeft,ttaLeft,ttaCenter);

type
  TTransparentButton = class(TGraphicControl)
  private
    FIsDown:           Boolean;
    FTextAlign:        TTextAlign;
    FCaption:          TCaption;
    FAutoGray:         Boolean;          
    FTransparent:      Boolean;
    FMouseDown:        Boolean;
    FMouseInside:      Boolean;
    FShowPressed:      Boolean;
    FSpacing:          integer;
    FGlyph:            TBitmap;
    FGrayGlyph:        TBitmap;
    FPopUpMenu:        TPopUpMenu;
    FDisabledGlyph:    TBitmap;
    FState:            TButtonState;
    FBorderSize:       Cardinal;
    FNumGlyphs:        TNumGlyphs;
    ImList:            TImageList;
    FOutline:          TFrameStyle;
    FOnMouseEnter:     TNotifyEvent;
    FOnMouseExit:      TNotifyEvent;
    FInsideButton:     Boolean;
    FWordWrap:         Boolean;
    FStayDown:         Boolean;
    { added by Alejandro Llorca }
    FMovable:          Boolean; { to make it movable at runtime}
    PosY,PosX:         integer; {mousepos on start drag}
		 { ... }
{    Norris}
    FPattern: TBitmap;   {Fill pattern when button is set to stay down}
    procedure SetStayDown(Value:boolean);
    procedure SetWordWrap(Value:boolean);
    procedure SetSpacing(Value:integer);
    procedure SetTextAlign(Value:TTextAlign);
    procedure SetCaption(Value: TCaption);
    procedure SetGlyph(Bmp: TBitmap);
    procedure SetNumGlyphs(Value: TNumGlyphs);
    procedure SetFrameStyle(Value: TFrameStyle);
    procedure SetTransparent(Value:boolean);
    procedure SetBorderWidth(Value:Cardinal);
    procedure GlyphChanged(Sender:TObject);
    procedure CMMouseEnter(var msg: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var msg: TMessage); message CM_MOUSELEAVE;
    procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
    procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  protected
    procedure Notification(AComponent: TComponent; Operation:TOperation);override;
    procedure AddGlyphs(aGlyph:TBitmap;aColor:TColor;Value:integer);
    procedure DrawTheText(aRect: TRect);
    procedure DrawTheBitmap(aRect:TRect);
    function  InsideBtn(X,Y: Integer): boolean;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer);override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
    procedure Paint;  override;
    procedure PaintButton;
  public
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
    procedure Click;override;
    property Canvas;
  published
    property AutoGray:boolean read FAutoGray write FAutoGray default True;
    property BorderWidth:Cardinal read FBorderSize write SetBorderWidth default 1;
    property Caption: TCaption read FCaption write SetCaption;
    property Down: boolean read FStayDown write SetStayDown default False;
    property Enabled;
    property Font;
    property FrameStyle: TFrameStyle read FOutline write SetFrameStyle default fsExplorer;
    property Glyph: TBitmap read FGlyph write SetGlyph;
    property NumGlyphs: TNumGlyphs read FNumGlyphs write SetNumGlyphs default 1;
    property ParentFont;
    property ParentShowHint;
    property PopUpMenu: TPopUpMenu read FPopUpMenu write FPopUpMenu;
    property ShowHint;
    property ShowPressed:boolean read FShowPressed write FShowPressed default True;
    property Spacing:integer read FSpacing write SetSpacing default 2;
    property TextAlign:TTextAlign read FTextAlign write SetTextAlign default ttaCenter;
    property Transparent: boolean read FTransparent write SetTransparent default True;
    property Visible;
    property WordWrap:boolean read FWordWrap write SetWordWrap default False;
    property OnClick;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
    property OnMouseExit:  TNotifyEvent read FOnMouseExit  write FOnMouseExit;
    { AL: }
    property Movable: Boolean read FMovable write FMovable default False;
  end;


procedure Register;

implementation

{ create a grayed version of a color bitmap }
{ SLOW! don't use in realtime! }
procedure MonoBitmap(Bmp:TBitmap;R,G,B:integer);
var i,j:integer;col:longint;
begin
  if Bmp.Empty then Exit;
  for i := 0 to Bmp.Width do
    for j := 0 to Bmp.Height do
    begin
      Col := Bmp.Canvas.Pixels[i,j];
      Col := (GetRValue(Col)*R + GetGValue(Col)*G + GetBValue(Col)*B) div (R+G+B);
      Bmp.Canvas.Pixels[i,j] := RGB(Col,Col,Col);
    end;
end;

{ create a disabled bitmap from a regular one, works best when bitmap has been
reduced to a few colors. Used by BWBitmap }
procedure DisabledBitmap(Bmp:TBitmap);
const ROP_DSPDxax = $00E20746;
var MonoBmp,TmpImage: TBitmap;
    W,H:integer;
begin
 if Bmp.Empty then Exit;
	MonoBmp := TBitmap.Create;
 TmpImage := TBitmap.Create;
 W := Bmp.Width;
 H := Bmp.Height;

 with TmpImage do
 begin
   Width := W;
   Height := H;
   Canvas.Brush.Color := clBtnFace;
 end;

	try
   with MonoBmp do
   begin
     Assign(Bmp);
     Canvas.Font.Color := clWhite;
     Canvas.Brush.Color := clBlack;
     Monochrome := True;
   end;

   with TmpImage.Canvas do
   begin
     Brush.Color := clBtnFace;
     FillRect(Rect(0,0,W,H));
     Brush.Color := clBtnHighLight;
     SetTextColor(Handle, clBlack);
     SetBkColor(Handle, clWhite);
     BitBlt(Handle, 1, 1, W+1, H+1,MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
     Brush.Color := clBtnShadow;
     SetTextColor(Handle, clBlack);
     SetBkColor(Handle, clWhite);
     BitBlt(Handle, 0, 0, W, H,MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
   end;
   Bmp.Assign(TmpImage);
finally
 MonoBmp.Free;
 TmpImage.Free;
end;
end;

{ create a disabled bitmap by changing all colors to either black or tCol and then
  running it through DisabledBitmap }
{ SLOW! don't use in realtime! }
procedure BWBitmap(Bmp:TBitmap);
var i,j,W,H:integer;tcol:TColor;col:longint;
begin
  if Bmp.Empty then Exit;

  W := Bmp.Width;
  H := Bmp.Height;
  tCol := Bmp.Canvas.Pixels[0,0];

  for i := 0 to W do
    for j := 0 to H do
    begin
    Col := Bmp.Canvas.Pixels[i,j];
    if (Col <> clWhite) and (Col <> tCol) then
      Col := clBlack
    else
      Col := tCol;
    Bmp.Canvas.Pixels[i,j] := Col;
    end;
  DisabledBitmap(Bmp);
end;

function CreateBrushPattern: TBitmap;
var X, Y: Integer;
begin
  Result := TBitmap.Create;
  Result.Width := 8;     { must have this size }
  Result.Height := 8;
  with Result.Canvas do
  begin
    Brush.Style := bsSolid;
    Brush.Color := clBtnFace;
    FillRect(Rect(0, 0, Result.Width, Result.Height));
    for Y := 0 to 7 do
      for X := 0 to 7 do
        if (Y mod 2) = (X mod 2) then  { toggles between even/odd pixles }
          Pixels[X, Y] := clWhite;     { on even/odd rows }
  end;
end;

constructor TTransparentButton.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);
   if (csOpaque in ControlStyle) then
     ControlStyle := ControlStyle - [csOpaque];
   if (csDoubleClicks in ControlStyle) then
     ControlStyle := ControlStyle - [csDoubleClicks];
   FNumGlyphs:= 1;
   FState := bsUp;
   FMouseInside := False;
   FAutoGray := True;
   FShowPressed := True;
   FBorderSize := 1;
   FStayDown := False;
   SetBounds(0,0,40,40);
   FTransparent := True;

   ImList := TImageList.CreateSize(Width,Height);
   FGlyph:= TBitmap.Create;
   FGrayGlyph := TBitmap.Create;
   FDisabledGlyph := TBitmap.Create;
   FGlyph.OnChange := GlyphChanged;

   FNumGlyphs := 1;
   FSpacing := 2;
   FMouseDown:= False;
   FTextAlign := ttaCenter;
   FInsideButton := False;
   FWordwrap := False;
   FMovable:= False;
   FOutline := fsExplorer;
   FIsDown := False;
   { Norris }
   FPattern := CreateBrushPattern;
end;

destructor  TTransparentButton.Destroy;
begin
   FGlyph.Free;
   FGrayGlyph.Free;
   FDisabledGlyph.Free;
   ImList.Free;
   FPattern.Free;
   inherited Destroy;
end;

procedure TTransparentButton.AddGlyphs(aGlyph:TBitmap;aColor:TColor;Value:integer);
var Bmp:TBitmap;i,TmpWidth:integer;Dest,Source:TRect;
begin
      Bmp := TBitmap.Create;
try
      if aGlyph.Empty then Exit;
      if not aGlyph.Empty then
      begin
      { destroy old list }
        ImList.Clear;
        TmpWidth := aGlyph.Width div FNumGlyphs;
        ImList.Width := TmpWidth;
        ImList.Height := aGlyph.Height;
        Bmp.Width := ImList.Width;
        Bmp.Height := ImList.Height;
        Dest := Rect(0,0,Bmp.Width,Bmp.Height);
        { create the imagelist }
        for i := 0 to FNumGlyphs - 1 do
        begin
          Source := Rect(i * Bmp.Width,0,i * Bmp.Width + Bmp.Width,Bmp.Height);
          Bmp.Canvas.CopyRect(Dest,aGlyph.Canvas,Source);
          if i = 0 then { first picture }
          begin
          { create the disabled and grayed bitmaps too }
            FGrayGlyph.Assign(Bmp);
            MonoBitmap(FGrayGlyph,11,59,30);
            FDisabledGlyph.Assign(Bmp);
            BWBitmap(FDisabledGlyph);
          end;
          ImList.AddMasked(Bmp,Bmp.TransparentColor);
        end;
        { add last }
        ImList.AddMasked(FGrayGlyph,FGrayGlyph.TransparentColor);
        ImList.AddMasked(FDisabledGlyph,FDisabledGlyph.TransparentColor);
      end;
finally
      Bmp.Free;
end;
    Invalidate;
end;

procedure TTransparentButton.SetGlyph(Bmp: TBitmap);
begin
  FGlyph.Assign(Bmp);
  Invalidate;
end;

procedure TTransparentButton.SetNumGlyphs(Value: TNumGlyphs);
begin
   if FNumGlyphs <> Value then
   begin
    FNumGlyphs:= Value;
    Invalidate;
   end;
end;

procedure TTransparentButton.SetFrameStyle(Value: TFrameStyle);
begin
   if FOutline <> Value then
   begin
     FOutline:= Value;
     Invalidate;
   end;
end;

procedure TTransparentButton.SetTransparent(Value:boolean);
begin
  if FTransparent <> Value then
  begin
    FTransparent := Value;
    Invalidate;
  end;
end;

procedure TTransparentButton.SetCaption(Value: TCaption);
begin
  if FCaption <> Value then
  begin
    FCaption := Value;
    Invalidate;
  end;
end;


procedure TTransparentButton.SetBorderWidth(Value:Cardinal);
begin
  if FBorderSize <> Value then
  begin
    FBorderSize := Value;
    Invalidate;
  end;
end;

procedure TTransparentButton.SetStayDown(Value:boolean);
begin
  if FStayDown <> Value then
  begin
    FStayDown := Value;
    if FStayDown then
    begin
     FMouseDown := True;
     FState := bsDown;
{     Click; }{ uncomment and see what happens... }
    end
    else
    begin
     FMouseDown := False;
     FState := bsUp;
    end;
    Repaint;
  end;
end;

procedure TTransparentButton.SetWordWrap(Value:boolean);
begin
  if FWordWrap <> Value then
  begin
    FWordwrap := Value;
    Invalidate;
  end;
end;

procedure TTransparentButton.SetSpacing(Value:integer);
begin
  if FSpacing <> Value then
  begin
    FSpacing := Value;
    Invalidate;
  end;
end;

procedure TTransparentButton.SetTextAlign(Value:TTextAlign);
begin
  if FTextAlign <> Value then
  begin
    FTextAlign := Value;
    Invalidate;
  end;
end;

function TTransparentButton.InsideBtn(X,Y: Integer): boolean;
begin
  Result := PtInRect(Rect(0,0,Width,Height),Point(X,Y));
end;

{ paint everything but bitmap and text }
procedure TTransparentButton.Paint;
var TmpRect:TRect;
begin
   TmpRect := Rect(0,0,Width,Height);
   { draw the outline }
   with Canvas do
   begin
     Brush.Color:= clBtnFace;
     Pen.Color := clBlack;
     Pen.Width := BorderWidth;

     case FrameStyle of
     fsNone:
     begin
       if not Transparent then
         FillRect(Rect(0,0,width,height));
       if (csDesigning in ComponentState) then
         Frame3D(Canvas,TmpRect,clBlack,clBlack,1);
     end;

     fsExplorer:
     begin
       if not Transparent then
         FillRect(Rect(0,0,width,height));
       if (csDesigning in ComponentState) then
         Frame3D(Canvas,TmpRect,clBtnHighLight,clBtnShadow,1);
     end;

     fsRegular:
     begin
       { draw outline }
       Pen.Color := clBlack;
       if not Transparent then
         Rectangle(1,1,Width,Height)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -