Внешний вид сайта:

Графическая кнопка

Графическая кнопка с закругленными краями с состояниями Up/Down.

Исходный код компонента:

unit Bibutton;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, 
  Graphics, Controls, Forms, ExtCtrls;

type
  TBiButton = class(TCustomControl)
  private
    FTPicture : TPicture;
    FPPicture : TPicture;
    FOnPaint  : TNotifyEvent;
    FRegion   : THandle;
    FBRegion  : THandle;
    FBorder   : Boolean;
    FOffset   : Integer;
    FCaption  : String;

    FXRad,
    FYRad     : Integer;

    Down,
    Pressed   : Boolean;

    procedure SetTPicture (Value : TPicture);
    procedure SetPPicture (Value : TPicture);
    procedure SetXRadius (Value : Integer);
    procedure SetYRadius (Value : Integer);
    procedure SetBorder (Value : Boolean);
    procedure PictureChanged(Sender : TObject);
    procedure WM_LButtonDown (var Msg : TWMLButtonDown);
        message wm_LButtonDown;
    procedure WM_LButtonUp (var Msg : TWMLButtonUp);
        message wm_LButtonUp;
    procedure WM_MouseMove (var Msg : TWMMouseMove);
        message wm_MouseMove;
    procedure WM_Size (var Msg : TWMSize);
        message wm_Size;
    procedure SetRegion;
    procedure SetOffest(const Value: Integer);
    procedure SetCaption(const Value: String);

  public
    constructor Create (AOwner : TComponent); override;
    destructor Destroy; override;
    property Canvas;

  protected
    function GetPalette : HPalette; override;
    procedure Paint; override;

  published
    // "не нажатое изображение"
    property TopPicture : TPicture read FTPicture write SetTPicture;
    // "нажатое изображение" - если нет, будет использоваться TopPicture
    property PressedPicture : TPicture read FPPicture write SetPPicture;
    // для круглых кнопок
    property XRadius : Integer read FXRad write SetXRadius;
    property YRadius : Integer read FYRad write SetYRadius;
    // показывать грагицу кнопки или нет
    property Border : Boolean read FBorder write SetBorder;
    // смещение "нажатого изображения"
    property Offset : Integer read FOffset write SetOffest;
    property Caption : String read FCaption write SetCaption;

    property Color;
    property Font;
    property Align;
    property Visible;
    property ShowHint;
    property Enabled;
    property ParentColor;
    property ParentFont;
    property ParentShowHint;
    property TabOrder;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEnter;
    property OnExit;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('GBit', [TBiButton]);
end;

constructor TBiButton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FRegion := 0;
  FBRegion := 0;
  ControlStyle := [csCaptureMouse, csClickEvents];
  FTPicture := TPicture.Create;
  FTPicture.OnChange := PictureChanged;
  FPPicture := TPicture.Create;
  FPPicture.OnChange := PictureChanged;
  FBorder := True;
  Height := 100;
  Width := 100;
  XRadius := Width;
  YRadius := Height;
  Offset := 2;
  Pressed := False;
end;

destructor TBiButton.Destroy;
begin
  FTPicture.Free;
  FPPicture.Free;
  DeleteObject (FRegion);
  DeleteObject (FBRegion);
  inherited Destroy;
end;

function TBiButton.GetPalette: HPalette;
begin
  Result := 0;
  if FTPicture.Graphic is TBitmap then
    Result := TBitmap(FTPicture.Graphic).Palette;
end;

procedure TBiButton.SetTPicture(Value: TPicture);
begin
  FTPicture.Assign(Value);
end;

procedure TBiButton.SetPPicture(Value: TPicture);
begin
  FPPicture.Assign(Value);
end;

procedure TBiButton.Paint;
var
  Rect  : TRect;
  Ha    : HDC;
  ps    : TPaintStruct;
  x, y  : Integer;
  R, rx,
  G, gx,
  B, bx : Word;
  AColor,
  LightC,
  DarkC : TColor;
