📄 fccombobutton.pas
字号:
MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
{ Convert gray to clBtnShadow }
DDB.Canvas.Brush.Color := clGray;
MonoBmp.Canvas.CopyRect(IRect, DDB.Canvas, ORect);
Brush.Color := clBtnShadow;
DestDC := Handle;
SetTextColor(DestDC, clBlack);
SetBkColor(DestDC, clWhite);
BitBlt(DestDC, 0, 0, IWidth, IHeight,
MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
{ Convert transparent color to clBtnFace }
DDB.Canvas.Brush.Color := ColorToRGB(FTransparentColor);
MonoBmp.Canvas.CopyRect(IRect, DDB.Canvas, ORect);
Brush.Color := clBtnFace;
DestDC := Handle;
SetTextColor(DestDC, clBlack);
SetBkColor(DestDC, clWhite);
BitBlt(DestDC, 0, 0, IWidth, IHeight,
MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
end
else
begin
{ Create a disabled version }
with MonoBmp do
begin
Assign(FOriginal);
HandleType := bmDDB;
Canvas.Brush.Color := clBlack;
Width := IWidth;
if Monochrome then
begin
Canvas.Font.Color := clWhite;
Monochrome := False;
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;
finally
DDB.Free;
MonoBmp.Free;
end;
FIndexs[State] := FGlyphList.AddMasked(TmpImage, clDefault);
end;
end;
finally
TmpImage.Free;
end;
Result := FIndexs[State];
FOriginal.Dormant;
end;
procedure TfcComboButtonGlyph.DrawButtonGlyph(Canvas: TCanvas; const GlyphPos: TPoint;
State: TButtonState; Transparent: Boolean);
var
Index: Integer;
{$ifdef fcUseThemeManager}
Details: TThemedElementDetails;
R: TRect;
Button: TThemedButton;
{$endif}
begin
if FOriginal = nil then Exit;
if (FOriginal.Width = 0) or (FOriginal.Height = 0) then Exit;
Index := CreateButtonGlyph(State);
with GlyphPos do
begin
if fcUseThemes(ComboButton) then
begin
{$ifdef fcUseThemeManager}
R.TopLeft := GlyphPos;
R.Right := R.Left + FOriginal.Width div FNumGlyphs;
R.Bottom := R.Top + FOriginal.Height;
case State of
bsDisabled:
Button := tbPushButtonDisabled;
bsDown,
bsExclusive:
Button := tbPushButtonPressed;
else
// bsUp
Button := tbPushButtonNormal;
end;
Details := ThemeServices.GetElementDetails(Button);
ThemeServices.DrawIcon(Canvas.Handle, Details, R, FGlyphList.Handle, Index);
{$endif}
end
else
if Transparent or (State = bsExclusive) then
begin
ImageList_DrawEx(FGlyphList.Handle, Index, Canvas.Handle, X, Y, 0, 0,
clNone, clNone, ILD_Transparent)
end
else
ImageList_DrawEx(FGlyphList.Handle, Index, Canvas.Handle, X, Y, 0, 0,
ColorToRGB(clBtnFace), clNone, ILD_Normal);
end;
end;
procedure TfcComboButtonGlyph.DrawButtonText(Canvas: TCanvas; const Caption: string;
TextBounds: TRect; State: TButtonState; BiDiFlags: LongInt);
begin
with Canvas do
begin
Brush.Style := bsClear;
if State = bsDisabled then
begin
OffsetRect(TextBounds, 1, 1);
Font.Color := clBtnHighlight;
DrawText(Handle, PChar(Caption), Length(Caption), TextBounds,
DT_CENTER or DT_VCENTER or BiDiFlags);
OffsetRect(TextBounds, -1, -1);
Font.Color := clBtnShadow;
DrawText(Handle, PChar(Caption), Length(Caption), TextBounds,
DT_CENTER or DT_VCENTER or BiDiFlags);
end else
DrawText(Handle, PChar(Caption), Length(Caption), TextBounds,
DT_CENTER or DT_VCENTER or BiDiFlags);
end;
end;
procedure TfcComboButtonGlyph.CalcButtonLayout(Canvas: TCanvas; const Client: TRect;
const Offset: TPoint; const Caption: string; Layout: TButtonLayout; Margin,
Spacing: Integer; var GlyphPos: TPoint; var TextBounds: TRect;
BiDiFlags: LongInt);
var
TextPos: TPoint;
ClientSize, GlyphSize, TextSize: TPoint;
TotalSize: TPoint;
begin
if (BiDiFlags and DT_RIGHT) = DT_RIGHT then
if Layout = blGlyphLeft then Layout := blGlyphRight
else
if Layout = blGlyphRight then Layout := blGlyphLeft;
{ 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 or BiDiFlags);
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 }
with GlyphPos do
begin
Inc(X, Client.Left + Offset.X);
Inc(Y, Client.Top + Offset.Y);
end;
{ Themed text is not shifted, but gets a different color. }
{ Themed text is not shifted, but gets a different color. }
if fcUseThemes(ComboButton) then
OffsetRect(TextBounds, TextPos.X + Client.Left, TextPos.Y + Client.Top)
else
OffsetRect(TextBounds, TextPos.X + Client.Left + Offset.X, TextPos.Y + Client.Top + Offset.Y);
end;
function TfcComboButtonGlyph.Draw(Canvas: TCanvas; const Client: TRect;
const Offset: TPoint; const Caption: string; Layout: TButtonLayout;
Margin, Spacing: Integer; State: TButtonState; Transparent: Boolean;
BiDiFlags: LongInt): TRect;
var
GlyphPos: TPoint;
begin
CalcButtonLayout(Canvas, Client, Offset, Caption, Layout, Margin, Spacing,
GlyphPos, Result, BiDiFlags);
DrawButtonGlyph(Canvas, GlyphPos, State, Transparent);
DrawButtonText(Canvas, Caption, Result, State, BiDiFlags);
end;
procedure TfcComboButtonActionLink.AssignClient(AClient: TObject);
begin
inherited AssignClient(AClient);
FClient := AClient as TSpeedButton;
end;
function TfcComboButtonActionLink.IsCheckedLinked: Boolean;
begin
Result := inherited IsCheckedLinked and (FClient.GroupIndex <> 0) and
FClient.AllowAllUp and (FClient.Down = (Action as TCustomAction).Checked);
end;
{$ifdef fcDelphi6Up}
function TfcComboButtonActionLink.IsGroupIndexLinked: Boolean;
begin
Result := (FClient is TSpeedButton) and
(TSpeedButton(FClient).GroupIndex = (Action as TCustomAction).GroupIndex);
end;
{$endif}
procedure TfcComboButtonActionLink.SetChecked(Value: Boolean);
begin
if IsCheckedLinked then TSpeedButton(FClient).Down := Value;
end;
{$ifdef fcDelphi6Up}
procedure TfcComboButtonActionLink.SetGroupIndex(Value: Integer);
begin
if IsGroupIndexLinked then TSpeedButton(FClient).GroupIndex := Value;
end;
{$endif}
{ TfcComboButton }
constructor TfcComboButton.Create(AOwner: TComponent);
begin
FGlyph := TfcComboButtonGlyph.Create(self);
TfcComboButtonGlyph(FGlyph).OnChange := GlyphChanged;
inherited Create(AOwner);
SetBounds(0, 0, 23, 22);
ControlStyle := [csCaptureMouse, csDoubleClicks];
ParentFont := True;
Color := clBtnFace;
FSpacing := 4;
FMargin := -1;
FLayout := blGlyphLeft;
FTransparent := True;
Inc(ButtonCount);
end;
destructor TfcComboButton.Destroy;
begin
Dec(ButtonCount);
inherited Destroy;
TfcComboButtonGlyph(FGlyph).Free;
end;
{$ifdef ThemeManager}
procedure PerformEraseBackground(Control: TControl; DC: HDC);
var
LastOrigin: TPoint;
begin
GetWindowOrgEx(DC, LastOrigin);
SetWindowOrgEx(DC, LastOrigin.X + Control.Left, LastOrigin.Y + Control.Top, nil);
Control.Parent.Perform(WM_ERASEBKGND, Integer(DC), Integer(DC));
SetWindowOrgEx(DC, LastOrigin.X, LastOrigin.Y, nil);
end;
{$endif}
// Should likely support button style as well as combobutton
procedure TfcComboButton.Paint;
const
DownStyles: array[Boolean] of Integer = (BDR_RAISEDINNER, BDR_SUNKENOUTER);
FillStyles: array[Boolean] of Integer = (BF_MIDDLE, 0);
var
PaintRect: TRect;
DrawFlags: Integer;
Offset: TPoint;
{$ifdef fcUseThemeManager}
ComboBox: TThemedCombobox;
Details: TThemedElementDetails;
W, X, Y: Integer;
R: TRect;
Pressed: boolean;
{$endif}
begin
if not Enabled 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 fcUseThemes(self) then
begin
{$ifdef fcUseThemeManager}
PerformEraseBackground(Self, Canvas.Handle);
if Ellipsis then begin
Pressed:= FState in [bsDown, bsExclusive];
if Pressed then
Details := ThemeServices.GetElementDetails(tbPushButtonPressed)
else
if MouseInControl then
Details := ThemeServices.GetElementDetails(tbPushButtonHot)
else
Details := ThemeServices.GetElementDetails(tbPushButtonNormal);
PaintRect := ClientRect;
ThemeServices.DrawElement(Canvas.Handle, Details, PaintRect);
R:= PaintRect;
X := R.Left + ((R.Right - R.Left) shr 1) - 1;
Y := R.Top + ((R.Bottom - R.Top) shr 1) - 1;
W := ClientWidth shr 3;
if W = 0 then W := 1;
PatBlt(Canvas.Handle, X, Y, W, W, BLACKNESS);
PatBlt(Canvas.handle, X - (W * 2), Y, W, W, BLACKNESS);
PatBlt(Canvas.Handle, X + (W * 2), Y, W, W, BLACKNESS);
end
else begin
if not Enabled then // Not ellpisis
ComboBox:= tcDropDownButtonDisabled
else
if FState in [bsDown, bsExclusive] then
ComboBox:= tcDropDownButtonPressed
else
if MouseInControl then
ComboBox:= tcDropDownButtonHot
else
ComboBox:= tcDropDownButtonNormal;
PaintRect := ClientRect;
if (parent.parent<>nil) and (parent.parent.parent<>nil) and
not fcIsClass(parent.parent.parent.classtype, 'TCustomGrid') then
begin
PaintRect.Top:= PaintRect.Top-1;
PaintRect.Bottom:= PaintRect.Bottom+1;
PaintRect.Right:= PaintRect.Right+1;
PaintRect.Left:= PaintRect.Left+1;
end
else begin // parent of combo is grid
PaintRect.Bottom:= PaintRect.Bottom+1;
end;
Details := ThemeServices.GetElementDetails(ComboBox);
ThemeServices.DrawElement(Canvas.Handle, Details, PaintRect);
PaintRect := ThemeServices.ContentRect(Canvas.Handle, Details, PaintRect);
if ComboBox = tcDropDownButtonPressed then
begin
Offset := Point(0, 0);
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -