2 {*****************************************************************************}
4 { Tnt Delphi Unicode Controls }
5 { http://www.tntware.com/delphicontrols/unicode/ }
8 { Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com) }
10 {*****************************************************************************}
14 {$INCLUDE TntCompilers.inc}
19 Windows
, Messages
, Classes
, Controls
, Graphics
, StdCtrls
,
20 ExtCtrls
, CommCtrl
, Buttons
,
24 ITntGlyphButton
= interface
25 ['{15D7E501-1E33-4293-8B45-716FB3B14504}']
26 function GetButtonGlyph
: Pointer;
27 procedure UpdateInternalGlyphList
;
30 {TNT-WARN TSpeedButton}
31 TTntSpeedButton
= class(TSpeedButton
{TNT-ALLOW TSpeedButton}, ITntGlyphButton
)
33 FPaintInherited
: Boolean;
34 function GetCaption
: TWideCaption
;
35 procedure SetCaption(const Value
: TWideCaption
);
36 function GetHint
: WideString
;
37 procedure SetHint(const Value
: WideString
);
38 function IsCaptionStored
: Boolean;
39 function IsHintStored
: Boolean;
40 procedure CMHintShow(var Message: TMessage
); message CM_HINTSHOW
;
41 procedure CMDialogChar(var Message: TCMDialogChar
); message CM_DIALOGCHAR
;
43 function GetButtonGlyph
: Pointer;
44 procedure UpdateInternalGlyphList
; dynamic;
45 procedure PaintButton
; dynamic;
46 procedure Paint
; override;
47 procedure DefineProperties(Filer
: TFiler
); override;
48 function GetActionLinkClass
: TControlActionLinkClass
; override;
49 procedure ActionChange(Sender
: TObject
; CheckDefaults
: Boolean); override;
51 property Caption
: TWideCaption read GetCaption write SetCaption stored IsCaptionStored
;
52 property Hint
: WideString read GetHint write SetHint stored IsHintStored
;
56 TTntBitBtn
= class(TBitBtn
{TNT-ALLOW TBitBtn}, ITntGlyphButton
)
58 FPaintInherited
: Boolean;
59 FMouseInControl
: Boolean;
60 function IsCaptionStored
: Boolean;
61 function GetCaption
: TWideCaption
;
62 procedure SetCaption(const Value
: TWideCaption
);
63 function IsHintStored
: Boolean;
64 function GetHint
: WideString
;
65 procedure SetHint(const Value
: WideString
);
66 procedure CMDialogChar(var Message: TCMDialogChar
); message CM_DIALOGCHAR
;
67 procedure CNDrawItem(var Message: TWMDrawItem
); message CN_DRAWITEM
;
68 procedure CMMouseEnter(var Message: TMessage
); message CM_MOUSEENTER
;
69 procedure CMMouseLeave(var Message: TMessage
); message CM_MOUSELEAVE
;
71 function GetButtonGlyph
: Pointer;
72 procedure UpdateInternalGlyphList
; dynamic;
73 procedure DrawItem(const DrawItemStruct
: TDrawItemStruct
); dynamic;
74 procedure CreateWindowHandle(const Params
: TCreateParams
); override;
75 procedure DefineProperties(Filer
: TFiler
); override;
76 function GetActionLinkClass
: TControlActionLinkClass
; override;
77 procedure ActionChange(Sender
: TObject
; CheckDefaults
: Boolean); override;
79 property Caption
: TWideCaption read GetCaption write SetCaption stored IsCaptionStored
;
80 property Hint
: WideString read GetHint write SetHint stored IsHintStored
;
83 procedure TButtonGlyph_CalcButtonLayout(Control
: TControl
; DC
: HDC
; const Client
: TRect
;
84 const Offset
: TPoint
; const Caption
: WideString
; Layout
: TButtonLayout
;
85 Margin
, Spacing
: Integer; var GlyphPos
: TPoint
; var TextBounds
: TRect
;
86 BiDiFlags
: Integer {$IFDEF COMPILER_7_UP}; WordWrap
: Boolean {$ENDIF});
88 function TButtonGlyph_Draw(Control
: TControl
; Canvas
: TCanvas
; const Client
: TRect
;
89 const Offset
: TPoint
; const Caption
: WideString
; Layout
: TButtonLayout
; Margin
: Integer;
90 Spacing
: Integer; State
: TButtonState
; Transparent
: Boolean;
91 BiDiFlags
: Longint {$IFDEF COMPILER_7_UP}; WordWrap
: Boolean {$ENDIF}): TRect
;
96 SysUtils
, ActnList
, TntForms
, TntStdCtrls
, TypInfo
, RTLConsts
, TntWindows
,
97 {$IFDEF THEME_7_UP} Themes
, {$ENDIF} TntClasses
, TntActnList
, TntSysUtils
;
100 EAbortPaint
= class(EAbort
);
102 // Many routines in this unit are nearly the same as those found in Buttons.pas. They are
103 // included here because the VCL implementation of TButtonGlyph is completetly inaccessible.
106 THackButtonGlyph_D6_D7_D9
= class
109 FGlyphList
: TImageList
;
110 FIndexs
: array[TButtonState
] of Integer;
111 FxxxxTransparentColor
: TColor
;
112 FNumGlyphs
: TNumGlyphs
;
115 THackBitBtn_D6_D7_D9
= class(TButton
{TNT-ALLOW TButton})
119 FxxxxStyle
: TButtonStyle
;
120 FxxxxKind
: TBitBtnKind
;
121 FxxxxLayout
: TButtonLayout
;
122 FxxxxSpacing
: Integer;
123 FxxxxMargin
: Integer;
127 THackSpeedButton_D6_D7_D9
= class(TGraphicControl
)
129 FxxxxGroupIndex
: Integer;
135 {$IFDEF COMPILER_6} // verified against VCL source in Delphi 6 and BCB 6
136 THackButtonGlyph
= THackButtonGlyph_D6_D7_D9
;
137 THackBitBtn
= THackBitBtn_D6_D7_D9
;
138 THackSpeedButton
= THackSpeedButton_D6_D7_D9
;
140 {$IFDEF DELPHI_7} // verified against VCL source in Delphi 7
141 THackButtonGlyph
= THackButtonGlyph_D6_D7_D9
;
142 THackBitBtn
= THackBitBtn_D6_D7_D9
;
143 THackSpeedButton
= THackSpeedButton_D6_D7_D9
;
145 {$IFDEF DELPHI_9} // verified against VCL source in Delphi 9
146 THackButtonGlyph
= THackButtonGlyph_D6_D7_D9
;
147 THackBitBtn
= THackBitBtn_D6_D7_D9
;
148 THackSpeedButton
= THackSpeedButton_D6_D7_D9
;
150 {$IFDEF DELPHI_10} // verified against VCL source in Delphi 10
151 THackButtonGlyph
= THackButtonGlyph_D6_D7_D9
;
152 THackBitBtn
= THackBitBtn_D6_D7_D9
;
153 THackSpeedButton
= THackSpeedButton_D6_D7_D9
;
156 function GetButtonGlyph(Control
: TControl
): THackButtonGlyph
;
158 GlyphButton
: ITntGlyphButton
;
160 if Control
.GetInterface(ITntGlyphButton
, GlyphButton
) then
161 Result
:= GlyphButton
.GetButtonGlyph
163 raise ETntInternalError
.Create('Internal Error: Control does not support ITntGlyphButton.');
166 procedure UpdateInternalGlyphList(Control
: TControl
);
168 GlyphButton
: ITntGlyphButton
;
170 if Control
.GetInterface(ITntGlyphButton
, GlyphButton
) then
171 GlyphButton
.UpdateInternalGlyphList
173 raise ETntInternalError
.Create('Internal Error: Control does not support ITntGlyphButton.');
176 function TButtonGlyph_CreateButtonGlyph(Control
: TControl
; State
: TButtonState
): Integer;
178 ButtonGlyph
: THackButtonGlyph
;
181 ButtonGlyph
:= GetButtonGlyph(Control
);
182 NumGlyphs
:= ButtonGlyph
.FNumGlyphs
;
184 if (State
= bsDown
) and (NumGlyphs
< 3) then State
:= bsUp
;
185 Result
:= ButtonGlyph
.FIndexs
[State
];
186 if (Result
= -1) then begin
187 UpdateInternalGlyphList(Control
);
188 Result
:= ButtonGlyph
.FIndexs
[State
];
192 procedure TButtonGlyph_DrawButtonGlyph(Control
: TControl
; Canvas
: TCanvas
; const GlyphPos
: TPoint
;
193 State
: TButtonState
; Transparent
: Boolean);
195 ButtonGlyph
: THackButtonGlyph
;
197 GlyphList
: TImageList
;
200 Details
: TThemedElementDetails
;
202 Button
: TThemedButton
;
205 ButtonGlyph
:= GetButtonGlyph(Control
);
206 Glyph
:= ButtonGlyph
.FOriginal
;
207 GlyphList
:= ButtonGlyph
.FGlyphList
;
208 if Glyph
= nil then Exit
;
209 if (Glyph
.Width
= 0) or (Glyph
.Height
= 0) then Exit
;
210 Index
:= TButtonGlyph_CreateButtonGlyph(Control
, State
);
213 if ThemeServices
.ThemesEnabled
then begin
214 R
.TopLeft
:= GlyphPos
;
215 R
.Right
:= R
.Left
+ Glyph
.Width
div ButtonGlyph
.FNumGlyphs
;
216 R
.Bottom
:= R
.Top
+ Glyph
.Height
;
219 Button
:= tbPushButtonDisabled
;
222 Button
:= tbPushButtonPressed
;
225 Button
:= tbPushButtonNormal
;
227 Details
:= ThemeServices
.GetElementDetails(Button
);
228 ThemeServices
.DrawIcon(Canvas
.Handle
, Details
, R
, GlyphList
.Handle
, Index
);
231 if Transparent
or (State
= bsExclusive
) then
232 ImageList_DrawEx(GlyphList
.Handle
, Index
, Canvas
.Handle
, X
, Y
, 0, 0,
233 clNone
, clNone
, ILD_Transparent
)
235 ImageList_DrawEx(GlyphList
.Handle
, Index
, Canvas
.Handle
, X
, Y
, 0, 0,
236 ColorToRGB(clBtnFace
), clNone
, ILD_Normal
);
239 procedure TButtonGlyph_DrawButtonText(Canvas
: TCanvas
; const Caption
: WideString
;
240 TextBounds
: TRect
; State
: TButtonState
;
241 BiDiFlags
: LongInt {$IFDEF COMPILER_7_UP}; WordWrap
: Boolean {$ENDIF});
245 Brush
.Style
:= bsClear
;
246 if State
= bsDisabled
then
248 OffsetRect(TextBounds
, 1, 1);
249 Font
.Color
:= clBtnHighlight
;
251 {$IFDEF COMPILER_7_UP}
253 Tnt_DrawTextW(Handle
, PWideChar(Caption
), Length(Caption
), TextBounds
,
254 DT_CENTER
or DT_VCENTER
or BiDiFlags
or DT_WORDBREAK
)
257 Tnt_DrawTextW(Handle
, PWideChar(Caption
), Length(Caption
), TextBounds
,
258 DT_CENTER
or DT_VCENTER
or BiDiFlags
);
260 OffsetRect(TextBounds
, -1, -1);
261 Font
.Color
:= clBtnShadow
;
263 {$IFDEF COMPILER_7_UP}
265 Tnt_DrawTextW(Handle
, PWideChar(Caption
), Length(Caption
), TextBounds
,
266 DT_CENTER
or DT_WORDBREAK
or BiDiFlags
) { TODO: Figure out why DT_VCENTER is not used }
269 Tnt_DrawTextW(Handle
, PWideChar(Caption
), Length(Caption
), TextBounds
,
270 DT_CENTER
or DT_VCENTER
or BiDiFlags
);
274 {$IFDEF COMPILER_7_UP}
276 Tnt_DrawTextW(Handle
, PWideChar(Caption
), Length(Caption
), TextBounds
,
277 DT_CENTER
or DT_WORDBREAK
or BiDiFlags
) { TODO: Figure out why DT_VCENTER is not used }
280 Tnt_DrawTextW(Handle
, PWideChar(Caption
), Length(Caption
), TextBounds
,
281 DT_CENTER
or DT_VCENTER
or BiDiFlags
);
286 procedure TButtonGlyph_CalcButtonLayout(Control
: TControl
; DC
: HDC
; const Client
: TRect
;
287 const Offset
: TPoint
; const Caption
: WideString
; Layout
: TButtonLayout
;
288 Margin
, Spacing
: Integer; var GlyphPos
: TPoint
; var TextBounds
: TRect
;
289 BiDiFlags
: Integer {$IFDEF COMPILER_7_UP}; WordWrap
: Boolean {$ENDIF});
298 ButtonGlyph
: THackButtonGlyph
;
300 ButtonGlyph
:= GetButtonGlyph(Control
);
301 Glyph
:= ButtonGlyph
.FOriginal
;
302 NumGlyphs
:= ButtonGlyph
.FNumGlyphs
;
304 if (BiDiFlags
and DT_RIGHT
) = DT_RIGHT
then
305 if Layout
= blGlyphLeft
then
306 Layout
:= blGlyphRight
308 if Layout
= blGlyphRight
then
309 Layout
:= blGlyphLeft
;
311 // Calculate the item sizes.
312 ClientSize
:= Point(Client
.Right
- Client
.Left
, Client
.Bottom
- Client
.Top
);
314 if Assigned(Glyph
) then
315 GlyphSize
:= Point(Glyph
.Width
div NumGlyphs
, Glyph
.Height
)
317 GlyphSize
:= Point(0, 0);
319 if Length(Caption
) > 0 then
321 {$IFDEF COMPILER_7_UP}
322 TextBounds
:= Rect(0, 0, Client
.Right
- Client
.Left
- GlyphSize
.X
- 3, 0); { TODO: Figure out why GlyphSize.X is in here. }
324 TextBounds
:= Rect(0, 0, Client
.Right
- Client
.Left
, 0);
327 {$IFDEF COMPILER_7_UP}
329 Tnt_DrawTextW(DC
, PWideChar(Caption
), Length(Caption
), TextBounds
, DT_WORDBREAK
330 or DT_CALCRECT
or BiDiFlags
)
333 Tnt_DrawTextW(DC
, PWideChar(Caption
), Length(Caption
), TextBounds
, DT_CALCRECT
or BiDiFlags
);
335 TextSize
:= Point(TextBounds
.Right
- TextBounds
.Left
, TextBounds
.Bottom
- TextBounds
.Top
);
339 TextBounds
:= Rect(0, 0, 0, 0);
340 TextSize
:= Point(0, 0);
343 // If the layout has the glyph on the right or the left, then both the text and the glyph are centered vertically.
344 // If the glyph is on the top or the bottom, then both the text and the glyph are centered horizontally.
345 if Layout
in [blGlyphLeft
, blGlyphRight
] then
347 GlyphPos
.Y
:= (ClientSize
.Y
- GlyphSize
.Y
+ 1) div 2;
348 TextPos
.Y
:= (ClientSize
.Y
- TextSize
.Y
+ 1) div 2;
352 GlyphPos
.X
:= (ClientSize
.X
- GlyphSize
.X
+ 1) div 2;
353 TextPos
.X
:= (ClientSize
.X
- TextSize
.X
+ 1) div 2;
356 // If there is no text or no bitmap, then Spacing is irrelevant.
357 if (TextSize
.X
= 0) or (GlyphSize
.X
= 0) then
360 // Adjust Margin and Spacing.
365 TotalSize
:= Point(GlyphSize
.X
+ TextSize
.X
, GlyphSize
.Y
+ TextSize
.Y
);
366 if Layout
in [blGlyphLeft
, blGlyphRight
] then
367 Margin
:= (ClientSize
.X
- TotalSize
.X
) div 3
369 Margin
:= (ClientSize
.Y
- TotalSize
.Y
) div 3;
374 TotalSize
:= Point(GlyphSize
.X
+ Spacing
+ TextSize
.X
, GlyphSize
.Y
+ Spacing
+ TextSize
.Y
);
375 if Layout
in [blGlyphLeft
, blGlyphRight
] then
376 Margin
:= (ClientSize
.X
- TotalSize
.X
+ 1) div 2
378 Margin
:= (ClientSize
.Y
- TotalSize
.Y
+ 1) div 2;
385 TotalSize
:= Point(ClientSize
.X
- (Margin
+ GlyphSize
.X
), ClientSize
.Y
- (Margin
+ GlyphSize
.Y
));
386 if Layout
in [blGlyphLeft
, blGlyphRight
] then
387 Spacing
:= (TotalSize
.X
- TextSize
.X
) div 2
389 Spacing
:= (TotalSize
.Y
- TextSize
.Y
) div 2;
396 GlyphPos
.X
:= Margin
;
397 TextPos
.X
:= GlyphPos
.X
+ GlyphSize
.X
+ Spacing
;
401 GlyphPos
.X
:= ClientSize
.X
- Margin
- GlyphSize
.X
;
402 TextPos
.X
:= GlyphPos
.X
- Spacing
- TextSize
.X
;
406 GlyphPos
.Y
:= Margin
;
407 TextPos
.Y
:= GlyphPos
.Y
+ GlyphSize
.Y
+ Spacing
;
411 GlyphPos
.Y
:= ClientSize
.Y
- Margin
- GlyphSize
.Y
;
412 TextPos
.Y
:= GlyphPos
.Y
- Spacing
- TextSize
.Y
;
416 // Fixup the Result variables.
419 Inc(X
, Client
.Left
+ Offset
.X
);
420 Inc(Y
, Client
.Top
+ Offset
.Y
);
424 { Themed text is not shifted, but gets a different color. }
425 if ThemeServices
.ThemesEnabled
then
426 OffsetRect(TextBounds
, TextPos
.X
+ Client
.Left
, TextPos
.Y
+ Client
.Top
)
429 OffsetRect(TextBounds
, TextPos
.X
+ Client
.Left
+ Offset
.X
, TextPos
.Y
+ Client
.Top
+ Offset
.Y
);
432 function TButtonGlyph_Draw(Control
: TControl
; Canvas
: TCanvas
; const Client
: TRect
;
433 const Offset
: TPoint
; const Caption
: WideString
; Layout
: TButtonLayout
; Margin
: Integer;
434 Spacing
: Integer; State
: TButtonState
; Transparent
: Boolean;
435 BiDiFlags
: Longint {$IFDEF COMPILER_7_UP}; WordWrap
: Boolean {$ENDIF}): TRect
;
439 TButtonGlyph_CalcButtonLayout(Control
, Canvas
.Handle
, Client
, Offset
, Caption
, Layout
, Margin
,
440 Spacing
, GlyphPos
, Result
, BiDiFlags
{$IFDEF COMPILER_7_UP}, WordWrap
{$ENDIF});
441 TButtonGlyph_DrawButtonGlyph(Control
, Canvas
, GlyphPos
, State
, Transparent
);
442 TButtonGlyph_DrawButtonText(Canvas
, Caption
, Result
, State
,
443 BiDiFlags
{$IFDEF COMPILER_7_UP}, WordWrap
{$ENDIF});
448 procedure TTntSpeedButton
.DefineProperties(Filer
: TFiler
);
451 TntPersistent_AfterInherited_DefineProperties(Filer
, Self
);
454 function TTntSpeedButton
.IsCaptionStored
: Boolean;
456 Result
:= TntControl_IsCaptionStored(Self
)
459 function TTntSpeedButton
.GetCaption
: TWideCaption
;
461 Result
:= TntControl_GetText(Self
);
464 procedure TTntSpeedButton
.SetCaption(const Value
: TWideCaption
);
466 TntControl_SetText(Self
, Value
);
469 function TTntSpeedButton
.IsHintStored
: Boolean;
471 Result
:= TntControl_IsHintStored(Self
)
474 function TTntSpeedButton
.GetHint
: WideString
;
476 Result
:= TntControl_GetHint(Self
)
479 procedure TTntSpeedButton
.SetHint(const Value
: WideString
);
481 TntControl_SetHint(Self
, Value
);
484 procedure TTntSpeedButton
.CMHintShow(var Message: TMessage
);
486 ProcessCMHintShowMsg(Message);
490 procedure TTntSpeedButton
.CMDialogChar(var Message: TCMDialogChar
);
493 if IsWideCharAccel(CharCode
, Caption
) and Enabled
and Visible
and
494 (Parent
<> nil) and Parent
.Showing
then
502 function TTntSpeedButton
.GetButtonGlyph
: Pointer;
504 Result
:= THackSpeedButton(Self
).FGlyph
;
507 procedure TTntSpeedButton
.UpdateInternalGlyphList
;
509 FPaintInherited
:= True;
513 FPaintInherited
:= False;
516 raise EAbortPaint
.Create('');
519 procedure TTntSpeedButton
.Paint
;
521 if FPaintInherited
then
527 procedure TTntSpeedButton
.PaintButton
;
529 DownStyles
: array[Boolean] of Integer = (BDR_RAISEDINNER
, BDR_SUNKENOUTER
);
530 FillStyles
: array[Boolean] of Integer = (BF_MIDDLE
, 0);
536 Button
: TThemedButton
;
537 ToolButton
: TThemedToolBar
;
538 Details
: TThemedElementDetails
;
544 FState
:= bsDisabled
;
545 THackSpeedButton(Self
).FDragging
:= False;
547 else if FState
= bsDisabled
then
548 if Down
and (GroupIndex
<> 0) then
549 FState
:= bsExclusive
552 Canvas
.Font
:= Self
.Font
;
555 if ThemeServices
.ThemesEnabled
then
557 {$IFDEF COMPILER_7_UP}
558 PerformEraseBackground(Self
, Canvas
.Handle
);
560 SelectObject(Canvas
.Handle
, Canvas
.Font
.Handle
); { For some reason, PerformEraseBackground sometimes messes the font up. }
563 Button
:= tbPushButtonDisabled
565 if FState
in [bsDown
, bsExclusive
] then
566 Button
:= tbPushButtonPressed
568 if MouseInControl
then
569 Button
:= tbPushButtonHot
571 Button
:= tbPushButtonNormal
;
573 ToolButton
:= ttbToolbarDontCare
;
577 tbPushButtonDisabled
:
578 Toolbutton
:= ttbButtonDisabled
;
580 Toolbutton
:= ttbButtonPressed
;
582 Toolbutton
:= ttbButtonHot
;
584 Toolbutton
:= ttbButtonNormal
;
588 PaintRect
:= ClientRect
;
589 if ToolButton
= ttbToolbarDontCare
then
591 Details
:= ThemeServices
.GetElementDetails(Button
);
592 ThemeServices
.DrawElement(Canvas
.Handle
, Details
, PaintRect
);
593 PaintRect
:= ThemeServices
.ContentRect(Canvas
.Handle
, Details
, PaintRect
);
597 Details
:= ThemeServices
.GetElementDetails(ToolButton
);
598 ThemeServices
.DrawElement(Canvas
.Handle
, Details
, PaintRect
);
599 PaintRect
:= ThemeServices
.ContentRect(Canvas
.Handle
, Details
, PaintRect
);
602 if Button
= tbPushButtonPressed
then
604 // A pressed speed button has a white text. This applies however only to flat buttons.
605 if ToolButton
<> ttbToolbarDontCare
then
606 Canvas
.Font
.Color
:= clHighlightText
;
607 Offset
:= Point(1, 0);
610 Offset
:= Point(0, 0);
611 TButtonGlyph_Draw(Self
, Canvas
, PaintRect
, Offset
, Caption
, Layout
, Margin
, Spacing
, FState
,
612 Transparent
, DrawTextBiDiModeFlags(0) {$IFDEF COMPILER_7_UP}, False {$ENDIF});
617 PaintRect
:= Rect(0, 0, Width
, Height
);
620 DrawFlags
:= DFCS_BUTTONPUSH
or DFCS_ADJUSTRECT
;
621 if FState
in [bsDown
, bsExclusive
] then
622 DrawFlags
:= DrawFlags
or DFCS_PUSHED
;
623 DrawFrameControl(Canvas
.Handle
, PaintRect
, DFC_BUTTON
, DrawFlags
);
627 if (FState
in [bsDown
, bsExclusive
]) or
628 (MouseInControl
and (FState
<> bsDisabled
)) or
629 (csDesigning
in ComponentState
) then
630 DrawEdge(Canvas
.Handle
, PaintRect
, DownStyles
[FState
in [bsDown
, bsExclusive
]],
631 FillStyles
[Transparent
] or BF_RECT
)
632 else if not Transparent
then
634 Canvas
.Brush
.Color
:= Color
;
635 Canvas
.FillRect(PaintRect
);
637 InflateRect(PaintRect
, -1, -1);
639 if FState
in [bsDown
, bsExclusive
] then
641 if (FState
= bsExclusive
) and (not Flat
or not MouseInControl
) then
643 Canvas
.Brush
.Bitmap
:= AllocPatternBitmap(clBtnFace
, clBtnHighlight
);
644 Canvas
.FillRect(PaintRect
);
654 TButtonGlyph_Draw(Self
, Canvas
, PaintRect
, Offset
, Caption
,
655 Layout
, Margin
, Spacing
, FState
, Transparent
,
656 DrawTextBiDiModeFlags(0) {$IFDEF COMPILER_7_UP}, False {$ENDIF});
666 function TTntSpeedButton
.GetActionLinkClass
: TControlActionLinkClass
;
668 Result
:= TntControl_GetActionLinkClass(Self
, inherited GetActionLinkClass
);
671 {$IFDEF COMPILER_10_UP}
673 TAccessGraphicControl
= class(TGraphicControl
);
676 procedure TTntSpeedButton
.ActionChange(Sender
: TObject
; CheckDefaults
: Boolean);
677 {$IFDEF COMPILER_10_UP}
678 // bug fix for VCL where ImageIndex on Action ALWAYS overrides the Glyph.
680 CallActionChange
= procedure(Sender
: TObject
; CheckDefaults
: Boolean) of object;
685 TntControl_BeforeInherited_ActionChange(Self
, Sender
, CheckDefaults
);
686 {$IFNDEF COMPILER_10_UP}
689 // call TGraphicControl.ActionChange (bypass TSpeedButton.ActionChange)
690 M
.Code
:= @TAccessGraphicControl
.ActionChange
;
692 CallActionChange(M
)(Sender
, CheckDefaults
);
693 // call Delphi2005's TSpeedButton.ActionChange
694 if Sender
is TCustomAction
{TNT-ALLOW TCustomAction} then
695 with TCustomAction
{TNT-ALLOW TCustomAction}(Sender
) do
697 if CheckDefaults
or (Self
.GroupIndex
= 0) then
698 Self
.GroupIndex
:= GroupIndex
;
699 { Copy image from action's imagelist }
700 if (Glyph
.Empty
) and (ActionList
<> nil) and (ActionList
.Images
<> nil) and
701 (ImageIndex
>= 0) and (ImageIndex
< ActionList
.Images
.Count
) then
702 CopyImage(ActionList
.Images
, ImageIndex
);
709 procedure TTntBitBtn
.CreateWindowHandle(const Params
: TCreateParams
);
711 CreateUnicodeHandle(Self
, Params
, 'BUTTON');
714 procedure TTntBitBtn
.DefineProperties(Filer
: TFiler
);
717 TntPersistent_AfterInherited_DefineProperties(Filer
, Self
);
720 function TTntBitBtn
.IsCaptionStored
: Boolean;
725 Assert(Self
is TButton
{TNT-ALLOW TButton});
726 Assert(Self
is TBitBtn
{TNT-ALLOW TBitBtn});
727 if Kind
= bkCustom
then
728 // don't use TBitBtn, it's broken for Kind <> bkCustom
729 BaseClass
:= TButton
{TNT-ALLOW TButton}
731 //TBitBtn has it's own storage specifier, based upon the button kind
732 BaseClass
:= TBitBtn
{TNT-ALLOW TBitBtn};
734 PropInfo
:= GetPropInfo(BaseClass
, 'Caption');
735 if PropInfo
= nil then
736 raise EPropertyError
.CreateResFmt(PResStringRec(@SUnknownProperty
), ['Caption']);
737 Result
:= IsStoredProp(Self
, PropInfo
);
740 function TTntBitBtn
.GetCaption
: TWideCaption
;
742 Result
:= TntControl_GetText(Self
)
745 procedure TTntBitBtn
.SetCaption(const Value
: TWideCaption
);
747 TntControl_SetText(Self
, Value
);
750 function TTntBitBtn
.IsHintStored
: Boolean;
752 Result
:= TntControl_IsHintStored(Self
)
755 function TTntBitBtn
.GetHint
: WideString
;
757 Result
:= TntControl_GetHint(Self
)
760 procedure TTntBitBtn
.SetHint(const Value
: WideString
);
762 TntControl_SetHint(Self
, Value
);
765 procedure TTntBitBtn
.CMDialogChar(var Message: TCMDialogChar
);
767 TntButton_CMDialogChar(Self
, Message);
770 function TTntBitBtn
.GetButtonGlyph
: Pointer;
772 Result
:= THackBitBtn(Self
).FGlyph
;
775 procedure TTntBitBtn
.UpdateInternalGlyphList
;
777 FPaintInherited
:= True;
781 FPaintInherited
:= False;
784 raise EAbortPaint
.Create('');
787 procedure TTntBitBtn
.CNDrawItem(var Message: TWMDrawItem
);
789 if FPaintInherited
then
792 DrawItem(Message.DrawItemStruct
^);
795 procedure TTntBitBtn
.DrawItem(const DrawItemStruct
: TDrawItemStruct
);
797 IsDown
, IsDefault
: Boolean;
804 Details
: TThemedElementDetails
;
805 Button
: TThemedButton
;
810 FCanvas
:= THackBitBtn(Self
).FCanvas
;
811 IsFocused
:= THackBitBtn(Self
).IsFocused
;
812 FCanvas
.Handle
:= DrawItemStruct
.hDC
;
815 with DrawItemStruct
do
817 FCanvas
.Handle
:= hDC
;
818 FCanvas
.Font
:= Self
.Font
;
819 IsDown
:= itemState
and ODS_SELECTED
<> 0;
820 IsDefault
:= itemState
and ODS_FOCUS
<> 0;
822 if not Enabled
then State
:= bsDisabled
823 else if IsDown
then State
:= bsDown
828 if ThemeServices
.ThemesEnabled
then
831 Button
:= tbPushButtonDisabled
834 Button
:= tbPushButtonPressed
836 if FMouseInControl
then
837 Button
:= tbPushButtonHot
839 if IsFocused
or IsDefault
then
840 Button
:= tbPushButtonDefaulted
842 Button
:= tbPushButtonNormal
;
844 Details
:= ThemeServices
.GetElementDetails(Button
);
845 // Parent background.
846 ThemeServices
.DrawParentBackground(Handle
, DrawItemStruct
.hDC
, @Details
, True);
848 ThemeServices
.DrawElement(DrawItemStruct
.hDC
, Details
, DrawItemStruct
.rcItem
);
849 R
:= ThemeServices
.ContentRect(FCanvas
.Handle
, Details
, DrawItemStruct
.rcItem
);
851 if Button
= tbPushButtonPressed
then
852 Offset
:= Point(1, 0)
854 Offset
:= Point(0, 0);
855 TButtonGlyph_Draw(Self
, FCanvas
, R
, Offset
, Caption
, Layout
, Margin
, Spacing
, State
, False,
856 DrawTextBiDiModeFlags(0) {$IFDEF COMPILER_7_UP}, Self
.WordWrap
{$ENDIF});
858 if IsFocused
and IsDefault
then
860 FCanvas
.Pen
.Color
:= clWindowFrame
;
861 FCanvas
.Brush
.Color
:= clBtnFace
;
862 DrawFocusRect(FCanvas
.Handle
, R
);
870 Flags
:= DFCS_BUTTONPUSH
or DFCS_ADJUSTRECT
;
871 if IsDown
then Flags
:= Flags
or DFCS_PUSHED
;
872 if DrawItemStruct
.itemState
and ODS_DISABLED
<> 0 then
873 Flags
:= Flags
or DFCS_INACTIVE
;
875 { DrawFrameControl doesn't allow for drawing a button as the
876 default button, so it must be done here. }
877 if IsFocused
or IsDefault
then
879 FCanvas
.Pen
.Color
:= clWindowFrame
;
880 FCanvas
.Pen
.Width
:= 1;
881 FCanvas
.Brush
.Style
:= bsClear
;
882 FCanvas
.Rectangle(R
.Left
, R
.Top
, R
.Right
, R
.Bottom
);
884 { DrawFrameControl must draw within this border }
885 InflateRect(R
, -1, -1);
888 { DrawFrameControl does not draw a pressed button correctly }
891 FCanvas
.Pen
.Color
:= clBtnShadow
;
892 FCanvas
.Pen
.Width
:= 1;
893 FCanvas
.Brush
.Color
:= clBtnFace
;
894 FCanvas
.Rectangle(R
.Left
, R
.Top
, R
.Right
, R
.Bottom
);
895 InflateRect(R
, -1, -1);
898 DrawFrameControl(DrawItemStruct
.hDC
, R
, DFC_BUTTON
, Flags
);
903 InflateRect(R
, -1, -1);
906 FCanvas
.Font
:= Self
.Font
;
910 TButtonGlyph_Draw(Self
, FCanvas
, R
, Point(0, 0), Caption
, Layout
, Margin
, Spacing
, State
,
911 False, DrawTextBiDiModeFlags(0) {$IFDEF COMPILER_7_UP}, Self
.WordWrap
{$ENDIF});
913 if IsFocused
and IsDefault
then
916 InflateRect(R
, -4, -4);
917 FCanvas
.Pen
.Color
:= clWindowFrame
;
918 FCanvas
.Brush
.Color
:= clBtnFace
;
919 DrawFocusRect(FCanvas
.Handle
, R
);
931 procedure TTntBitBtn
.CMMouseEnter(var Message: TMessage
);
933 FMouseInControl
:= True;
937 procedure TTntBitBtn
.CMMouseLeave(var Message: TMessage
);
939 FMouseInControl
:= False;
943 {$IFDEF COMPILER_10_UP}
945 TAccessButton
= class(TButton
{TNT-ALLOW TButton});
948 procedure TTntBitBtn
.ActionChange(Sender
: TObject
; CheckDefaults
: Boolean);
949 {$IFDEF COMPILER_10_UP}
950 // bug fix for VCL where ImageIndex on Action ALWAYS overrides the Glyph.
952 CallActionChange
= procedure(Sender
: TObject
; CheckDefaults
: Boolean) of object;
957 TntControl_BeforeInherited_ActionChange(Self
, Sender
, CheckDefaults
);
958 {$IFNDEF COMPILER_10_UP}
961 // call TButton.ActionChange (bypass TBitBtn.ActionChange)
962 M
.Code
:= @TAccessButton
.ActionChange
;
964 CallActionChange(M
)(Sender
, CheckDefaults
);
965 // call Delphi2005's TBitBtn.ActionChange
966 if Sender
is TCustomAction
{TNT-ALLOW TCustomAction} then
967 with TCustomAction
{TNT-ALLOW TCustomAction}(Sender
) do
969 { Copy image from action's imagelist }
970 if (Glyph
.Empty
) and (ActionList
<> nil) and (ActionList
.Images
<> nil) and
971 (ImageIndex
>= 0) and (ImageIndex
< ActionList
.Images
.Count
) then
972 CopyImage(ActionList
.Images
, ImageIndex
);
977 function TTntBitBtn
.GetActionLinkClass
: TControlActionLinkClass
;
979 Result
:= TntControl_GetActionLinkClass(Self
, inherited GetActionLinkClass
);