📄 mybutton.pas
字号:
Canvas.Brush.Color := clWhite;
end;
Monochrome := True;
end;
with TmpImage.Canvas do
begin
Brush.Color := clBtnFace;
FillRect(IRect);
Brush.Color := clBtnHighlight;
SetTextColor(Handle, clBlack);
SetBkColor(Handle, clWhite);
BitBlt(Handle, 1, 1, IWidth, IHeight,
MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
Brush.Color := clBtnShadow;
SetTextColor(Handle, clBlack);
SetBkColor(Handle, clWhite);
BitBlt(Handle, 0, 0, IWidth, IHeight,
MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
end;
end;
FIndexs[State] := FGlyphList.Add(TmpImage, nil);
finally
MonoBmp.Free;
end;
end;
end;
finally
TmpImage.Free;
end;
Result := FIndexs[State];
FOriginal.Dormant;
end;
procedure TButtonGlyph.DrawButtonGlyph(Canvas: TCanvas; X, Y: Integer;
State: TButtonState);
var
Index: Integer;
begin
if FOriginal = nil then Exit;
if (FOriginal.Width = 0) or (FOriginal.Height = 0) then Exit;
Index := CreateButtonGlyph(State);
if State = bsExclusive then
ImageList_DrawEx(FGlyphList.Handle, Index, Canvas.Handle, X, Y, 0, 0,
clNone, clNone, ILD_Transparent)
else
ImageList_DrawEx(FGlyphList.Handle, Index, Canvas.Handle, X, Y, 0, 0,
ColorToRGB(clBtnFace), clNone, ILD_Normal);
end;
procedure TButtonGlyph.DrawButtonText(Canvas: TCanvas; const Caption: string;
TextBounds: TRect; State: TButtonState);
begin
with Canvas do
begin
Brush.Style := bsClear;
if State = bsDisabled then
begin
OffsetRect(TextBounds, 1, 1);
Font.Color := clWhite;
DrawText(Handle, PChar(Caption), Length(Caption), TextBounds, 0);
OffsetRect(TextBounds, -1, -1);
Font.Color := clDkGray;
DrawText(Handle, PChar(Caption), Length(Caption), TextBounds, 0);
end else
DrawText(Handle, PChar(Caption), Length(Caption), TextBounds,
DT_CENTER or DT_VCENTER or DT_SINGLELINE);
end;
end;
procedure TButtonGlyph.CalcButtonLayout(Canvas: TCanvas; const Client: TRect;
const Caption: string; Layout: TButtonLayout; Margin, Spacing: Integer;
var GlyphPos: TPoint; var TextBounds: TRect);
var
TextPos: TPoint;
ClientSize, GlyphSize, TextSize: TPoint;
TotalSize: TPoint;
begin
{ calculate the item sizes }
ClientSize := Point(Client.Right - Client.Left, Client.Bottom -
Client.Top);
if FOriginal <> nil then
GlyphSize := Point(FOriginal.Width div FNumGlyphs, FOriginal.Height) else
GlyphSize := Point(0, 0);
if Length(Caption) > 0 then
begin
TextBounds := Rect(0, 0, Client.Right - Client.Left, 0);
DrawText(Canvas.Handle, PChar(Caption), Length(Caption), TextBounds, DT_CALCRECT);
TextSize := Point(TextBounds.Right - TextBounds.Left, TextBounds.Bottom -
TextBounds.Top);
end
else
begin
TextBounds := Rect(0, 0, 0, 0);
TextSize := Point(0,0);
end;
{ If the layout has the glyph on the right or the left, then both the
text and the glyph are centered vertically. If the glyph is on the top
or the bottom, then both the text and the glyph are centered horizontally.}
if Layout in [blGlyphLeft, blGlyphRight] then
begin
GlyphPos.Y := (ClientSize.Y - GlyphSize.Y + 1) div 2;
TextPos.Y := (ClientSize.Y - TextSize.Y + 1) div 2;
end
else
begin
GlyphPos.X := (ClientSize.X - GlyphSize.X + 1) div 2;
TextPos.X := (ClientSize.X - TextSize.X + 1) div 2;
end;
{ if there is no text or no bitmap, then Spacing is irrelevant }
if (TextSize.X = 0) or (GlyphSize.X = 0) then
Spacing := 0;
{ adjust Margin and Spacing }
if Margin = -1 then
begin
if Spacing = -1 then
begin
TotalSize := Point(GlyphSize.X + TextSize.X, GlyphSize.Y + TextSize.Y);
if Layout in [blGlyphLeft, blGlyphRight] then
Margin := (ClientSize.X - TotalSize.X) div 3
else
Margin := (ClientSize.Y - TotalSize.Y) div 3;
Spacing := Margin;
end
else
begin
TotalSize := Point(GlyphSize.X + Spacing + TextSize.X, GlyphSize.Y +
Spacing + TextSize.Y);
if Layout in [blGlyphLeft, blGlyphRight] then
Margin := (ClientSize.X - TotalSize.X + 1) div 2
else
Margin := (ClientSize.Y - TotalSize.Y + 1) div 2;
end;
end
else
begin
if Spacing = -1 then
begin
TotalSize := Point(ClientSize.X - (Margin + GlyphSize.X), ClientSize.Y -
(Margin + GlyphSize.Y));
if Layout in [blGlyphLeft, blGlyphRight] then
Spacing := (TotalSize.X - TextSize.X) div 2
else
Spacing := (TotalSize.Y - TextSize.Y) div 2;
end;
end;
case Layout of
blGlyphLeft:
begin
GlyphPos.X := Margin;
TextPos.X := GlyphPos.X + GlyphSize.X + Spacing;
end;
blGlyphRight:
begin
GlyphPos.X := ClientSize.X - Margin - GlyphSize.X;
TextPos.X := GlyphPos.X - Spacing - TextSize.X;
end;
blGlyphTop:
begin
GlyphPos.Y := Margin;
TextPos.Y := GlyphPos.Y + GlyphSize.Y + Spacing;
end;
blGlyphBottom:
begin
GlyphPos.Y := ClientSize.Y - Margin - GlyphSize.Y;
TextPos.Y := GlyphPos.Y - Spacing - TextSize.Y;
end;
end;
{ fixup the result variables }
Inc(GlyphPos.X, Client.Left);
Inc(GlyphPos.Y, Client.Top);
OffsetRect(TextBounds, TextPos.X + Client.Left, TextPos.Y + Client.Top);
end;
function TButtonGlyph.Draw(Canvas: TCanvas; const Client: TRect;
const Caption: string; Layout: TButtonLayout; Margin, Spacing: Integer;
State: TButtonState): TRect;
var
GlyphPos: TPoint;
begin
CalcButtonLayout(Canvas, Client, Caption, Layout, Margin, Spacing,
GlyphPos, Result);
DrawButtonGlyph(Canvas, GlyphPos.X, GlyphPos.Y, State);
DrawButtonText(Canvas, Caption, Result, State);
end;
{ TMyButton }
constructor TMyButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
SetBounds(0, 0, 25, 25);
ControlStyle := [csCaptureMouse, csOpaque, csDoubleClicks];
FGlyph := TButtonGlyph.Create;
TButtonGlyph(FGlyph).OnChange := GlyphChanged;
ParentFont := True;
FSpacing := 4;
FMargin := -1;
FLayout := blGlyphLeft;
Inc(ButtonCount);
end;
destructor TMyButton.Destroy;
begin
TButtonGlyph(FGlyph).Free;
Dec(ButtonCount);
if ButtonCount = 0 then
begin
Pattern.Free;
Pattern := nil;
end;
inherited Destroy;
end;
procedure TMyButton.Paint;
var
PaintRect: TRect;
begin
if not Enabled and not (csDesigning in ComponentState) then
begin
FState := bsDisabled;
FDragging := False;
end
else if FState = bsDisabled then
if FDown and (GroupIndex <> 0) then
FState := bsExclusive
else
FState := bsUp;
Canvas.Font := Self.Font;
if csDesigning in ComponentState then
PaintRect := DrawMyButtonFace(Canvas, Rect(0, 0, Width, Height), 1, bsNew,
True, FState in [bsDown, bsExclusive], False)
else
PaintRect := DrawMyButtonFace(Canvas, Rect(0, 0, Width, Height), 1, bsNew,
False, FState in [bsDown, bsExclusive], False);
if FState = bsExclusive then
begin
if Pattern = nil then CreateBrushPattern;
Canvas.Brush.Bitmap := Pattern;
Dec(PaintRect.Right);
Dec(PaintRect.Bottom);
Canvas.FillRect(PaintRect);
end;
TButtonGlyph(FGlyph).Draw(Canvas, PaintRect, Caption, FLayout, FMargin, FSpacing,
FState);
end;
{
function TMyButton.getGlyphPos:Tpoint;
var therect:Trect;
PaintRect: TRect;
begin
paintRect := Rect(1, 1, Width-2, Height-2);
if Down then OffsetRect(paintRect, 1, 1);
TButtonGlyph(FGlyph).CalcButtonLayout(Canvas, paintRect, Caption, FLayout, FMargin, FSpacing,
result,therect);
end;
}
procedure TMyButton.Loaded;
var
State: TButtonState;
begin
inherited Loaded;
if Enabled then
State := bsUp
else
State := bsDisabled;
TButtonGlyph(FGlyph).CreateButtonGlyph(State);
end;
procedure TMyButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited MouseDown(Button, Shift, X, Y);
if (Button = mbLeft) and Enabled then
begin
if not FDown then
begin
FState := bsDown;
Repaint;
end;
FDragging := True;
end;
end;
procedure TMyButton.MouseMove(Shift: TShiftState; X, Y: Integer);
var
NewState: TButtonState;
begin
inherited MouseMove(Shift, X, Y);
if FDragging then
begin
if not FDown then NewState := bsUp
else NewState := bsExclusive;
if (X >= 0) and (X < ClientWidth) and (Y >= 0) and (Y <= ClientHeight) then
if FDown then NewState := bsExclusive else NewState := bsDown;
if NewState <> FState then
begin
FState := NewState;
Repaint;
end;
end;
end;
procedure TMyButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
DoClick: Boolean;
begin
inherited MouseUp(Button, Shift, X, Y);
if FDragging then
begin
FDragging := False;
DoClick := (X >= 0) and (X < ClientWidth) and (Y >= 0) and (Y <= ClientHeight);
FState := bsUp;
if FGroupIndex = 0 then
Repaint
else
if DoClick then SetDown(not FDown)
else
begin
if FDown then FState := bsExclusive;
Repaint;
end;
if DoClick then Click;
end;
end;
procedure TMyButton.Click;
begin
inherited Click;
end;
function TMyButton.GetPalette: HPALETTE;
begin
Result := Glyph.Palette;
end;
function TMyButton.GetGlyph: TBitmap;
begin
Result := TButtonGlyph(FGlyph).Glyph;
end;
procedure TMyButton.SetGlyph(Value: TBitmap);
begin
TButtonGlyph(FGlyph).Glyph := Value;
Invalidate;
end;
function TMyButton.GetNumGlyphs: TNumGlyphs;
begin
Result := TButtonGlyph(FGlyph).NumGlyphs;
end;
procedure TMyButton.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 TMyButton.GlyphChanged(Sender: TObject);
begin
Invalidate;
end;
procedure TMyButton.UpdateExclusive;
var
Msg: TMessage;
begin
if (FGroupIndex <> 0) and (Parent <> nil) then
begin
Msg.Msg := CM_BUTTONPRESSED;
Msg.WParam := FGroupIndex;
Msg.LParam := Longint(Self);
Msg.Result := 0;
Parent.Broadcast(Msg);
end;
end;
procedure TMyButton.SetDown(Value: Boolean);
begin
if FGroupIndex = 0 then Value := False;
if Value <> FDown then
begin
if FDown and (not FAllowAllUp) then Exit;
FDown := Value;
if Value then FState := bsExclusive
else FState := bsUp;
Invalidate;
if Value then UpdateExclusive;
end;
end;
procedure TMyButton.SetGroupIndex(Value: Integer);
begin
if FGroupIndex <> Value then
begin
FGroupIndex := Value;
UpdateExclusive;
end;
end;
procedure TMyButton.SetLayout(Value: TButtonLayout);
begin
if FLayout <> Value then
begin
FLayout := Value;
Invalidate;
end;
end;
procedure TMyButton.SetMargin(Value: Integer);
begin
if (Value <> FMargin) and (Value >= -1) then
begin
FMargin := Value;
Invalidate;
end;
end;
procedure TMyButton.SetSpacing(Value: Integer);
begin
if Value <> FSpacing then
begin
FSpacing := Value;
Invalidate;
end;
end;
procedure TMyButton.SetAllowAllUp(Value: Boolean);
begin
if FAllowAllUp <> Value then
begin
FAllowAllUp := Value;
UpdateExclusive;
end;
end;
procedure TMyButton.WMLButtonDblClk(var Message: TWMLButtonDown);
begin
inherited;
if FDown then DblClick;
end;
procedure TMyButton.CMEnabledChanged(var Message: TMessage);
const
NewState: array[Boolean] of TButtonState = (bsDisabled, bsUp);
begin
TButtonGlyph(FGlyph).CreateButtonGlyph(NewState[Enabled]);
Invalidate;
end;
procedure TMyButton.CMButtonPressed(var Message: TMessage);
var
Sender: TMyButton;
begin
if Message.WParam = FGroupIndex then
begin
Sender := TMyButton(Message.LParam);
if Sender <> Self then
begin
if Sender.Down and FDown then
begin
FDown := False;
FState := bsUp;
Invalidate;
end;
FAllowAllUp := Sender.AllowAllUp;
end;
end;
end;
procedure TMyButton.CMDialogChar(var Message: TCMDialogChar);
begin
with Message do
if IsAccel(CharCode, Caption) and Enabled then
begin
Click;
Result := 1;
end else
inherited;
end;
procedure TMyButton.CMMOUSELEAVE(var Message: TMessage);
begin
inherited;
MouseLeave;
end;
procedure TMyButton.CMMOUSEENTER(var Message: TMessage);
begin
inherited;
MouseEnter;
end;
procedure TMyButton.MouseEnter;
begin
if Assigned(FOnMouseEnter) then FOnMouseEnter(Self);
end;
procedure TMyButton.MouseLeave;
begin
if Assigned(FOnMouseLeave) then FOnMouseLeave(Self);
end;
procedure TMyButton.CMFontChanged(var Message: TMessage);
begin
Invalidate;
end;
procedure TMyButton.CMTextChanged(var Message: TMessage);
begin
Invalidate;
end;
procedure TMyButton.CMSysColorChange(var Message: TMessage);
begin
with TButtonGlyph(FGlyph) do
begin
Invalidate;
CreateButtonGlyph(FState);
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -