diff --git a/components/exctrls/exctrlspkg.lpk b/components/exctrls/exctrlspkg.lpk index 58d5c9e3f..6e1c8b27f 100644 --- a/components/exctrls/exctrlspkg.lpk +++ b/components/exctrls/exctrlspkg.lpk @@ -17,7 +17,7 @@ - CurrencyEdit - TRadioButton, TCheckbox, TRadioGroup and TCheckGroup: drawn by ThemeServices/Canvas, not by widgetset, button/text layout, wordwrap, user-provided check images"/> - + @@ -31,6 +31,10 @@ + + + + diff --git a/components/exctrls/exctrlspkg.pas b/components/exctrls/exctrlspkg.pas index 403753cc9..ed4fb1d19 100644 --- a/components/exctrls/exctrlspkg.pas +++ b/components/exctrls/exctrlspkg.pas @@ -8,7 +8,7 @@ unit ExCtrlsPkg; interface uses - ExCheckCtrls, ExEditCtrls, ExCtrlsReg, LazarusPackageIntf; + ExCheckCtrls, ExEditCtrls, ExCtrlsReg, ExButtons, LazarusPackageIntf; implementation diff --git a/components/exctrls/images/imagelist.txt b/components/exctrls/images/imagelist.txt index 7d6b03466..afc1b7ba1 100644 --- a/components/exctrls/images/imagelist.txt +++ b/components/exctrls/images/imagelist.txt @@ -1,3 +1,6 @@ +tbuttonex.png +tbuttonex_150.png +tbuttonex_200.png tradiobuttonex.png tradiobuttonex_150.png tradiobuttonex_200.png diff --git a/components/exctrls/images/tbuttonex.png b/components/exctrls/images/tbuttonex.png new file mode 100644 index 000000000..493530ba7 Binary files /dev/null and b/components/exctrls/images/tbuttonex.png differ diff --git a/components/exctrls/images/tbuttonex_150.png b/components/exctrls/images/tbuttonex_150.png new file mode 100644 index 000000000..d3f9ac36c Binary files /dev/null and b/components/exctrls/images/tbuttonex_150.png differ diff --git a/components/exctrls/images/tbuttonex_200.png b/components/exctrls/images/tbuttonex_200.png new file mode 100644 index 000000000..e9adcc773 Binary files /dev/null and b/components/exctrls/images/tbuttonex_200.png differ diff --git a/components/exctrls/source/exbuttons.pas b/components/exctrls/source/exbuttons.pas new file mode 100644 index 000000000..29b85b8d9 --- /dev/null +++ b/components/exctrls/source/exbuttons.pas @@ -0,0 +1,1013 @@ +unit ExButtons; + +{$mode objfpc}{$H+} + +interface + +uses + Graphics, Classes, SysUtils, LMessages, Types, Controls, StdCtrls, Forms; + +type + TButtonExState = (bxsNormal, bxsHot, bxsDown, bxsFocused, bxsDisabled); + TButtonExBorderWidth = 1..10; + + TButtonEx = class; + + TButtonExBorder = class(TPersistent) + private + FButton: TButtonEx; + FColorNormal: TColor; + FColorHot: TColor; + FColorDown: TColor; + FColorDisabled: TColor; + FColorFocused: TColor; + FWidthNormal: TButtonExBorderWidth; + FWidthHot: TButtonExBorderWidth; + FWidthDown: TButtonExBorderWidth; + FWidthDisabled: TButtonExBorderWidth; + FWidthFocused: TButtonExBorderWidth; + procedure SetWidthNormal(const Value: TButtonExBorderWidth); + procedure SetColorNormal(const Value: TColor); + public + constructor Create(AButton: TButtonEx); + published + property ColorNormal: TColor read FColorNormal write SetColorNormal; + property ColorHot: TColor read FColorHot write FColorHot; + property ColorDown: TColor read FColorDown write FColorDown; + property ColorDisabled: TColor read FColorDisabled write FColorDisabled; + property ColorFocused: TColor read FColorFocused write FColorFocused; + property WidthNormal: TButtonExBorderWidth read FWidthNormal write SetWidthNormal; + property WidthHot: TButtonExBorderWidth read FWidthHot write FWidthHot; + property WidthDown: TButtonExBorderWidth read FWidthDown write FWidthDown; + property WidthDisabled: TButtonExBorderWidth read FWidthDisabled write FWidthDisabled; + property WidthFocused: TButtonExBorderWidth read FWidthFocused write FWidthFocused; + end; + + TButtonExColors = class(TPersistent) + private + FButton: TButtonEx; + FColorNormalFrom: TColor; + FColorNormalTo: TColor; + FColorHotFrom: TColor; + FColorHotTo: TColor; + FColorDownFrom: TColor; + FColorDownTo: TColor; + FColorDisabledFrom: TColor; + FColorDisabledTo: TColor; + FColorFocusedFrom: TColor; + FColorFocusedTo: TColor; + procedure SetColorNormalFrom(const Value: TColor); + procedure SetColorNormalTo(const Value: TColor); + public + constructor Create(AButton: TButtonEx); + published + property ColorNormalFrom: TColor read FColorNormalFrom write SetColorNormalFrom; + property ColorNormalTo: TColor read FColorNormalTo write SetColorNormalTo; + property ColorHotFrom: TColor read FColorHotFrom write FColorHotFrom; + property ColorHotTo: TColor read FColorHotTo write FColorHotTo; + property ColorDownFrom: TColor read FColorDownFrom write FColorDownFrom; + property ColorDownTo: TColor read FColorDownTo write FColorDownTo; + property ColorDisabledFrom: TColor read FColorDisabledFrom write FColorDisabledFrom; + property ColorDisabledTo: TColor read FColorDisabledTo write FColorDisabledTo; + property ColorFocusedFrom: TColor read FColorFocusedFrom write FColorFocusedFrom; + property ColorFocusedTo: TColor read FColorFocusedTo write FColorFocusedTo; + end; +{ + TButtonExPictures = class(TPersistent) + private + FButton: TButtonEx; + FAlignment: TLeftRight; + FTransparent: boolean; + FPictureNormal: TPicture; + FPictureHot: TPicture; + FPictureDown: TPicture; + FPictureDisabled: TPicture; + FPictureFocused: TPicture; + procedure SetPictureNormal(const Value: TPicture); + procedure SetPictureDisabled(const Value: TPicture); + procedure SetPictureDown(const Value: TPicture); + procedure SetPictureFocused(const Value: TPicture); + procedure SetPictureHot(const Value: TPicture); + procedure SetAlignment(const Value: TLeftRight); + procedure SetTransparent(const Value: boolean); + public + constructor Create(AButton: TButtonEx); + destructor Destroy; override; + published + property PictureNormal: TPicture read FPictureNormal write SetPictureNormal; + property PictureHot: TPicture read FPictureHot write SetPictureHot; + property PictureDown: TPicture read FPictureDown write SetPictureDown; + property PictureDisabled: TPicture read FPictureDisabled write SetPictureDisabled; + property PictureFocused: TPicture read FPictureFocused write SetPictureFocused; + property Alignment: TLeftRight read FAlignment write SetAlignment default taLeftJustify; + property Transparent: boolean read FTransparent write SetTransparent default False; + end; +} + TButtonEx = class(TCustomButton) + private + FAlignment: TAlignment; + FBorder: TButtonExBorder; + FCanvas: TCanvas; + FColors: TButtonExColors; + FDefaultDrawing: Boolean; + FFontDisabled: TFont; + FFontDown: TFont; + FFontFocused: TFont; + FFontHot: TFont; + FGradient: Boolean; + FMargin: integer; + FShowFocusRect: Boolean; + FState: TButtonExState; + FWordwrap: Boolean; + procedure SetAlignment(const Value: TAlignment); + procedure SetDefaultDrawing(const Value: Boolean); + procedure SetGradient(const Value: Boolean); + procedure SetShowFocusRect(const Value: Boolean); +// procedure SetSpacing(const Value: integer); + procedure SetMargin(const Value: integer); + procedure SetWordWrap(const Value: Boolean); + protected + procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: Integer; + WithThemeSpace: Boolean); override; + class function GetControlClassDefaultSize: TSize; override; + function GetDrawTextFlags: Cardinal; + procedure MouseEnter; override; + procedure MouseLeave; override; + procedure PaintCustomButton; + procedure PaintThemedButton; + procedure WMKillFocus(var Message: TLMKillFocus); message LM_KILLFOCUS; + procedure WMPaint(var Msg: TLMPaint); message LM_PAINT; + procedure WMSetFocus(var Message: TLMSetFocus); message LM_SETFOCUS; + procedure WndProc(var Message: TLMessage); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + //procedure Click; override; + published + property Align; + property Anchors; + property AutoSize; + property BorderSpacing; + property Cancel; + property Caption; + //property Color; removed for new property Colors + property Constraints; + property Cursor; + property Default; +// property DoubleBuffered; // PaintButton is not called when this is set. + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property Font; + property Height; + property HelpContext; + property HelpKeyword; + property HelpType; + property Hint; + property Left; + property ModalResult; + property ParentBiDiMode; +// property ParentDoubleBuffered; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property TabOrder; + property TabStop default True; + property Tag; + property Top; + property Visible; + property Width; + + property OnChangeBounds; + property OnClick; + property OnContextPopup; + property OnDragDrop; + property OnDragOver; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnResize; + property OnStartDrag; + property OnUTF8KeyPress; + + property Alignment: TAlignment read FAlignment write SetAlignment default taCenter; + property Border: TButtonExBorder read FBorder write FBorder; + property Colors: TButtonExColors read FColors write FColors; + property DefaultDrawing: Boolean read FDefaultDrawing write SetDefaultDrawing default true; + property FontDisabled: TFont read FFontDisabled write FFontDisabled; + property FontDown: TFont read FFontDown write FFontDown; + property FontFocused: TFont read FFontFocused write FFontFocused; + property FontHot: TFont read FFontHot write FFontHot; + property Gradient: Boolean read FGradient write SetGradient default true; + property Margin: integer read FMargin write SetMargin; + property ShowFocusRect: Boolean read FShowFocusRect write SetShowFocusRect default true; + property Wordwrap: Boolean read FWordWrap write SetWordWrap default false; + end; + + +implementation + +uses + LCLType, LCLIntf, Themes; + + +{ TButtonExBorder } + +constructor TButtonExBorder.Create(AButton: TButtonEx); +begin + inherited Create; + FButton := AButton; +end; + +procedure TButtonExBorder.SetColorNormal(const Value: TColor); +begin + if FColorNormal = Value then exit; + FColorNormal := Value; + FButton.Invalidate; +end; + +procedure TButtonExBorder.SetWidthNormal(const Value: TButtonExBorderWidth); +begin + if FWidthNormal = Value then exit; + FWidthNormal := Value; + FButton.Invalidate; +end; + + +{ TButtonExColors } + +constructor TButtonExColors.Create(AButton: TButtonEx); +begin + inherited Create; + FButton := AButton; +end; + +procedure TButtonExColors.SetColorNormalFrom(const Value: TColor); +begin + if FColorNormalFrom = Value then + exit; + FColorNormalFrom := Value; + FButton.Invalidate; +end; + +procedure TButtonExColors.SetColorNormalTo(const Value: TColor); +begin + if FColorNormalTo = Value then + exit; + FColorNormalTo := Value; + FButton.Invalidate; +end; + + +(* +{ TButtonExPictures } + +constructor TButtonExPictures.Create(AButton: TButtonEx); +begin + inherited Create; + FButton := AButton; + FAlignment := taLeftJustify; + FTransparent := False; + FPictureNormal := TPicture.Create; + FPictureHot := TPicture.Create; + FPictureDown := TPicture.Create; + FPictureDisabled := TPicture.Create; + FPictureFocused := TPicture.Create; +end; + +destructor TButtonExPictures.Destroy; +begin + FPictureNormal.Free; + FPictureHot.Free; + FPictureDown.Free; + FPictureDisabled.Free; + FPictureFocused.Free; + inherited; +end; + +procedure TButtonExPictures.SetAlignment(const Value: TLeftRight); +begin + if FAlignment = Value then + exit; + FAlignment := Value; + FButton.Invalidate; +end; + +procedure TButtonExPictures.SetPictureDisabled(const Value: TPicture); +begin + FPictureDisabled.Assign(Value); +end; + +procedure TButtonExPictures.SetPictureDown(const Value: TPicture); +begin + FPictureDown.Assign(Value); +end; + +procedure TButtonExPictures.SetPictureFocused(const Value: TPicture); +begin + FPictureFocused.Assign(Value); +end; + +procedure TButtonExPictures.SetPictureHot(const Value: TPicture); +begin + FPictureHot.Assign(Value); +end; + +procedure TButtonExPictures.SetPictureNormal(const Value: TPicture); +begin + FPictureNormal.Assign(Value); + FButton.Invalidate; +end; + +procedure TButtonExPictures.SetTransparent(const Value: boolean); +begin + FTransparent := Value; + FButton.Invalidate; +end; +*) + + +{ TButtonEx } + +constructor TButtonEx.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + + FCanvas := TControlCanvas.Create; + TControlCanvas(FCanvas).Control := Self; + + FDefaultDrawing := true; + FGradient := true; + FShowFocusRect := true; + + FBorder := TButtonExBorder.Create(Self); + FColors := TButtonExColors.Create(Self); + //FPictures := TButtonExPictures.Create(Self); + + // Button + FColors.ColorNormalFrom := $00FCFCFC; + FColors.ColorNormalTo := $00CFCFCF; + FColors.ColorHotFrom := $00FCFCFC; + FColors.ColorHotTo := $00F5D9A7; + FColors.ColorDownFrom := $00FCFCFC; + FColors.ColorDownTo := $00DBB368; + FColors.ColorDisabledFrom := $00F4F4F4; + FColors.ColorDisabledTo := $00F4F4F4; + FColors.ColorFocusedFrom := $00FCFCFC; + FColors.ColorFocusedTo := $00CFCFCF; + + // Fonts + FFontDisabled := TFont.Create; + FFontDisabled.Assign(Font); + FFontDisabled.Color := clGrayText; + FFontDisabled.OnChange := @FontChanged; + FFontDown := TFont.Create; + FFontDown.Assign(Font); + FFontDown.OnChange := @FontChanged; + FFontFocused := TFont.Create; + FFontFocused.Assign(Font); + FFontFocused.OnChange := @FontChanged; + FFontHot := TFont.Create; + FFontHot.Assign(Font); + FFontHot.OnChange := @FontChanged; + + // Border + FBorder.ColorNormal := $00707070; + FBorder.ColorHot := $00B17F3C; + FBorder.ColorDown := $008B622C; + FBorder.ColorDisabled := $00B5B2AD; + FBorder.ColorFocused := $00B17F3C; + FBorder.WidthNormal := 1; + FBorder.WidthHot := 1; + FBorder.WidthDown := 1; + FBorder.WidthDisabled := 1; + FBorder.WidthFocused := 1; + + // Other +// FSpacing := 5; + FMargin := 5; + FAlignment := taCenter; + FState := bxsNormal; +// TabStop := True; +// FModalResult := 0; +// FCancel := False; +// FDefault := False; +// Width := 85; +// Height := 30; +end; + +destructor TButtonEx.Destroy; +begin + FFontHot.Free; + FFontDown.Free; + FFontDisabled.Free; + FFontFocused.Free; + //FPictures.Free; + FColors.Free; + FBorder.Free; + FCanvas.Free; + inherited; +end; + +procedure TButtonEx.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: Integer; WithThemeSpace: Boolean); +var + flags: Cardinal; + txtSize: TSize; + R: TRect; + details: TThemedElementDetails; +begin + FCanvas.Font.Assign(Font); + + R := ClientRect; + InflateRect(R, -FMargin, 0); + R.Bottom := MaxInt; // Max height possible + + flags := GetDrawTextFlags + DT_CALCRECT; + + // rectangle available for text + details := ThemeServices.GetElementDetails(tbPushButtonNormal); + if FWordWrap then + begin + with ThemeServices.GetTextExtent(FCanvas.Handle, details, Caption, flags, @R) do begin + txtSize.CX := Right; + txtSize.CY := Bottom; + end; + end else + with ThemeServices.GetTextExtent(FCanvas.Handle, details, Caption, flags, nil) do begin + txtSize.CX := Right; + txtSize.CY := Bottom; + end; + + PreferredHeight := txtSize.CY + 2 * FMargin; + PreferredWidth := txtSize.CX + 2 * FMargin; + + if not FWordWrap then + PreferredHeight := 0; + { + if FWordWrap then //and AutoSize then + begin + PreferredWidth := 0 ; + PreferredHeight := txtSize.CY + 2*FMargin; + end else + begin + PreferredWidth := txtSize.CX + 2 * FMargin; + PreferredHeight := 0; + end; + } +end; + + (* +procedure TButtonEx.Click; +var + Form: TCustomForm; +begin + Form := GetParentForm(Self); + if Form <> nil then + Form.ModalResult := FModalResult; + inherited; +end; + +procedure TButtonEx.FontChanged(Sender: TObject); +begin + Invalidate; +end; + *) + +class function TButtonEx.GetControlClassDefaultSize: TSize; +begin + Result.CX := 75; + Result.CY := 25; +end; + +function TButtonEx.GetDrawTextFlags: Cardinal; +begin + Result := DT_VCENTER; + case FAlignment of + taLeftJustify: + if IsRightToLeft then Result := Result or DT_RIGHT else Result := Result or DT_LEFT; + taRightJustify: + if IsRightToLeft then Result := Result or DT_LEFT else Result := Result or DT_RIGHT; + taCenter: + Result := Result or DT_CENTER; + end; + if IsRightToLeft then + result := Result or DT_RTLREADING; + if FWordWrap then + Result := Result or DT_WORDBREAK and not DT_SINGLELINE + else + Result := Result or DT_SINGLELINE and not DT_WORDBREAK;; +end; + +procedure TButtonEx.MouseEnter; +begin + if FState <> bxsDisabled then + begin + FState := bxsHot; + Invalidate; + end; + inherited; +end; + +procedure TButtonEx.MouseLeave; +begin + if (FState <> bxsDisabled) then + begin + if Focused then + FState := bxsFocused + else + FState := bxsNormal; + Invalidate; + end; + inherited; +end; + +procedure TButtonEx.PaintThemedButton; +var + btn: TThemedButton; + details: TThemedElementDetails; + lRect: TRect; + flags: Cardinal; + txtSize: TSize; + txtPt: TPoint; +begin + if (csDestroying in ComponentState) or not HandleAllocated then + exit; + + lRect.Left := 0; + lRect.Right := Width; + lRect.Top := 0; + lRect.Bottom := Height; + + if FState = bxsDisabled then + btn := tbPushButtonDisabled + else if FState = bxsDown then + btn := tbPushButtonPressed + else if FState = bxsHot then + btn := tbPushButtonHot + else + if Focused or Default then + btn := tbPushButtonDefaulted + else + btn := tbPushButtonNormal; + + // Background + details := ThemeServices.GetElementDetails(btn); + InflateRect(lRect, 1, 1); + ThemeServices.DrawElement(FCanvas.Handle, details, lRect); + InflateRect(lRect, -1, -1); + + // Text + FCanvas.Font.Assign(Font); + flags := GetDrawTextFlags; + + with ThemeServices.GetTextExtent(FCanvas.Handle, details, Caption, flags, @lRect) do begin + txtSize.CX := Right; + txtSize.CY := Bottom; + end; + + case FAlignment of + taLeftJustify: + if IsRightToLeft then + txtPt.X := Width - txtSize.CX - FMargin + else + txtPt.X := FMargin; + taRightJustify: + if IsRightToLeft then + txtPt.X := FMargin + else + txtPt.X := Width - txtSize.CX - FMargin; + taCenter: + txtPt.X := (Width - txtSize.CX) div 2; + end; + txtPt.Y := (Height + 1 - txtSize.CY) div 2; + lRect := Rect(txtPt.X, txtPt.Y, txtPt.X + txtSize.CX, txtPt.Y + txtSize.CY); + ThemeServices.DrawText(FCanvas, details, Caption, lRect, flags, 0); +end; + +procedure TButtonEx.PaintCustomButton; +var + lCanvas: TCanvas; + lBitmap: TBitmap; + lRect, R: TRect; + lBorderColor: TColor; + lBorderWidth: integer; + lColorFrom: TColor; + lColorTo: TColor; + lTextFont: TFont; + flags: Cardinal; + i: integer; + txtSize: TSize; + txtPt: TPoint; +begin + if (csDestroying in ComponentState) or not HandleAllocated then + exit; + + // Bitmap + lBitmap := TBitmap.Create; + lBitmap.Width := Width; + lBitmap.Height := Height; + lCanvas := lBitmap.Canvas; + + // State + lBorderColor := Border.ColorNormal; + lColorFrom := Colors.ColorNormalFrom; + lColorTo := Colors.ColorNormalTo; + lTextFont := Font; + lBorderWidth := Border.WidthNormal; + //lPicture := FPictures.PictureNormal; + + if not (csDesigning in ComponentState) then + begin + case FState of + bxsFocused: + begin + lBorderColor := FBorder.ColorFocused; + lColorFrom := FColors.ColorFocusedFrom; + lColorTo := FColors.ColorFocusedTo; + lTextFont := FFontFocused; + lBorderWidth := FBorder.WidthFocused; + { + if FPictures.PictureFocused.Graphic <> nil then + lPicture := FPictures.PictureFocused; + } + end; + bxsHot: + begin + lBorderColor := FBorder.ColorHot; + lColorFrom := FColors.ColorHotFrom; + lColorTo := FColors.ColorHotTo; + lTextFont := FFontHot; + lBorderWidth := FBorder.WidthHot; + { + if FPictures.PictureHot.Graphic <> nil then + lPicture := FPictures.PictureHot; + } + end; + bxsDown: + begin + lBorderColor := FBorder.ColorDown; + lColorFrom := FColors.ColorDownFrom; + lColorTo := FColors.ColorDownTo; + lTextFont := FFontDown; + lBorderWidth := FBorder.WidthDown; + { + if FPictures.PictureDown.Graphic <> nil then + lPicture := FPictures.PictureDown; + } + end; + bxsDisabled: + begin + lBorderColor := FBorder.ColorDisabled; + lColorFrom := FColors.ColorDisabledFrom; + lColorTo := FColors.ColorDisabledTo; + lTextFont := FFontDisabled; + lBorderWidth := FBorder.WidthDisabled; + { + if FPictures.PictureDisabled.Graphic <> nil then + lPicture := FPictures.PictureDisabled; + } + end; + end; + end; + + // Background + lRect.Left := 0; + lRect.Right := Width; + lRect.Top := 0; //lBorderWidth; + lRect.Bottom := Height; // - lBorderWidth; + + if FGradient then + lCanvas.GradientFill(lRect, lColorFrom, lColorTo, gdVertical) + else + begin + lCanvas.Brush.Style := bsSolid; + lCanvas.Brush.Color := lColorFrom; + lCanvas.FillRect(lRect); + end; + + { + // Image + lPicLeft := 0; + if lPicture.Graphic <> nil then + begin + lPicture.Graphic.Transparent := FPictures.Transparent; + case FPictures.Alignment of + taLeftJustify : lPicLeft := Border.WidthNormal + FMargin; + taRightJustify: lPicLeft := Width - Border.WidthNormal - FMargin - lPicture.Graphic.Width; + end; + lPicTop := (Height - lPicture.Height) div 2; + lCanvas.Draw(lPicLeft, lPicTop, lPicture.Graphic); + end; + } + // Border + lCanvas.Pen.Width := 1; + lCanvas.Pen.Color := lBorderColor; + for i := 1 to lBorderWidth do + begin + lCanvas.MoveTo(i - 1, i - 1); + lCanvas.LineTo(Width - i, i - 1); + lCanvas.LineTo(Width - i, Height - i); + lCanvas.LineTo(i - 1, Height - i); + lCanvas.LineTo(i - 1, i - 1); + end; + + (* + // Corner + lCanvas.Pixels[0, 0] := Color; + lCanvas.Pixels[lBorderWidth, lBorderWidth] := lBorderColor; + lCanvas.Pixels[Width - 1, 0] := Color; + lCanvas.Pixels[Width - 1 - lBorderWidth, lBorderWidth] := lBorderColor; + lCanvas.Pixels[0, Height - 1] := Color; + lCanvas.Pixels[lBorderWidth, Height - 1 - lBorderWidth] := lBorderColor; + lCanvas.Pixels[Width - 1, Height - 1] := Color; + lCanvas.Pixels[Width - 1 - lBorderWidth, Height - 1 - lBorderWidth] := lBorderColor; + *) + + // Text + lCanvas.Pen.Width := 1; + lCanvas.Brush.Style := bsClear; + lCanvas.Font.Assign(lTextFont); + + flags := GetDrawTextFlags; + R := lRect; + DrawText(FCanvas.Handle, PChar(Caption), Length(Caption), R, flags + DT_CALCRECT); + txtSize.CX := R.Right - R.Left; + txtSize.CY := R.Bottom - R.Top; + + case FAlignment of + taLeftJustify: + if IsRightToLeft then + txtPt.X := Width - txtSize.CX - FMargin + else + txtPt.X := FMargin; + taRightJustify: + if IsRightToLeft then + txtPt.X := FMargin + else + txtPt.X := Width - txtSize.CX - FMargin; + taCenter: + txtPt.X := (Width - txtSize.CX) div 2; + end; + txtPt.Y := (Height - txtSize.CY + 1) div 2; + R := Rect(txtPt.X, txtPt.Y, txtPt.X + txtSize.CX, txtPt.Y + txtSize.CY); + (* + case FAlignment of + taLeftJustify: + begin + lRect.Left := lRect.Left + FBorder.WidthNormal + FMargin; + lAlignment := DT_LEFT; + end; + taRightJustify: + begin + lRect.Right := lRect.Right - FBorder.WidthNormal - FMargin; + lAlignment := DT_RIGHT; + end; + else + lAlignment := DT_CENTER; + end; + *) + { + if (lPicture.Graphic <> nil) and (Alignment <> taCenter) then + begin + case FPictures.Alignment of + taLeftJustify: lRect.Left := lPicLeft + lPicture.Graphic.Width + FSpacing; + taRightJustify: lRect.Right := lPicLeft - FSpacing; + end; + end; + } + DrawText(lCanvas.Handle, PChar(Caption), -1, R, flags); //lAlignment or DT_NOPREFIX or DT_VCENTER or DT_SINGLELINE); + + // Draw focus rectangle + if FShowFocusRect and Focused then + begin + InflateRect(lRect, -3, -2); + DrawFocusRect(lCanvas.Handle, lRect); + end; + + // Draw the button + FCanvas.Draw(0, 0, lBitmap); + + lBitmap.Free; +end; + +procedure TButtonEx.SetAlignment(const Value: TAlignment); +begin + if FAlignment = Value then + exit; + FAlignment := Value; + Invalidate; +end; + +procedure TButtonEx.SetDefaultDrawing(const Value: Boolean); +begin + if FDefaultDrawing = Value then + exit; + FDefaultDrawing := Value; + Invalidate; +end; + +procedure TButtonEx.SetGradient(const Value: Boolean); +begin + if FGradient = Value then + exit; + FGradient := Value; + Invalidate; +end; + +procedure TButtonEx.SetShowFocusRect(const Value: Boolean); +begin + if FShowFocusRect = Value then + exit; + FShowFocusRect := Value; + if Focused then Invalidate; +end; + +procedure TButtonEx.SetMargin(const Value: integer); +begin + if FMargin = Value then + exit; + FMargin := Value; + Invalidate; +end; + +{ +procedure TButtonEx.SetSpacing(const Value: integer); +begin + if FSpacing = Value then + exit; + FSpacing := Value; + Invalidate; +end; +} + +procedure TButtonEx.SetWordWrap(const Value: Boolean); +begin + if FWordWrap = Value then + exit; + FWordWrap := Value; + //if AutoSize then AdjustSize; + Invalidate; +end; + +procedure TButtonEx.WMKillFocus(var Message: TLMKillFocus); +begin + inherited WMKillFocus(Message); + if (FState = bxsFocused) then + begin + FState := bxsNormal; + Invalidate; + end; +end; + +procedure TButtonEx.WMSetFocus(var Message: TLMSetFocus); +begin + inherited WMSetFocus(Message); + if (FState = bxsNormal) then + begin + FState := bxsFocused; + Invalidate; + end; +end; + +procedure TButtonEx.WMPaint(var Msg: TLMPaint); +begin + inherited; + if FDefaultDrawing then + PaintThemedButton + else + PaintCustomButton; +end; + +procedure TButtonEx.WndProc(var Message: TLMessage); +begin + { + if Message.Msg = LM_PAINT then + PaintButton; + + if Message.Msg = CM_TEXTCHANGED then + PaintButton; + + if Message.Msg = CM_COLORCHANGED then + PaintButton; + + if Message.Msg = CM_BORDERCHANGED then + PaintButton; + + if Message.Msg = LM_ERASEBKGND then + Exit; +} + if not (csDesigning in ComponentState) then + begin + case Message.Msg of + + LM_KEYDOWN: + begin + if (Message.WParam = VK_RETURN) or (Message.WParam = VK_SPACE) then + if FState <> bxsDisabled then + FState := bxsDown; + Invalidate; + end; + + LM_KEYUP: + begin + if (Message.WParam = VK_RETURN) or (Message.WParam = VK_SPACE) then + if FState <> bxsDisabled then + FState := bxsFocused; + Invalidate; + end; + + { + LM_CHAR: + begin + if (Message.WParam = VK_RETURN) or (Message.WParam = VK_SPACE) and (FState <> bxsDisabled) then + begin + Click; + end; + end; + + CM_MOUSEENTER: + begin + FState := bxsHot; + PaintButton; + end; + CM_MOUSELEAVE: + begin + if (FState <> bxsDisabled) then + begin + if Focused then + FState := bxsFocused + else + FState := bxsNormal; + PaintButton; + end; + end; + } + CM_DIALOGKEY: + begin + if (Message.WParam = VK_RETURN) and Default and (not Focused) and (FState <> bxsDisabled) then + Click; + if (Message.WParam = VK_ESCAPE) and Cancel and (FState <> bxsDisabled) then + Click; + end; + + { + CM_FOCUSCHANGED: + begin + if Focused and (FState = bxsNormal) then + FState := bxsFocused; + if (not Focused) and (FState = bxsFocused) then + FState := bxsNormal; + PaintButton; + end; + } + CM_ENABLEDCHANGED: + begin + if not Enabled then + FState := bxsDisabled + else + FState := bxsNormal; + Invalidate; +// PaintButton; + end; + LM_LBUTTONDOWN: + begin + FState := bxsDown; + Invalidate; +// PaintButton; + end; + LM_LBUTTONUP: + begin + if (FState <> bxsNormal) and (FState <> bxsFocused) and (FState <> bxsDisabled) then + begin + FState := bxsHot; + Invalidate; + //PaintButton; + end; + end; + { + LM_LBUTTONDBLCLK: + begin + FState := bxsDown; + PaintButton; + Click; + end; + } + end; + end; + + inherited; +end; + +end. + diff --git a/components/exctrls/source/exctrlsreg.pas b/components/exctrls/source/exctrlsreg.pas index 61d5033d6..521990af1 100644 --- a/components/exctrls/source/exctrlsreg.pas +++ b/components/exctrls/source/exctrlsreg.pas @@ -12,14 +12,14 @@ procedure Register; implementation uses - ExCheckCtrls, ExEditCtrls; + ExButtons, ExCheckCtrls, ExEditCtrls; {$R exctrlsreg.res} procedure Register; begin RegisterComponents('ExCtrls', [ - TCheckboxEx, TRadioButtonEx, TCheckGroupEx, TRadioGroupEx + TButtonEx, TCheckboxEx, TRadioButtonEx, TCheckGroupEx, TRadioGroupEx ]); RegisterComponents('LazControls', [ TCurrSpinEditEx diff --git a/components/exctrls/source/exctrlsreg.res b/components/exctrls/source/exctrlsreg.res index a2679ce11..b1b574a50 100644 Binary files a/components/exctrls/source/exctrlsreg.res and b/components/exctrls/source/exctrlsreg.res differ