-
Notifications
You must be signed in to change notification settings - Fork 46
Expand file tree
/
Copy pathVcl.StyledTaskDialogFormUnit.pas
More file actions
1750 lines (1609 loc) · 58.7 KB
/
Vcl.StyledTaskDialogFormUnit.pas
File metadata and controls
1750 lines (1609 loc) · 58.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{******************************************************************************}
{ }
{ StyledTaskDialogForm: a Task Dialog Form with StyleButtons }
{ }
{ Copyright (c) 2022-2026 (Ethea S.r.l.) }
{ Author: Carlo Barazzetta }
{ Contributors: }
{ }
{ https://github.com/EtheaDev/StyledComponents }
{ }
{******************************************************************************}
{ }
{ Licensed under the Apache License, Version 2.0 (the "License"); }
{ you may not use this file except in compliance with the License. }
{ You may obtain a copy of the License at }
{ }
{ http://www.apache.org/licenses/LICENSE-2.0 }
{ }
{ Unless required by applicable law or agreed to in writing, software }
{ distributed under the License is distributed on an "AS IS" BASIS, }
{ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. }
{ See the License for the specific language governing permissions and }
{ limitations under the License. }
{ }
{******************************************************************************}
unit Vcl.StyledTaskDialogFormUnit;
interface
{$INCLUDE StyledComponents.inc}
{$WARN SYMBOL_PLATFORM OFF}
uses
Winapi.Windows,
Winapi.Messages,
System.SysUtils,
System.Variants,
System.Classes,
Vcl.Graphics,
Vcl.Controls,
Vcl.ComCtrls,
Vcl.Forms,
Vcl.Dialogs,
Vcl.StdCtrls,
Vcl.ExtCtrls,
Vcl.ImgList,
System.UITypes,
Vcl.StyledButton,
Vcl.StyledTaskDialog,
Vcl.StandardButtonStyles,
Vcl.BootstrapButtonStyles,
Vcl.AngularButtonStyles,
Vcl.ButtonStylesAttributes,
Vcl.ColorButtonStyles,
Vcl.ButtonGroup;
type
/// <summary>Default implementation of ITaskDialogLauncher interface</summary>
/// <remarks>Handles the execution and display of styled task dialogs</remarks>
TTaskDialogLauncherHandler = class(TInterfacedObject, ITaskDialogLauncher)
/// <summary>Executes and displays the task dialog</summary>
/// <param name="ParentWnd">Handle to the parent window</param>
/// <param name="ADialogType">The type of dialog to display</param>
/// <param name="ATaskDialog">The TStyledTaskDialog instance</param>
/// <param name="ADialogBtnFamily">The button style family</param>
/// <returns>True if dialog was executed successfully</returns>
function DoExecute(ParentWnd: HWND;
const ADialogType: TMsgDlgType;
const ATaskDialog: TStyledTaskDialog;
const ADialogBtnFamily: TStyledButtonFamily): Boolean;
end;
/// <summary>Base form class for styled task dialogs</summary>
/// <remarks>
/// TStyledTaskDialogForm is the visual form that displays styled task dialogs.
/// It contains all the UI elements including buttons, icons, text labels,
/// progress bars, radio buttons, and more. Inherit from this class to create
/// custom dialog forms with different visual appearances.
/// </remarks>
TStyledTaskDialogForm = class(TForm)
FooterPanel: TPanel;
ButtonsPanel: TPanel;
ExpandedPanel: TPanel;
VerificationPanel: TPanel;
CommandLinksPanel: TPanel;
CenterPanel: TPanel;
ImagePanel: TPanel;
FooterIconPanel: TPanel;
IconContainer: TPanel;
RadioGroupPanel: TPanel;
MessageScrollBox: TScrollBox;
TitleLabel: TLabel;
TextLabel: TLinkLabel;
AutoSizeLabel: TLabel;
YesButton: TStyledButton;
NoButton: TStyledButton;
OKButton: TStyledButton;
CancelButton: TStyledButton;
AbortButton: TStyledButton;
RetryButton: TStyledButton;
IgnoreButton: TStyledButton;
AllButton: TStyledButton;
NoToAllButton: TStyledButton;
YesToAllButton: TStyledButton;
HelpButton: TStyledButton;
CloseButton: TStyledButton;
FooterTextLabel: TLinkLabel;
VerificationCheckBox: TCheckBox;
ExpandButton: TStyledButton;
ExpandLabel: TLabel;
ProgressBarPanel: TPanel;
InternalProgressBar: TProgressBar;
procedure FormCreate(Sender: TObject);
procedure ButtonClick(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormShow(Sender: TObject);
procedure TextLabelLinkClick(Sender: TObject; const Link: string;
LinkType: TSysLinkType);
procedure FormDestroy(Sender: TObject);
procedure HelpButtonClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure VerificationCheckBoxClick(Sender: TObject);
procedure RadioButtonClick(Sender: TObject);
procedure ExpandButtonClick(Sender: TObject);
private
FFocusedButton: TStyledButton;
FCustomIcons: TStyledDialogIcons;
FTaskDialog: TCustomTaskDialog;
FDialogType: TMsgDlgType;
FButtonsWidth: Integer;
FButtonsHeight: Integer;
FDialogBtnFamily: TStyledButtonFamily;
FDialogBtnDrawType: TStyledButtonDrawType;
FDialogBtnRadius: Integer;
FDialogBtnRoundedCorners: TRoundedCorners;
FCommonButtons: TTaskDialogCommonButtons;
FDefaultButton: TTaskDialogCommonButton;
FUseMessageDefaultButton: Boolean;
FMessageDefaultButton: TMsgDlgBtn;
FButtons: TTaskDialogButtons;
FFooterIcon: TTaskDialogIcon;
FCustomMainIcon: TIcon;
FCustomFooterIcon: TIcon;
FMainIcon: TTaskDialogIcon;
FOnTimer: TTaskDlgTimerEvent;
FRadioButtons: TTaskDialogButtons;
FAutoClick: Boolean;
FAutoClickDelay: Integer;
FRadioButton: TTaskDialogRadioButtonItem;
FProgressBar: TTaskDialogProgressBar;
FFlags: TTaskDialogFlags;
FExpandButtonCaption: string;
FText: string;
FExpandedText: string;
FTaskDialogExpanded: TNotifyEvent;
FTimer: TTimer;
FTickCount: Cardinal;
FMainIconSize: Integer;
FAnimationLoop: Boolean;
FAnimationInverse: Boolean;
//procedure GetIconNameAndIndex(ATaskDialog: TMsgDlgType;
// out AImageName: string; out AImageIndex: Integer); overload;
procedure TaskDialogExpanded(Sender: TObject);
procedure GetIconNameAndIndex(ATaskDialogIcon: TTaskDialogIcon;
out AImageName: string; out AImageIndex: Integer); overload;
procedure ShowDialogForm;
procedure SetHelpContext(const AValue: Integer);
function GetHelpContext: Integer;
function GetText: string;
function GetTitle: string;
procedure SetText(const AValue: string);
procedure SetTitle(const AValue: string);
procedure AdjustHeight;
procedure AdjustWidth;
procedure AdjustControlsTopPos;
procedure AdjustButtonsCaption;
procedure SetButtons(const AValue: TTaskDialogButtons);
procedure PlayMessageDlgSound;
procedure FocusDefaultButton;
procedure LoadDialogImage;
procedure SetFooterText(const AValue: string);
function GetFooterText: string;
procedure SetVerificationText(const AValue: string);
procedure SetExpandedText(const AValue: string);
function GetVerificationText: string;
function GetFocusedButton: TStyledButton;
procedure InitDlgButtonsWithFamily(const AFamily: TStyledButtonFamily);
procedure UpdateButtonsVisibility;
procedure UpdateButtonsSize;
procedure SetFooterIcon(const AValue: TTaskDialogIcon);
procedure SetCustomMainIcon(const AValue: TIcon);
procedure SetCustomFooterIcon(const AValue: TIcon);
procedure SetMainIcon(const AValue: TTaskDialogIcon);
procedure AddCustomButtons(const AButtons: TTaskDialogButtons);
procedure SetMainIconSize(const AValue: Integer);
procedure SetRadioButtons(const AValue: TTaskDialogButtons);
function UsingCommandLinks: Boolean;
procedure SetFlags(const AValue: TTaskDialogFlags);
procedure SetExpandButtonCaption(const Value: string);
function GetExpanded: Boolean;
procedure CalcMessageText(const AExpanded: Boolean);
procedure SetProgressBar(const AValue: TTaskDialogProgressBar);
protected
procedure WndProc(var Message: TMessage); override;
procedure TimerEvent(Sender: TObject);
function GetScaleFactor: Single; virtual;
class function CanUseAnimations: Boolean; virtual; abstract;
function GetButtonsHeight: Integer; virtual;
function GetButtonsWidth: Integer; virtual;
procedure SetButtonsHeight(const AValue: Integer); virtual;
procedure SetButtonsWidth(const AValue: Integer); virtual;
function TaskDialogIconToImageIndex(const ATaskDialogIcon: TTaskDialogIcon): Integer;
function TaskDialogIconToImageName(const ATaskDialogIcon: TTaskDialogIcon): string;
procedure Loaded; override;
procedure LoadImage(const AImageIndex: TImageIndex;
AImageName: string); virtual; abstract;
procedure LoadCustomMainIcon(const AIcon: TIcon;
const ATaskDialogIcon: TTaskDialogIcon); virtual;
procedure LoadCustomFooterIcon(const AIcon: TIcon;
const ATaskDialogIcon: TTaskDialogIcon); virtual;
procedure DefaultDialogSize(out AClientWidth, AClientHeight, AImageSize: Integer); virtual;
function GetDefaultButton(const ADefaultButton: TTaskDialogCommonButton): TStyledButton; virtual;
property TaskDialog: TCustomTaskDialog read FTaskDialog;
public
/// <summary>Converts a modal result to a task dialog common button</summary>
/// <param name="AModalResult">The modal result to convert</param>
/// <param name="ACommonButton">Output: the corresponding common button</param>
/// <returns>True if conversion was successful</returns>
function ModalResultToCommonButton(const AModalResult: TModalResult;
out ACommonButton: TTaskDialogCommonButton): Boolean;
/// <summary>Finds a button by its modal result value</summary>
/// <param name="AModalResult">The modal result to search for</param>
/// <returns>The TStyledButton with the specified modal result, or nil</returns>
function FindButton(const AModalResult: TModalResult): TStyledButton;
/// <summary>Sets the font for all dialog elements</summary>
/// <param name="AFont">The font to apply</param>
procedure SetDialogFont(const AFont: TFont); virtual;
/// <summary>Creates a new instance of the dialog form</summary>
/// <param name="AOwner">The component owner</param>
constructor Create(AOwner: TComponent); override;
/// <summary>Destroys the dialog form instance</summary>
destructor Destroy; override;
/// <summary>Sets the screen position of the dialog</summary>
/// <param name="X">X coordinate in screen pixels</param>
/// <param name="Y">Y coordinate in screen pixels</param>
procedure SetPosition(const X, Y: Integer); virtual;
/// <summary>Enables automatic button click after a delay</summary>
property AutoClick: Boolean read FAutoClick write FAutoClick default False;
/// <summary>Delay in milliseconds before auto-clicking the default button</summary>
property AutoClickDelay: Integer read FAutoClickDelay write FAutoClickDelay default DEFAULT_AUTOCLICK_DELAY;
/// <summary>Width of dialog buttons in pixels</summary>
property ButtonsWidth: Integer read GetButtonsWidth write SetButtonsWidth;
/// <summary>Height of dialog buttons in pixels</summary>
property ButtonsHeight: Integer read GetButtonsHeight write SetButtonsHeight;
/// <summary>Collection of custom buttons for the dialog</summary>
property Buttons: TTaskDialogButtons read FButtons write SetButtons;
/// <summary>Collection of radio buttons for the dialog</summary>
property RadioButtons: TTaskDialogButtons read FRadioButtons write SetRadioButtons;
/// <summary>Standard common buttons to display (Ok, Cancel, Yes, No, etc.)</summary>
property CommonButtons: TTaskDialogCommonButtons read FCommonButtons write FCommonButtons default [tcbOk, tcbCancel];
/// <summary>The default button that receives focus</summary>
property DefaultButton: TTaskDialogCommonButton read FDefaultButton write FDefaultButton default TTaskDialogCommonButton.tcbOk;
/// <summary>Default button when using message dialog style</summary>
property MessageDefaultButton: TMsgDlgBtn read FMessageDefaultButton write FMessageDefaultButton default TMsgDlgBtn.mbOK;
/// <summary>Caption for the expand/collapse button</summary>
property ExpandButtonCaption: string read FExpandButtonCaption write SetExpandButtonCaption;
/// <summary>Returns True if the expandable content is currently shown</summary>
property Expanded: Boolean read GetExpanded;
/// <summary>Additional text shown when dialog is expanded</summary>
property ExpandedText: string read FExpandedText write SetExpandedText;
/// <summary>Progress bar settings for the dialog</summary>
property ProgressBar: TTaskDialogProgressBar read FProgressBar write SetProgressBar;
(*
property URL: string read FURL;
*)
/// <summary>Dialog behavior flags</summary>
property Flags: TTaskDialogFlags read FFlags write SetFlags default [tfAllowDialogCancellation];
/// <summary>Main icon displayed in the dialog (tdiWarning, tdiError, tdiInformation, etc.)</summary>
property MainIcon: TTaskDialogIcon read FMainIcon write SetMainIcon default tdiInformation;
/// <summary>Custom icon to display instead of standard icons</summary>
property CustomMainIcon: TIcon read FCustomMainIcon write SetCustomMainIcon;
/// <summary>Size of the main icon in pixels</summary>
property MainIconSize: Integer read FMainIconSize write SetMainIconSize default DEFAULT_MAIN_ICON_SIZE;
/// <summary>Custom icon for the footer area</summary>
property CustomFooterIcon: TIcon read FCustomFooterIcon write SetCustomFooterIcon;
/// <summary>Standard icon displayed in the footer</summary>
property FooterIcon: TTaskDialogIcon read FFooterIcon write SetFooterIcon default tdiNone;
/// <summary>Text displayed in the footer area</summary>
property FooterText: string read GetFooterText write SetFooterText;
/// <summary>Text for the verification checkbox</summary>
property VerificationText: string read GetVerificationText write SetVerificationText;
/// <summary>Help context ID for F1 help</summary>
property HelpContext: Integer read GetHelpContext write SetHelpContext default 0;
/// <summary>The currently selected radio button item</summary>
property RadioButton: TTaskDialogRadioButtonItem read FRadioButton;
/// <summary>The main message text displayed in the dialog</summary>
property TextMessage: string read GetText write SetText;
/// <summary>The title/instruction text displayed at the top</summary>
property TitleMessage: string read GetTitle write SetTitle;
/// <summary>Timer event fired periodically while dialog is shown</summary>
property OnTimer: TTaskDlgTimerEvent read FOnTimer write FOnTimer;
/// <summary>When True, loops the icon animation continuously (requires Skia4Delphi)</summary>
property AnimationLoop: Boolean read FAnimationLoop write FAnimationLoop;
/// <summary>When True, plays the icon animation in reverse (requires Skia4Delphi)</summary>
property AnimationInverse: Boolean read FAnimationInverse write FAnimationInverse;
end;
/// <summary>Class reference type for TStyledTaskDialogForm descendants</summary>
TStyledTaskDialogFormClass = class of TStyledTaskDialogForm;
/// <summary>Activates or deactivates use of styled task dialogs</summary>
/// <param name="AActivate">True to use styled dialogs, False to use standard Windows dialogs</param>
procedure UseStyledDialogForm(const AActivate: Boolean);
/// <summary>Registers a custom styled task dialog form class</summary>
/// <param name="AFormClass">The form class to register (must inherit from TStyledTaskDialogForm)</param>
/// <remarks>Use this to register custom dialog forms or animated dialog forms</remarks>
procedure RegisterTaskDialogFormClass(AFormClass: TStyledTaskDialogFormClass);
/// <summary>Unregisters a previously registered task dialog form class</summary>
/// <param name="AFormClass">The form class to unregister</param>
procedure UnRegisterTaskDialogFormClass(AFormClass: TStyledTaskDialogFormClass);
/// <summary>Returns True if an animated task dialog form is registered</summary>
/// <returns>True if an animated form class (with Skia4Delphi support) is registered</returns>
function AnimatedTaskDialogFormRegistered: Boolean;
implementation
{$R *.dfm}
uses
System.Math
, Vcl.Themes
, System.HelpIntfs
, Winapi.ShellAPI
, Winapi.CommCtrl
, Winapi.MultiMon
, Vcl.StyledCmpMessages
, System.Typinfo
;
var
_DialogLauncher: ITaskDialogLauncher;
_AnimatedTaskDialogFormClass: TStyledTaskDialogFormClass;
_TaskDialogFormClass: TStyledTaskDialogFormClass;
_DlgButtonClasses: TButtonClasses;
_DialogPosition: Vcl.Forms.TPosition;
function AnimatedTaskDialogFormRegistered: Boolean;
begin
Result := Assigned(_AnimatedTaskDialogFormClass);
end;
procedure UnRegisterTaskDialogFormClass(
AFormClass: TStyledTaskDialogFormClass);
begin
//Unregister handle
_DialogLauncher := nil;
if AFormClass = _AnimatedTaskDialogFormClass then
_AnimatedTaskDialogFormClass := nil;
if AFormClass = _TaskDialogFormClass then
_TaskDialogFormClass := nil;
end;
procedure RegisterTaskDialogFormClass(
AFormClass: TStyledTaskDialogFormClass);
begin
//Create handler for execute custom TaskDialog Form
_DialogLauncher := TTaskDialogLauncherHandler.Create;
if AFormClass.CanUseAnimations then
_AnimatedTaskDialogFormClass := AFormClass
else
_TaskDialogFormClass := AFormClass;
UseStyledDialogForm(True);
end;
procedure UseStyledDialogForm(const AActivate: Boolean);
begin
if AActivate then
RegisterCustomExecute(_DialogLauncher)
else
UnregisterCustomExecute;
end;
{ TStyledTaskDialogForm }
procedure TStyledTaskDialogForm.SetRadioButtons(const AValue: TTaskDialogButtons);
var
I: Integer;
LTaskDialogRadioButtonItem: TTaskDialogRadioButtonItem;
LRadioButton, LLastButton, LFirstButton: TRadioButton;
LHeight: Integer;
LDefaultAssigned: Boolean;
begin
LHeight := RadioGroupPanel.Height;
FRadioButtons := AValue;
LLastButton := nil;
LFirstButton := nil;
LDefaultAssigned := False;
for I := 0 to FRadioButtons.Count -1 do
begin
LTaskDialogRadioButtonItem := FRadioButtons[I] as TTaskDialogRadioButtonItem;
LRadioButton := TRadioButton.Create(Self);
if I = 0 then
LFirstButton := LRadioButton;
LRadioButton.Tag := 100+I;
LRadioButton.Caption := LTaskDialogRadioButtonItem.Caption;
LRadioButton.Parent := RadioGroupPanel;
LRadioButton.Align := alTop;
LRadioButton.Height := LHeight;
if Assigned(LLastButton) then
LRadioButton.Top := LLastButton.Top + LLastButton.Height;
LRadioButton.OnClick := RadioButtonClick;
if LTaskDialogRadioButtonItem.Default then
begin
LRadioButton.Checked := True;
LDefaultAssigned := True;
end;
RadioGroupPanel.Visible := True;
RadioGroupPanel.Height := LHeight * (I+1);
LLastButton := LRadioButton;
end;
if (FRadioButtons.Count > 0) then
begin
RadioGroupPanel.Height := RadioGroupPanel.Height + (LHeight div 3);
if not LDefaultAssigned then
LFirstButton.Checked := True;
end;
end;
procedure TStyledTaskDialogForm.SetButtons(const AValue: TTaskDialogButtons);
var
I: Integer;
LTaskDialogButtonItem: TTaskDialogBaseButtonItem;
LStyledButton: TStyledButton;
begin
FButtons := AValue;
for I := FButtons.Count -1 downto 0 do
begin
LTaskDialogButtonItem := FButtons[I];
if Assigned(LTaskDialogButtonItem) then
begin
case LTaskDialogButtonItem.ModalResult of
mrYes: LStyledButton := YesButton;
mrNo: LStyledButton := NoButton;
mrOk: LStyledButton := OKButton;
mrCancel: LStyledButton := CancelButton;
mrAbort: LStyledButton := AbortButton;
mrRetry: LStyledButton := RetryButton;
mrIgnore: LStyledButton := IgnoreButton;
mrAll: LStyledButton := AllButton;
mrNoToAll: LStyledButton := NoToAllButton;
mrYesToAll: LStyledButton := YesToAllButton;
mrClose: LStyledButton := CloseButton;
mrHelp: LStyledButton := HelpButton;
else
begin
LStyledButton := nil;
end;
end;
if Assigned(LStyledButton) then
begin
TabOrder := LStyledButton.TabOrder -1;
if LTaskDialogButtonItem.Default then
FFocusedButton := LStyledButton;
end;
end;
end;
end;
procedure TStyledTaskDialogForm.SetButtonsHeight(const AValue: Integer);
begin
if FButtonsHeight <> AValue then
begin
FButtonsHeight := AValue;
UpdateButtonsSize;
end;
end;
procedure TStyledTaskDialogForm.SetButtonsWidth(const AValue: Integer);
begin
if FButtonsHeight <> AValue then
begin
FButtonsHeight := AValue;
UpdateButtonsSize;
end;
end;
procedure TStyledTaskDialogForm.SetCustomMainIcon(const AValue: TIcon);
begin
if FCustomMainIcon <> AValue then
begin
FCustomMainIcon := AValue;
LoadCustomMainIcon(FCustomMainIcon, FMainIcon);
end;
end;
procedure TStyledTaskDialogForm.SetCustomFooterIcon(const AValue: TIcon);
begin
if FCustomFooterIcon <> AValue then
begin
FCustomMainIcon := AValue;
LoadCustomFooterIcon(FCustomFooterIcon, FfooterIcon);
end;
end;
procedure TStyledTaskDialogForm.SetFlags(const AValue: TTaskDialogFlags);
begin
if FFlags <> AValue then
begin
FFlags := AValue;
FTaskDialog.Flags := AValue;
ProgressBarPanel.Visible := (tfShowProgressBar in Flags) or (tfShowMarqueeProgressBar in Flags);
if tfShowMarqueeProgressBar in Flags then
InternalProgressBar.Style := pbstMarquee;
end;
end;
procedure TStyledTaskDialogForm.SetMainIcon(const AValue: TTaskDialogIcon);
begin
if FMainIcon <> AValue then
begin
FMainIcon := AValue;
LoadCustomMainIcon(FCustomMainIcon, FMainIcon);
end;
end;
procedure TStyledTaskDialogForm.SetMainIconSize(const AValue: Integer);
begin
if AValue <> FMainIconSize then
FMainIconSize := AValue;
end;
procedure TStyledTaskDialogForm.SetProgressBar(
const AValue: TTaskDialogProgressBar);
begin
FProgressBar := AValue;
InternalProgressBar.Min := FProgressBar.Min;
InternalProgressBar.Max := FProgressBar.Max;
InternalProgressBar.Position := FProgressBar.Position;
InternalProgressBar.MarqueeInterval := FProgressBar.MarqueeSpeed;
InternalProgressBar.State := FProgressBar.State;
end;
procedure TStyledTaskDialogForm.SetFooterIcon(const AValue: TTaskDialogIcon);
begin
if FFooterIcon <> AValue then
begin
FFooterIcon := AValue;
LoadCustomFooterIcon(FCustomFooterIcon, FFooterIcon);
end;
end;
procedure TStyledTaskDialogForm.SetFooterText(const AValue: string);
var
LRows: TStringList;
begin
if Trim(AValue) <> '' then
begin
LRows := TStringList.Create;
try
LRows.Text := AValue;
FooterTextLabel.Caption := AValue;
if LRows.Count > 1 then
FooterPanel.Height := FooterPanel.Height * LRows.Count
else
FooterPanel.Height := 32;
FooterPanel.Visible := True;
finally
LRows.Free;
end;
end
else
FooterPanel.Visible := False;
end;
function TStyledTaskDialogForm.GetButtonsHeight: Integer;
begin
//Assuming all buttons have the same Height
Result := YesButton.Height;
end;
function TStyledTaskDialogForm.GetButtonsWidth: Integer;
begin
//Assuming all buttons have the same Width
Result := YesButton.Width;
end;
function TStyledTaskDialogForm.GetDefaultButton(
const ADefaultButton :TTaskDialogCommonButton): TStyledButton;
begin
if FUseMessageDefaultButton then
begin
case FMessageDefaultButton of
mbYes: Result := YesButton;
mbNo: Result := NoButton;
mbOK: Result := OKButton;
mbCancel: Result := CancelButton;
mbAbort: Result := AbortButton;
mbRetry: Result := RetryButton;
mbIgnore: Result := IgnoreButton;
mbAll: Result := AllButton;
mbNoToAll: Result := NoToAllButton;
mbYesToAll: Result := YesToAllButton;
mbHelp: Result := HelpButton;
mbClose: Result := CloseButton;
else
Result := nil;
end;
end
else
begin
case ADefaultButton of
tcbOk: Result := OKButton;
tcbYes: Result := YesButton;
tcbNo: Result := NoButton;
tcbCancel: Result := CancelButton;
tcbRetry: Result := RetryButton;
tcbClose: Result := CloseButton;
else
Result := nil;
end;
end;
end;
function TStyledTaskDialogForm.GetExpanded: Boolean;
begin
Result := FTaskDialog.Expanded;
end;
procedure TStyledTaskDialogForm.FocusDefaultButton;
var
LButton: TStyledButton;
begin
LButton := GetDefaultButton(DefaultButton);
if not Assigned(LButton) then
LButton := FFocusedButton;
if Assigned(LButton) then
begin
if LButton.CanFocus and Self.Visible then
begin
LButton.SetFocus;
LButton.AutoClick := FAutoClick;
LButton.AutoClickDelay := FAutoClickDelay;
end;
end;
end;
procedure TStyledTaskDialogForm.SetDialogFont(const AFont: TFont);
begin
Self.Font.Assign(AFont);
TextLabel.Font.Name := Font.Name;
TextLabel.Font.Size := AFont.Size;
//TitleLabel font attributes
if not StyleServices.Enabled or StyleServices.IsSystemStyle then
TitleLabel.Font.Color := clHighlight
else
TextLabel.Font.Color := StyleServices.GetSystemColor(clHighlight);
TitleLabel.Font.Style := [TFontStyle.fsBold];
TitleLabel.Font.Name := Font.Name;
TitleLabel.Font.Height := Round(AFont.Height * 1.4);
end;
procedure TStyledTaskDialogForm.SetHelpContext(const AValue: Integer);
begin
inherited HelpContext := AValue;
HelpButton.HelpContext := AValue;
end;
procedure TStyledTaskDialogForm.AdjustHeight;
var
LTitleHeight: Integer;
LRadioGroupPanelHeight: Integer;
LImagePanelHeight: Integer;
LCommandLinksPanelHeight: Integer;
LVerificationPanelHeight: Integer;
LProgressBarPanelHeight: Integer;
LExpandedPanelHeight: Integer;
LButtonsPanelHeight: Integer;
LFooterPanelHeight: Integer;
LMinHeight, LCalcHeight: Integer;
LImageSize, LMessageHeight, LWidth, LHeight, LMargins: Integer;
begin
LMargins := CenterPanel.Margins.Top * 2;
DefaultDialogSize(LWidth, LHeight, LImageSize);
LImagePanelHeight := LImageSize +
IconContainer.Margins.Top + IconContainer.Margins.Bottom +
ImagePanel.Margins.Top + ImagePanel.Margins.Bottom;
//Height of Buttons
if FButtonsHeight <> DEFAULT_STYLEDDIALOG_BUTTONSHEIGHT then
ButtonsPanel.Height := FButtonsHeight;
//Calculate Height of Form, based on Visible Components
if TitleLabel.Caption <> '' then
begin
LTitleHeight := TitleLabel.Height +
TitleLabel.Margins.Top + TitleLabel.Margins.Bottom;
end
else
begin
LTitleHeight := 0;
TitleLabel.Visible := False;
end;
if RadioGroupPanel.Visible then
LRadioGroupPanelHeight := RadioGroupPanel.Height
else
LRadioGroupPanelHeight := 0;
if FooterPanel.Visible then
LFooterPanelHeight := FooterPanel.Height
else
LFooterPanelHeight := 0;
if VerificationPanel.Visible then
LVerificationPanelHeight := VerificationPanel.Height
else
LVerificationPanelHeight := 0;
if ProgressBarPanel.Visible then
LProgressBarPanelHeight := ProgressBarPanel.Height
else
LProgressBarPanelHeight := 0;
if ExpandedPanel.Visible then
LExpandedPanelHeight := ExpandedPanel.Height
else
LExpandedPanelHeight := 0;
if CommandLinksPanel.Visible then
LCommandLinksPanelHeight := CommandLinksPanel.Height + LMargins
else
LCommandLinksPanelHeight := 0;
if ButtonsPanel.Visible then
LButtonsPanelHeight := ButtonsPanel.Height
else
LButtonsPanelHeight := 0;
LMessageHeight := AutoSizeLabel.Height +
AutoSizeLabel.Margins.Top + AutoSizeLabel.Margins.Bottom +
MessageScrollBox.Margins.Top + MessageScrollBox.Margins.Bottom +
LMargins;
LMessageHeight := Max(LMessageHeight,
LImagePanelHeight - LTitleHeight);
//Actual Height based on size of Message
LCalcHeight :=
LTitleHeight +
LMessageHeight +
LExpandedPanelHeight +
LRadioGroupPanelHeight +
LFooterPanelHeight +
LVerificationPanelHeight +
LProgressBarPanelHeight +
LButtonsPanelHeight +
LCommandLinksPanelHeight;
//Minumum Height based on size of Image
LMinHeight := Max(
LImagePanelHeight +
LButtonsPanelHeight
,
LTitleHeight +
LExpandedPanelHeight +
LRadioGroupPanelHeight +
LFooterPanelHeight +
LVerificationPanelHeight +
LProgressBarPanelHeight +
LButtonsPanelHeight +
LCommandLinksPanelHeight);
LHeight := Min(Self.Monitor.Height - Round(150 * GetScaleFactor),
Max(LCalcHeight, LMinHeight));
ClientHeight := LHeight;
Constraints.MinHeight := LMinHeight +
Height - ClientHeight;
TextLabel.Font.Assign(AutoSizeLabel.Font);
TextLabel.Height := LMessageHeight;
if LCalcHeight > LHeight then
begin
MessageScrollBox.VertScrollBar.Visible := True;
{$IFDEF D11+}
//You need Delphi 11 Update 3 to compile this row or remove it!
MessageScrollBox.UseWheelForScrolling := True;
{$ENDIF}
MessageScrollBox.VertScrollBar.Range := LMessageHeight + LTitleHeight + 100;
TextLabel.Align := alClient;
end
else
begin
MessageScrollBox.VertScrollBar.Visible := False;
TextLabel.Margins.Top := Max(0,
(CenterPanel.Height - AutoSizeLabel.Height - LTitleHeight) div 2);
end;
AutoSizeLabel.Visible := False;
end;
procedure TStyledTaskDialogForm.AdjustWidth;
var
LFormWidth, I: Integer;
LStyledButton: TStyledButton;
LMargins: Integer;
LImageSize, LWidth, LHeight: Integer;
begin
DefaultDialogSize(LWidth, LHeight, LImageSize);
ImagePanel.Width := Round(LImageSize * GetScaleFactor);
LMargins := ButtonsPanel.Margins.Left;
LFormWidth := LMargins;
if ButtonsPanel.Visible then
begin
for I := 0 to ComponentCount - 1 do
begin
if Components[I] is TStyledButton then
begin
LStyledButton := TStyledButton(Components[I]);
if LStyledButton.Visible and (LStyledButton.Align = alRight) then
LFormWidth := LFormWidth + LStyledButton.Width + LMargins + LMargins;
end;
end;
end;
LFormWidth := LFormWidth + LMargins;
ClientWidth := Max(LWidth, LFormWidth);
//Resize Image based on Scale Factor
ImagePanel.SetBounds(ImagePanel.Left, ImagePanel.Top,
LImageSize, LImageSize);
IconContainer.SetBounds(IconContainer.Left, IconContainer.Top,
LImageSize, LImageSize);
end;
procedure TStyledTaskDialogForm.CalcMessageText(const AExpanded: Boolean);
var
LMessage: string;
begin
if not AExpanded then
begin
ExpandButton.Caption := '+';
if ExpandButtonCaption = '' then
ExpandLabel.Caption := SShowDetails;
end
else
begin
ExpandButton.Caption := '-';
if ExpandButtonCaption = '' then
ExpandLabel.Caption := SHideDetails;
end;
LMessage := FText;
if AExpanded and (FExpandedText <> '') then
LMessage := LMessage + sLineBreak + sLineBreak + FExpandedText;
if TextLabel.Caption <> LMessage then
begin
AutoSizeLabel.Caption := ClearHRefs(LMessage);
TextLabel.Caption := LMessage;
end;
end;
procedure TStyledTaskDialogForm.SetText(const AValue: string);
begin
if AValue <> FText then
begin
FText := AValue;
CalcMessageText(Expanded);
end;
end;
procedure TStyledTaskDialogForm.SetTitle(const AValue: string);
begin
if TitleLabel.Caption <> AValue then
begin
TitleLabel.Caption := AValue;
end;
end;
procedure TStyledTaskDialogForm.SetVerificationText(const AValue: string);
var
LRows: TStringList;
begin
if Trim(AValue) <> '' then
begin
LRows := TStringList.Create;
try
LRows.Text := AValue;
VerificationCheckBox.Caption := AValue;
if LRows.Count > 1 then
VerificationPanel.Height := VerificationPanel.Height * LRows.Count;
VerificationPanel.Visible := True;
finally
LRows.Free;
end;
end
else
VerificationPanel.Visible := False;
end;
procedure TStyledTaskDialogForm.SetExpandButtonCaption(const Value: string);
begin
FExpandButtonCaption := Value;
end;
procedure TStyledTaskDialogForm.SetExpandedText(const AValue: string);
begin
if Trim(AValue) <> FExpandedText then
begin
FExpandedText := AValue;
ExpandedPanel.Visible := FExpandedText <> '';
CalcMessageText(Expanded);
end;
end;
procedure TStyledTaskDialogForm.LoadCustomFooterIcon(const AIcon: TIcon;
const ATaskDialogIcon: TTaskDialogIcon);
begin
//In descendand form implements this method
;
end;
procedure TStyledTaskDialogForm.LoadCustomMainIcon(const AIcon: TIcon;
const ATaskDialogIcon: TTaskDialogIcon);
begin
//In descendand form implements this method
;
end;
procedure TStyledTaskDialogForm.LoadDialogImage;
var
LIconName: string;
LIconIndex: Integer;
LMargins: Integer;
begin
if (tfUseHiconMain in FTaskDialog.Flags) and Assigned(FTaskDialog.CustomMainIcon) then
begin
LoadCustomMainIcon(FTaskDialog.CustomMainIcon, FTaskDialog.MainIcon);
end
else
begin
GetIconNameAndIndex(FMainIcon, LIconName, LIconIndex);
LoadImage(LIconIndex, LIconName);
end;
LMargins := CenterPanel.Margins.Left + CenterPanel.Margins.Right;
if ImagePanel.Visible then
Inc(LMargins, ImagePanel.Width);
RadioGroupPanel.Margins.Left := LMargins;
CommandLinksPanel.Margins.Left := LMargins;
ProgressBarPanel.Margins.Left := LMargins;
end;
function TStyledTaskDialogForm.FindButton(const AModalResult: TModalResult): TStyledButton;
var
I: Integer;
begin
for I := 0 to Self.ComponentCount - 1 do
begin
if Components[I] is TStyledButton then
begin
Result := TStyledButton(Components[I]);
if Result.ModalResult = AModalResult then
Exit;
end;
end;
Result := nil;
end;
procedure TStyledTaskDialogForm.UpdateButtonsSize;
procedure UpdateButtonSize(const AButton: TStyledButton);
begin
AButton.Width := Round(FButtonsWidth * GetScaleFactor);
end;
begin
UpdateButtonSize(YesButton);
UpdateButtonSize(NoButton);
UpdateButtonSize(OKButton);
UpdateButtonSize(CancelButton);
UpdateButtonSize(RetryButton);
UpdateButtonSize(CloseButton);
UpdateButtonSize(AbortButton);
UpdateButtonSize(IgnoreButton);
UpdateButtonSize(AllButton);
UpdateButtonSize(NoToAllButton);
UpdateButtonSize(YesToAllButton);
UpdateButtonSize(HelpButton);
end;
procedure TStyledTaskDialogForm.UpdateButtonsVisibility;
function IsButtonVisible(const AButton: TStyledButton): Boolean;
var
I: Integer;
LTaskDialogButtonItem: TTaskDialogBaseButtonItem;
begin
Result := False;