Skip to content

Commit 6f37995

Browse files
26 Maj 2026 - version 4.2.0
- Fixed TaskDialog component in Delphi 13.1 - Fixed TStyledButton: now reacts to form.StyleName changes - Fixed WM_PAINT cascade on style change (ApplyButtonStyle skip-invalidate when called from paint; all attribute groups assigned in one pass).
1 parent d60ada3 commit 6f37995

7 files changed

Lines changed: 104 additions & 52 deletions

README.htm

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
</style>
3232
<h1>Delphi VCL StyledComponents <a href="https://opensource.org/licenses/Apache-2.0"><img src="https://img.shields.io/badge/License-Apache%202.0-yellowgreen.svg" alt="License"/></a></h1>
3333
<h2>Components similar to Delphi VCL Buttons, Panels, Toolbar, DbNavigator, BindNavigator, ButtonGroup and CategoryButtons with Custom Graphic Styles, and an advanced, full-customizable TaskDialog, also with animations!</h2>
34-
<h3>Actual official version: 4.1.1</h3>
34+
<h3>Actual official version: 4.2.0</h3>
3535
<hr />
3636
<h2>New Setup for Installation of Components</h2>
3737
<p>From 3.8.1 version a new &ldquo;Installer&rdquo; read-to-use is located in the Release area: <a href="https://github.com/EtheaDev/StyledComponents/releases/latest/download/StyledComponents_Setup.exe">Download the Installer</a>.</p>
@@ -332,7 +332,7 @@ <h2>How to change Dialogs attributes (Font/Buttons Style)</h2>
332332
<p><ins><em>Confirmation Dialog with custom font/size and English buttons</em></ins></p>
333333
<p><img src="./Images/ConfirmationDialog.jpg" alt="ConfirmationDialog.jpg"/></p>
334334
<p><ins><em>Warning Dialog with italians Captions in AcquaGraphite Style</em></ins></p>
335-
<p>To activate button captions is to change StyledComponents.inc file and activate {$Define ItaMessages}</p>
335+
<p>To change language of button captions (for example in italian) you must change StyledComponents.inc file and activate: <code>{$Define ItaMessages}</code></p>
336336
<p><img src="./Images/WarningDialog.jpg" alt="StyledButtonDemo.jpg"/></p>
337337
<p><ins><em>Error Dialog in Windows10 Vcl Style</em></ins></p>
338338
<p><img src="./Images/ErrorDialog.jpg" alt="StyledButtonDemo.jpg"/></p>
@@ -348,6 +348,12 @@ <h3>Available from Delphi XE6 to Delphi 13 (32bit and 64bit platforms)</h3>
348348
<p><img src="./Images/SupportingDelphi.jpg" alt="Delphi Support"/></p>
349349
<p>Related links: <a href="https://www.embarcadero.com">embarcadero.com</a> - <a href="https://learndelphi.org">learndelphi.org</a></p>
350350
<h3>RELEASE NOTES</h3>
351+
<p>26 Maj 2026 - version 4.2.0</p>
352+
<ul>
353+
<li>Fixed TaskDialog component in Delphi 13.1</li>
354+
<li>Fixed TStyledButton: now reacts to form.StyleName changes</li>
355+
<li>Fixed WM_PAINT cascade on style change (ApplyButtonStyle skip-invalidate when called from paint; all attribute groups assigned in one pass).</li>
356+
</ul>
351357
<p>22 Apr 2026 - version 4.1.1</p>
352358
<ul>
353359
<li>Fixed Owner of TaskDialog form</li>

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Components similar to Delphi VCL Buttons, Panels, Toolbar, DbNavigator, BindNavigator, ButtonGroup and CategoryButtons with Custom Graphic Styles, and an advanced, full-customizable TaskDialog, also with animations!
44

5-
### Actual official version: 4.1.1
5+
### Actual official version: 4.2.0
66

77
---
88
## New Setup for Installation of Components
@@ -366,7 +366,7 @@ The main form is useful to test every format / buttons and type of dialogs.
366366

367367
++*Warning Dialog with italians Captions in AcquaGraphite Style*++
368368

369-
To activate button captions is to change StyledComponents.inc file and activate {$Define ItaMessages}
369+
To change language of button captions (for example in italian) you must change StyledComponents.inc file and activate: `{$Define ItaMessages}`
370370

371371
![StyledButtonDemo.jpg](./Images/WarningDialog.jpg)
372372

@@ -397,6 +397,11 @@ If you are have Skia4Delphi installed, you can also try the AnimatedTaskDialogDe
397397
Related links: [embarcadero.com](https://www.embarcadero.com) - [learndelphi.org](https://learndelphi.org)
398398

399399
### RELEASE NOTES
400+
26 Maj 2026 - version 4.2.0
401+
- Fixed TaskDialog component in Delphi 13.1
402+
- Fixed TStyledButton: now reacts to form.StyleName changes
403+
- Fixed WM_PAINT cascade on style change (ApplyButtonStyle skip-invalidate when called from paint; all attribute groups assigned in one pass).
404+
400405
22 Apr 2026 - version 4.1.1
401406
- Fixed Owner of TaskDialog form
402407
- Fixed sound for TaskMessageDlg using mtConfirmation

source/Vcl.ButtonStylesAttributes.pas

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ interface
5656

5757
const
5858
/// <summary>Current version of the StyledComponents library</summary>
59-
StyledComponentsVersion = '4.1.1';
59+
StyledComponentsVersion = '4.2.0';
6060
/// <summary>Default corner radius for rounded buttons in pixels</summary>
6161
DEFAULT_RADIUS = 6;
6262
/// <summary>Resource name for the Windows shield admin icon</summary>
@@ -545,12 +545,12 @@ function StyleFamilyCheckAttributes(
545545
out AButtonFamily: TButtonFamily): Boolean;
546546

547547
/// <summary>Updates button attributes for all states based on family/class/appearance</summary>
548-
procedure StyleFamilyUpdateAttributes(
548+
function StyleFamilyUpdateAttributes(
549549
const AFamily: TStyledButtonFamily;
550550
var AClass: TStyledButtonClass;
551551
var AAppearance: TStyledButtonAppearance;
552552
var ANormalStyle, APressedStyle,
553-
ASelectedStyle, AHotStyle, ADisabledStyle: TStyledButtonAttributes);
553+
ASelectedStyle, AHotStyle, ADisabledStyle: TStyledButtonAttributes): Boolean;
554554

555555
/// <summary>Gets appropriate style class and appearance for a modal result</summary>
556556
/// <remarks>
@@ -578,6 +578,9 @@ implementation
578578
var
579579
_WindowsVersion: TWindowsVersion;
580580

581+
function GetButtonFamily(const AFamily: TStyledButtonFamily;
582+
out AButtonFamily: TButtonFamily): Boolean; forward;
583+
581584
procedure CheckValue(const AName: string; const AValue, AMin, AMax: Integer);
582585
begin
583586
if (AValue < AMin) or (AValue > AMax) then
@@ -700,31 +703,35 @@ procedure CloneButtonStyle(
700703
end;
701704

702705
function GetActiveStyleName(const AControl: TControl): string;
706+
{$IFDEF D10_4+}
707+
var
708+
LServices: TCustomStyleServices;
709+
{$ENDIF}
703710
begin
704-
{$IFDEF D10_4+}
705-
Result := AControl.GetStyleName;
711+
{$IFDEF D11+}
712+
//Vcl.Themes.StyleServices(AControl) resolves the effective style for the specific control: it walks the parent chain to honor an inherited
713+
LServices := StyleServices(AControl);
714+
if Assigned(LServices) then
715+
Result := LServices.Name
716+
else
717+
Result := '';
706718
if Result = '' then
707719
begin
708-
{$IFDEF D11+}
709720
if (csDesigning in AControl.ComponentState) then
710721
Result := TStyleManager.ActiveDesigningStyle.Name
711722
else
712723
Result := TStyleManager.ActiveStyle.Name;
713-
{$ELSE}
714-
Result := TStyleManager.ActiveStyle.Name;
715-
{$ENDIF}
716724
end;
717725
{$ELSE}
718726
Result := TStyleManager.ActiveStyle.Name;
719727
{$ENDIF}
720-
if (csDesigning in AControl.ComponentState) then
721-
begin
722-
if (Result = 'Windows Designer Dark') or
723-
(Result = 'Win10IDE_Dark') or
724-
(Result = 'Win10IDE_Light') or
725-
(Result = 'Mountain_Mist' ) then
726-
Result := 'Windows';
727-
end;
728+
if (Result = '') or
729+
(Result = 'Windows Designer Dark') or
730+
(Result = 'Windows Designer Modern Dark') or
731+
(Result = 'Win10IDE_Dark') or
732+
(Result = 'Win10IDE_Light') or
733+
(Result = 'Mountain_Mist' ) then
734+
Result := 'Windows';
728735
end;
729736

730737
function GetWindowsVersion: TWindowsVersion;
@@ -940,16 +947,17 @@ function StyleFamilyCheckAttributes(
940947
end;
941948
end;
942949

943-
procedure StyleFamilyUpdateAttributes(
950+
function StyleFamilyUpdateAttributes(
944951
const AFamily: TStyledButtonFamily;
945952
var AClass: TStyledButtonClass;
946953
var AAppearance: TStyledButtonAppearance;
947954
var ANormalStyle, APressedStyle,
948-
ASelectedStyle, AHotStyle, ADisabledStyle: TStyledButtonAttributes);
955+
ASelectedStyle, AHotStyle, ADisabledStyle: TStyledButtonAttributes): Boolean;
949956
var
950957
LButtonFamily: TButtonFamily;
951958
LNormalStyle, LPressedStyle, LSelectedStyle, LHotStyle, LDisabledStyle: TStyledButtonAttributes;
952959
begin
960+
Result := False;
953961
if GetButtonFamily(AFamily, LButtonFamily) then
954962
begin
955963
LNormalStyle := TStyledButtonAttributes.Create(nil);
@@ -963,11 +971,11 @@ procedure StyleFamilyUpdateAttributes(
963971
LNormalStyle, LPressedStyle, LSelectedStyle,
964972
LHotStyle, LDisabledStyle);
965973

966-
ANormalStyle.AssignStyledAttributes(LNormalStyle);
967-
APressedStyle.AssignStyledAttributes(LPressedStyle);
968-
ASelectedStyle.AssignStyledAttributes(LSelectedStyle);
969-
AHotStyle.AssignStyledAttributes(LHotStyle);
970-
ADisabledStyle.AssignStyledAttributes(LDisabledStyle);
974+
if ANormalStyle.AssignStyledAttributes(LNormalStyle) then Result := True;
975+
if APressedStyle.AssignStyledAttributes(LPressedStyle) then Result := True;
976+
if ASelectedStyle.AssignStyledAttributes(LSelectedStyle) then Result := True;
977+
if AHotStyle.AssignStyledAttributes(LHotStyle) then Result := True;
978+
if ADisabledStyle.AssignStyledAttributes(LDisabledStyle) then Result := True;
971979
finally
972980
LNormalStyle.Free;
973981
LPressedStyle.Free;
@@ -1284,17 +1292,30 @@ function TStyledButtonAttributes.AssignStyledAttributes(
12841292
const ASource: TStyledButtonAttributes): Boolean;
12851293
begin
12861294
//Assign internal variable
1287-
FDrawType := ASource.FDrawType;
1288-
FBorderWidth := ASource.FBorderWidth;
1289-
FBorderDrawStyle := ASource.FBorderDrawStyle;
1290-
FButtonDrawStyle := ASource.FButtonDrawStyle;
1291-
FBorderColor := ASource.FBorderColor;
1292-
FFontColor := ASource.FFontColor;
1293-
FFontStyle := ASource.FFontStyle;
1294-
FButtonColor := ASource.FButtonColor;
1295-
FRadius := ASource.FRadius;
1296-
FRoundedCorners := ASource.FRoundedCorners;
1297-
Result := True;
1295+
Result :=
1296+
(FDrawType <> ASource.FDrawType) or
1297+
(FBorderWidth <> ASource.FBorderWidth) or
1298+
(FBorderDrawStyle <> ASource.FBorderDrawStyle) or
1299+
(FButtonDrawStyle <> ASource.FButtonDrawStyle) or
1300+
(FBorderColor <> ASource.FBorderColor) or
1301+
(FFontColor <> ASource.FFontColor) or
1302+
(FFontStyle <> ASource.FFontStyle) or
1303+
(FButtonColor <> ASource.FButtonColor) or
1304+
(FRadius <> ASource.FRadius) or
1305+
(FRoundedCorners <> ASource.FRoundedCorners);
1306+
if Result then
1307+
begin
1308+
FDrawType := ASource.FDrawType;
1309+
FBorderWidth := ASource.FBorderWidth;
1310+
FBorderDrawStyle := ASource.FBorderDrawStyle;
1311+
FButtonDrawStyle := ASource.FButtonDrawStyle;
1312+
FBorderColor := ASource.FBorderColor;
1313+
FFontColor := ASource.FFontColor;
1314+
FFontStyle := ASource.FFontStyle;
1315+
FButtonColor := ASource.FButtonColor;
1316+
FRadius := ASource.FRadius;
1317+
FRoundedCorners := ASource.FRoundedCorners;
1318+
end;
12981319
end;
12991320

13001321
function TStyledButtonAttributes.BrushStyle: TBrushStyle;

source/Vcl.StandardButtonStyles.pas

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ procedure InitDefaultThemesAttributes;
732732
RegisterThemeAttributes('Windows Modern SlateGray',ttDark,clWhite,clWhite,
733733
htmlToColor('#2a353b'),htmlToColor('#2a353b'),htmlToColor('#7daca8'),
734734
htmlToColor('#2a353b'),htmlToColor('#7daca8'),btRoundRect);
735-
RegisterThemeAttributes('Windows Modern MountainMist',ttDark,clBlack,clBlack,
735+
RegisterThemeAttributes('Windows Modern MountainMist',ttLight,clBlack,clBlack,
736736
htmlToColor('#dadada'),htmlToColor('#dadada'),htmlToColor('#e1edf6'),
737737
htmlToColor('#b4b4b4'),htmlToColor('#3a93dd'),btRoundRect);
738738

@@ -812,9 +812,21 @@ procedure InitDefaultThemesAttributes;
812812
RegisterThemeAttributes('Win10IDE_Dark',ttDark,clWhite,clWhite,
813813
htmlToColor('#373737'),htmlToColor('#373737'),htmlToColor('#405560'),
814814
htmlToColor('#434343'),htmlToColor('#4ab2e9'),btRoundRect, True);
815+
RegisterThemeAttributes('Windows Designer Dark',ttDark,clWhite,clWhite,
816+
htmlToColor('#373737'),htmlToColor('#373737'),htmlToColor('#405560'),
817+
htmlToColor('#434343'),htmlToColor('#4ab2e9'),btRoundRect, True);
818+
RegisterThemeAttributes('Windows Designer Dark Modern',ttDark,clWhite,clWhite,
819+
htmlToColor('#373737'),htmlToColor('#373737'),htmlToColor('#405560'),
820+
htmlToColor('#434343'),htmlToColor('#4ab2e9'),btRoundRect, True);
815821
RegisterThemeAttributes('Win10IDE_Light',ttLight,clBlack,clBlack,
816822
htmlToColor('#fdfdfd'),htmlToColor('#fdfdfd'),htmlToColor('#eef4f9'),
817823
htmlToColor('#bbbbbb'),htmlToColor('#0067c0'),btRoundRect, True);
824+
RegisterThemeAttributes('Windows Designer Light',ttLight,clBlack,clBlack,
825+
htmlToColor('#fdfdfd'),htmlToColor('#fdfdfd'),htmlToColor('#eef4f9'),
826+
htmlToColor('#bbbbbb'),htmlToColor('#0067c0'),btRoundRect, True);
827+
RegisterThemeAttributes('Windows Designer Light Modern',ttLight,clBlack,clBlack,
828+
htmlToColor('#fdfdfd'),htmlToColor('#fdfdfd'),htmlToColor('#eef4f9'),
829+
htmlToColor('#bbbbbb'),htmlToColor('#0067c0'),btRoundRect, True);
818830
RegisterThemeAttributes('Mountain_Mist',ttLight,clBlack,clBlack,
819831
htmlToColor('#fdfdfd'),htmlToColor('#fdfdfd'),htmlToColor('#eef4f9'),
820832
htmlToColor('#bbbbbb'),htmlToColor('#0067c0'),btRoundRect, True);

source/Vcl.StyledButton.pas

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{******************************************************************************}
1+
{******************************************************************************}
22
{ }
33
{ TStyledGraphicButton: a "styled" Button based on TGraphicControl }
44
{ TStyledButton: a "styled" Button Component similar to TButton }
@@ -253,7 +253,7 @@ TStyledButtonRender = class(TObject)
253253
procedure SetStyleFamily(const AValue: TStyledButtonFamily);
254254
procedure SetStyleClass(const AValue: TStyledButtonClass);
255255
procedure SetStyleAppearance(const AValue: TStyledButtonAppearance);
256-
function ApplyButtonStyle: Boolean;
256+
function ApplyButtonStyle(const ASkipInvalidate: Boolean = False): Boolean;
257257

258258
procedure SetDisabledImages(const AValue: TCustomImageList);
259259
procedure SetImages(const AValue: TCustomImageList);
@@ -2315,11 +2315,12 @@ procedure TStyledButtonRender.ActionChange(Sender: TObject; CheckDefaults: Boole
23152315
end;
23162316
end;
23172317

2318-
function TStyledButtonRender.ApplyButtonStyle: Boolean;
2318+
function TStyledButtonRender.ApplyButtonStyle(const ASkipInvalidate: Boolean = False): Boolean;
23192319
var
23202320
LButtonFamily: TButtonFamily;
23212321
LStyleClass: TStyledButtonClass;
23222322
LStyleAppearance: TStyledButtonAppearance;
2323+
LInvaldate: Boolean;
23232324
begin
23242325
if AsVCLStyle then
23252326
begin
@@ -2336,9 +2337,9 @@ function TStyledButtonRender.ApplyButtonStyle: Boolean;
23362337
end;
23372338
Result := StyleFamilyCheckAttributes(FStyleFamily,
23382339
LStyleClass, LStyleAppearance, LButtonFamily);
2339-
if Result (*or (csDesigning in ComponentState)*) then
2340+
if Result then
23402341
begin
2341-
StyleFamilyUpdateAttributes(
2342+
LInvaldate := StyleFamilyUpdateAttributes(
23422343
FStyleFamily,
23432344
LStyleClass,
23442345
LStyleAppearance,
@@ -2353,10 +2354,14 @@ function TStyledButtonRender.ApplyButtonStyle: Boolean;
23532354
end
23542355
else
23552356
begin
2357+
LInvaldate := (FStyleClass <> LStyleClass) or (FStyleAppearance <> LStyleAppearance);
23562358
FStyleClass := LStyleClass;
23572359
FStyleAppearance := LStyleAppearance;
23582360
end;
2359-
if Result then
2361+
//ASkipInvalidate is True when this is called from inside the paint cycle
2362+
//(DrawBackgroundAndBorder), where Invalidate would trigger another WM_PAINT
2363+
//and cause an infinite paint loop.
2364+
if LInvaldate and not ASkipInvalidate then
23602365
Invalidate;
23612366
end;
23622367

@@ -2781,6 +2786,11 @@ procedure TStyledButtonRender.DrawBackgroundAndBorder(
27812786
LCorners: TRoundedCorners;
27822787
LDrawingAutoClick: Boolean;
27832788
begin
2789+
//Call with ASkipInvalidate=True: we are already inside WM_PAINT, the
2790+
//attributes update will be reflected by the current paint pass itself,
2791+
//and an Invalidate here would queue another WM_PAINT → loop.
2792+
if AsVCLStyle then
2793+
ApplyButtonStyle(True);
27842794
LStyleAttribute := GetDrawingStyle(ACanvas, ButtonState);
27852795

27862796
//Erase Background
@@ -6336,7 +6346,7 @@ procedure TCustomStyledButton.SetStyleName(const AValue: string);
63366346
StyleFamily := DEFAULT_CLASSIC_FAMILY;
63376347
inherited;
63386348
if (AValue <> '') then
6339-
StyleClass := AValue;
6349+
StyleClass := AValue;
63406350
end;
63416351
{$ENDIF}
63426352

source/Vcl.StyledTaskDialog.pas

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,7 @@ procedure TStyledTaskDialog.SetUseAnimations(const AValue: Boolean);
12231223
if AValue and not AnimatedTaskDialogFormRegistered then
12241224
raise EStyledTaskDialogException.CreateFmt(
12251225
ERR_DIALOG_FORM_NOT_REGISTERED,
1226-
['Skia.Vcl.StyledTaskDialogAnimatedUnit.pas']);
1226+
['Skia.Vcl.StyledTaskDialogAnimatedUnit']);
12271227
FUseAnimations := AValue;
12281228
end;
12291229
end;

source/Vcl.StyledTaskDialogFormUnit.pas

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{******************************************************************************}
1+
{******************************************************************************}
22
{ }
33
{ StyledTaskDialogForm: a Task Dialog Form with StyleButtons }
44
{ }
@@ -1170,8 +1170,6 @@ procedure TStyledTaskDialogForm.AdjustControlsTopPos;
11701170
begin
11711171
AControl.Top := LTop+1;
11721172
Inc(LTop, AControl.Height);
1173-
// if AControl.AlignWithMargins then
1174-
// Inc(LTop, AControl.Margins.Top + AControl.Margins.Bottom);
11751173
end;
11761174
end;
11771175

@@ -1683,7 +1681,7 @@ function TTaskDialogLauncherHandler.DoExecute(ParentWnd: HWND;
16831681
if not AnimatedTaskDialogFormRegistered then
16841682
raise EStyledTaskDialogException.CreateFmt(
16851683
ERR_DIALOG_FORM_NOT_REGISTERED,
1686-
['Skia.Vcl.StyledTaskDialogAnimatedUnit.pas'])
1684+
['Skia.Vcl.StyledTaskDialogAnimatedUnit'])
16871685
else
16881686
begin
16891687
LForm := _AnimatedTaskDialogFormClass.Create(nil);

0 commit comments

Comments
 (0)