Графическая кнопка
Исходный код компонента:
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.
Комментарии