begin
  Rect := GetClientRect;
  InvalidateRgn (Handle, FRegion, False);
  try
    SetWindowRgn (Self.Handle, FBRegion, True);
  except
  end;

  if Color < 0 then begin
    AColor := GetSysColor (Color and $00FFFFFF);
  end else
    AColor := Color;

  R := GetRValue (AColor);
  G := GetGValue (AColor);
  B := GetBValue (AColor);

  rx := Round ((255-R) * 0.5);
  gx := Round ((255-G) * 0.5);
  bx := Round ((255-B) * 0.5);
  LightC := RGB (R+rx, G+gx, B+bx);

  rx := Round (R * 0.3);
  gx := Round (G * 0.3);
  bx := Round (B * 0.3);
  darkC := RGB (R-rx, G-gx, B-bx);

  Ha := BeginPaint (Handle, ps);
  Canvas.Handle := Ha;
  if not Down then begin
    with Canvas do begin
      if FTPicture.Graphic is TBitmap then begin
        Brush.Color := AColor;
        FillRect(Rect);
        Draw (0, 0, FTPicture.Graphic);
      end else begin
        Brush.Color := AColor;
        FillRect(Rect);
      end;
      if Border then begin
        Brush.Style := bsClear;
        Pen.Width := 2;
        Pen.Color := LightC;
        RoundRect (2, 2, Width, Height, XRadius, YRadius);
        Pen.Width := 2;
        Pen.Color := DarkC;
        RoundRect (0, 0, Width, Height, XRadius, YRadius);
      end;
      Font := Self.Font;
      x := (Width - TextWidth (Caption)) div 2;
      y := (Height - TextHeight (Caption)) div 2;
      TextOut (x, y, Caption);
    end;
  end else begin
    with Canvas do begin
      if FPPicture.Graphic is TBitmap then begin
        Brush.Color := AColor;
        FillRect(Rect);
        Draw (Offset, Offset, FPPicture.Graphic);
      end else begin
        Brush.Color := AColor;
        FillRect(Rect);
      end;
      if Border then begin
        Brush.Style := bsClear;
        Pen.Width := 2;
        Pen.Color := LightC;
        RoundRect (0, 0, Width-2, Height-2, XRadius, YRadius);
        Pen.Width := 4;
        Pen.Color := DarkC;
        RoundRect (0, 0, Width, Height, XRadius, YRadius);
      end;
      Font := Self.Font;
      x := (Width - TextWidth (Caption)) div 2;
      y := (Height - TextHeight (Caption)) div 2;
      TextOut (x+1, y+1, Caption);
    end;
  end;
  EndPaint (Ha, ps);
end;

procedure TBiButton.PictureChanged(Sender: TObject);
begin
  if (FTPicture.Graphic is TBitmap) and (FTPicture.Width = Width) and
    (FTPicture.Height = Height) then
    ControlStyle := ControlStyle + [csOpaque] else
    ControlStyle := ControlStyle - [csOpaque];
  if (FPPicture.Graphic is TBitmap) and (FPPicture.Width = Width) and
    (FPPicture.Height = Height) then
    ControlStyle := ControlStyle + [csOpaque] else
    ControlStyle := ControlStyle - [csOpaque];
  Invalidate;
end;

procedure TBiButton.WM_LButtonDown (var Msg : TWMLButtonDown);
begin
  Pressed := PtInRegion (FRegion, Msg.xPos, Msg.yPos);
  if Pressed then begin
    Down := Pressed;
    SetCapture (Handle);
    Invalidate;
  end;
  inherited;
end;

procedure TBiButton.WM_LButtonUp (var Msg : TWMLButtonUp);
begin
  if not Pressed then
    exit;
  Pressed := False;
  Down := Pressed;
  ReleaseCapture;
  Invalidate;
  inherited;
end;

procedure TBiButton.WM_MouseMove (var Msg : TWMMouseMove);
var
   D : Boolean;
begin
  D := PtInRegion (FRegion, Msg.xPos, Msg.yPos);
  if Pressed then begin
    if D <> Down then begin
      Down := D;
      Invalidate;
    end;
  end;
  inherited;
end;

procedure TBiButton.SetYRadius (Value : Integer);
begin
  if Value > Height then
    Value := Height;
  if Value <> YRadius then begin
    FYRad := Value;
    SetRegion;
    Invalidate;
  end;
end;

procedure TBiButton.SetXRadius (Value : Integer);
begin
  if Value > Width then
    Value := Width;
  if Value <> XRadius then begin
    FXRad := Value;
    SetRegion;
    Invalidate;
  end;
end;

procedure TBiButton.SetRegion;
begin
  DeleteObject (FRegion);
  DeleteObject (FBRegion);
  if XRadius > Width then
    FXRad := Width;
  if YRadius > Height then
    FYRad := Height;
  FRegion := CreateRoundRectRgn (0, 0, Width+1, Height+1, XRadius, YRadius);
  FBRegion := CreateRoundRectRgn (0, 0, Width+1, Height+1, XRadius, YRadius);
end;

procedure TBiButton.WM_Size (var Msg : TWMSize);
begin
  SetRegion;
  Invalidate;
end;

procedure TBiButton.SetBorder (Value : Boolean);
begin
  if Value <> FBorder then begin
    FBorder := Value;
    Invalidate;
  end;
end;

procedure TBiButton.SetOffest(const Value: Integer);
begin
  FOffset := Value;
  Invalidate;
end;

procedure TBiButton.SetCaption(const Value: String);
begin
  FCaption := Value;
  Invalidate;
end;

end.

Комментарии

Нет комментариев. Ваш будет первым!