📄 buttons.pas
字号:
begin
FMouseInControl := True;
if Enabled then
Repaint;
end;
end;
procedure TSpeedButton.CMMouseLeave(var Message: TMessage);
var
NeedRepaint: Boolean;
begin
inherited;
NeedRepaint := FFlat and FMouseInControl and Enabled and not FDragging;
{ Windows XP introduced hot states also for non-flat buttons. }
if NeedRepaint or ThemeServices.ThemesEnabled then
begin
FMouseInControl := False;
if Enabled then
Repaint;
end;
end;
procedure TSpeedButton.ActionChange(Sender: TObject; CheckDefaults: Boolean);
procedure CopyImage(ImageList: TCustomImageList; Index: Integer);
begin
with Glyph do
begin
Width := ImageList.Width;
Height := ImageList.Height;
Canvas.Brush.Color := clFuchsia;//! for lack of a better color
Canvas.FillRect(Rect(0,0, Width, Height));
ImageList.Draw(Canvas, 0, 0, Index);
end;
end;
begin
inherited ActionChange(Sender, CheckDefaults);
if Sender is TCustomAction then
with TCustomAction(Sender) do
begin
if CheckDefaults or (Self.GroupIndex = 0) then
Self.GroupIndex := GroupIndex;
{ Copy image from action's imagelist }
if (Glyph.Empty) and (ActionList <> nil) and (ActionList.Images <> nil) and
(ImageIndex >= 0) and (ImageIndex < ActionList.Images.Count) then
CopyImage(ActionList.Images, ImageIndex);
end;
end;
{ TBitBtn }
constructor TBitBtn.Create(AOwner: TComponent);
begin
FGlyph := TButtonGlyph.Create;
TButtonGlyph(FGlyph).OnChange := GlyphChanged;
inherited Create(AOwner);
FCanvas := TCanvas.Create;
FStyle := bsAutoDetect;
FKind := bkCustom;
FLayout := blGlyphLeft;
FSpacing := 4;
FMargin := -1;
ControlStyle := ControlStyle + [csReflector];
DoubleBuffered := True;
end;
destructor TBitBtn.Destroy;
begin
inherited Destroy;
TButtonGlyph(FGlyph).Free;
FCanvas.Free;
end;
procedure TBitBtn.CreateHandle;
var
State: TButtonState;
begin
if Enabled then
State := bsUp
else
State := bsDisabled;
inherited CreateHandle;
TButtonGlyph(FGlyph).CreateButtonGlyph(State);
end;
procedure TBitBtn.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do Style := Style or BS_OWNERDRAW;
end;
procedure TBitBtn.SetButtonStyle(ADefault: Boolean);
begin
if ADefault <> IsFocused then
begin
IsFocused := ADefault;
Refresh;
end;
end;
procedure TBitBtn.Click;
var
Form: TCustomForm;
Control: TWinControl;
begin
case FKind of
bkClose:
begin
Form := GetParentForm(Self);
if Form <> nil then Form.Close
else inherited Click;
end;
bkHelp:
begin
Control := Self;
while (Control <> nil) and (Control.HelpContext = 0) do
Control := Control.Parent;
if Control <> nil then Application.HelpContext(Control.HelpContext)
else inherited Click;
end;
else
inherited Click;
end;
end;
procedure TBitBtn.CNMeasureItem(var Message: TWMMeasureItem);
begin
with Message.MeasureItemStruct^ do
begin
itemWidth := Width;
itemHeight := Height;
end;
end;
procedure TBitBtn.CNDrawItem(var Message: TWMDrawItem);
begin
DrawItem(Message.DrawItemStruct^);
end;
procedure TBitBtn.DrawItem(const DrawItemStruct: TDrawItemStruct);
var
IsDown, IsDefault: Boolean;
State: TButtonState;
R: TRect;
Flags: Longint;
Details: TThemedElementDetails;
Button: TThemedButton;
Offset: TPoint;
begin
FCanvas.Handle := DrawItemStruct.hDC;
R := ClientRect;
with DrawItemStruct do
begin
FCanvas.Handle := hDC;
FCanvas.Font := Self.Font;
IsDown := itemState and ODS_SELECTED <> 0;
IsDefault := itemState and ODS_FOCUS <> 0;
if not Enabled then State := bsDisabled
else if IsDown then State := bsDown
else State := bsUp;
end;
if ThemeServices.ThemesEnabled then
begin
if not Enabled then
Button := tbPushButtonDisabled
else
if IsDown then
Button := tbPushButtonPressed
else
if FMouseInControl then
Button := tbPushButtonHot
else
if IsFocused or IsDefault then
Button := tbPushButtonDefaulted
else
Button := tbPushButtonNormal;
Details := ThemeServices.GetElementDetails(Button);
// Parent background.
ThemeServices.DrawParentBackground(Handle, DrawItemStruct.hDC, @Details, True);
// Button shape.
ThemeServices.DrawElement(DrawItemStruct.hDC, Details, DrawItemStruct.rcItem);
R := ThemeServices.ContentRect(FCanvas.Handle, Details, DrawItemStruct.rcItem);
if Button = tbPushButtonPressed then
Offset := Point(1, 0)
else
Offset := Point(0, 0);
TButtonGlyph(FGlyph).Draw(FCanvas, R, Offset, Caption, FLayout, FMargin, FSpacing, State, False,
DrawTextBiDiModeFlags(0));
if IsFocused and IsDefault then
begin
FCanvas.Pen.Color := clWindowFrame;
FCanvas.Brush.Color := clBtnFace;
DrawFocusRect(FCanvas.Handle, R);
end;
end
else
begin
R := ClientRect;
Flags := DFCS_BUTTONPUSH or DFCS_ADJUSTRECT;
if IsDown then Flags := Flags or DFCS_PUSHED;
if DrawItemStruct.itemState and ODS_DISABLED <> 0 then
Flags := Flags or DFCS_INACTIVE;
{ DrawFrameControl doesn't allow for drawing a button as the
default button, so it must be done here. }
if IsFocused or IsDefault then
begin
FCanvas.Pen.Color := clWindowFrame;
FCanvas.Pen.Width := 1;
FCanvas.Brush.Style := bsClear;
FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
{ DrawFrameControl must draw within this border }
InflateRect(R, -1, -1);
end;
{ DrawFrameControl does not draw a pressed button correctly }
if IsDown then
begin
FCanvas.Pen.Color := clBtnShadow;
FCanvas.Pen.Width := 1;
FCanvas.Brush.Color := clBtnFace;
FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
InflateRect(R, -1, -1);
end
else
DrawFrameControl(DrawItemStruct.hDC, R, DFC_BUTTON, Flags);
if IsFocused then
begin
R := ClientRect;
InflateRect(R, -1, -1);
end;
FCanvas.Font := Self.Font;
if IsDown then
OffsetRect(R, 1, 1);
TButtonGlyph(FGlyph).Draw(FCanvas, R, Point(0,0), Caption, FLayout, FMargin,
FSpacing, State, False, DrawTextBiDiModeFlags(0));
if IsFocused and IsDefault then
begin
R := ClientRect;
InflateRect(R, -4, -4);
FCanvas.Pen.Color := clWindowFrame;
FCanvas.Brush.Color := clBtnFace;
DrawFocusRect(FCanvas.Handle, R);
end;
end;
FCanvas.Handle := 0;
end;
procedure TBitBtn.CMFontChanged(var Message: TMessage);
begin
inherited;
Invalidate;
end;
procedure TBitBtn.CMEnabledChanged(var Message: TMessage);
begin
inherited;
Invalidate;
end;
procedure TBitBtn.WMLButtonDblClk(var Message: TWMLButtonDblClk);
begin
Perform(WM_LBUTTONDOWN, Message.Keys, Longint(Message.Pos));
end;
function TBitBtn.GetPalette: HPALETTE;
begin
Result := Glyph.Palette;
end;
procedure TBitBtn.SetGlyph(Value: TBitmap);
begin
TButtonGlyph(FGlyph).Glyph := Value as TBitmap;
FModifiedGlyph := True;
Invalidate;
end;
function TBitBtn.GetGlyph: TBitmap;
begin
Result := TButtonGlyph(FGlyph).Glyph;
end;
procedure TBitBtn.GlyphChanged(Sender: TObject);
begin
Invalidate;
end;
function TBitBtn.IsCustom: Boolean;
begin
Result := Kind = bkCustom;
end;
procedure TBitBtn.SetStyle(Value: TButtonStyle);
begin
if Value <> FStyle then
begin
FStyle := Value;
Invalidate;
end;
end;
procedure TBitBtn.SetKind(Value: TBitBtnKind);
begin
if Value <> FKind then
begin
if Value <> bkCustom then
begin
Default := Value in [bkOK, bkYes];
Cancel := Value in [bkCancel, bkNo];
if ((csLoading in ComponentState) and (Caption = '')) or
(not (csLoading in ComponentState)) then
begin
if BitBtnCaptions[Value] <> nil then
Caption := LoadResString(BitBtnCaptions[Value]);
end;
ModalResult := BitBtnModalResults[Value];
TButtonGlyph(FGlyph).Glyph := GetBitBtnGlyph(Value);
NumGlyphs := 2;
FModifiedGlyph := False;
end;
FKind := Value;
Invalidate;
end;
end;
function TBitBtn.IsCustomCaption: Boolean;
begin
Result := AnsiCompareStr(Caption, LoadResString(BitBtnCaptions[FKind])) <> 0;
end;
function TBitBtn.GetKind: TBitBtnKind;
begin
if FKind <> bkCustom then
if ((FKind in [bkOK, bkYes]) xor Default) or
((FKind in [bkCancel, bkNo]) xor Cancel) or
(ModalResult <> BitBtnModalResults[FKind]) or
FModifiedGlyph then
FKind := bkCustom;
Result := FKind;
end;
procedure TBitBtn.SetLayout(Value: TButtonLayout);
begin
if FLayout <> Value then
begin
FLayout := Value;
Invalidate;
end;
end;
function TBitBtn.GetNumGlyphs: TNumGlyphs;
begin
Result := TButtonGlyph(FGlyph).NumGlyphs;
end;
procedure TBitBtn.SetNumGlyphs(Value: TNumGlyphs);
begin
if Value < 0 then Value := 1
else if Value > 4 then Value := 4;
if Value <> TButtonGlyph(FGlyph).NumGlyphs then
begin
TButtonGlyph(FGlyph).NumGlyphs := Value;
Invalidate;
end;
end;
procedure TBitBtn.SetSpacing(Value: Integer);
begin
if FSpacing <> Value then
begin
FSpacing := Value;
Invalidate;
end;
end;
procedure TBitBtn.SetMargin(Value: Integer);
begin
if (Value <> FMargin) and (Value >= - 1) then
begin
FMargin := Value;
Invalidate;
end;
end;
procedure TBitBtn.ActionChange(Sender: TObject; CheckDefaults: Boolean);
procedure CopyImage(ImageList: TCustomImageList; Index: Integer);
begin
with Glyph do
begin
Width := ImageList.Width;
Height := ImageList.Height;
Canvas.Brush.Color := clFuchsia;//! for lack of a better color
Canvas.FillRect(Rect(0,0, Width, Height));
ImageList.Draw(Canvas, 0, 0, Index);
end;
end;
begin
inherited ActionChange(Sender, CheckDefaults);
if Sender is TCustomAction then
with TCustomAction(Sender) do
begin
{ Copy image from action's imagelist }
if (Glyph.Empty) and (ActionList <> nil) and (ActionList.Images <> nil) and
(ImageIndex >= 0) and (ImageIndex < ActionList.Images.Count) then
CopyImage(ActionList.Images, ImageIndex);
end;
end;
procedure DestroyLocals; far;
var
I: TBitBtnKind;
begin
for I := Low(TBitBtnKind) to High(TBitBtnKind) do
BitBtnGlyphs[I].Free;
end;
procedure TBitBtn.CMMouseEnter(var Message: TMessage);
begin
inherited;
if ThemeServices.ThemesEnabled and not FMouseInControl and not (csDesigning in ComponentState) then
begin
FMouseInControl := True;
Repaint;
end;
end;
procedure TBitBtn.CMMouseLeave(var Message: TMessage);
begin
inherited;
if ThemeServices.ThemesEnabled and FMouseInControl then
begin
FMouseInControl := False;
Repaint;
end;
end;
initialization
FillChar(BitBtnGlyphs, SizeOf(BitBtnGlyphs), 0);
finalization
DestroyLocals;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -