TTaskDialog - A custom dialog in Delphi

TTaskDialog  is a non-visual component, which shows full-featured dialog at run-time which introduced in Delphi 2009. A task dialog is somewhat like the standard message dialog in the VCL but we can also add extra buttons, check-boxes, radio buttons besides the usual default sets of buttons like OK, Cancel, Yes, No. We can set caption, title and text for dialog also. This component is available on Dialog tab in Component Palette. Dialog is shown with calling Execute function and if it gets True then property ModalResult has ID of pressed button. Execute returns True if the dialog was opened successfully. TTaskDialog provides important properties like Caption, Title, Text to show dialog captions and messages in a dialog. Other properties are like property Buttons to add extra buttons, MainIcon to set values for standard icons: none, warning, error, information, shield and property RadioButton has the radio-button object, which was clicked.


Lets check with different type of dialog.

Normal Dialog with Caption, Title, Text and Close Button.

Caption is the text shown in the title bar of the window, Title is the header, and Text is the body matter of the dialog. CommonButtons property is used to show different buttons like Ok, Cancel, Yes, No and Close.

The CommonButtons property is of type TTaskDialogCommonButtons, defined as 

TTaskDialogCommonButton = (tcbOk, tcbYes, tcbNo, tcbCancel, tcbRetry, tcbClose);

TTaskDialogCommonButtons = set of TTaskDialogCommonButton;

This property determines that extra buttons will be shown in the dialog . If the user clicks any of these buttons, the corresponding TModalResult value will be stored in the ModalResult property as soon as Execute has returned. 

Simple Dialog with title, header and message.

procedure TForm1.btnShowTaskDialogClick(Sender: TObject);
begin
  with TTaskDialog.Create(Self) do
  begin
    try
      Caption := 'Dialog Caption';
      Title := 'Dialog Title';
      Text := 'This is dialog text.';
      CommonButtons := [tcbClose];
      Execute;
    finally
      Free;
    end;
  end;
end;


Error Dialog with Yes, No Button

  with TTaskDialog.Create(Self) do
  begin
    try
      Caption := 'Error Dialog';
      Title := 'Data Error';
      Text := 'Invalid data. Do you want to continue ?';
      MainIcon := tdiError;
      CommonButtons := [tcbYes, tcbNo];
      if Execute then
      begin
        if ModalResult=mrYes then
          ShowMessage('Yes')
        else
          ShowMessage('No');
      end;
    finally
      Free;
    end;
  end;


Dialog with Information, Shield, Warning, None and Custom Icon

The MainIcon property determines the icon shown in the dialog, and should reflect the nature of the dialog. As an integer type, MainIcon can be set to any of the values tdiNone, tdiWarning, tdiError, tdiInformation, and tdiShield

Information Icon

  with TTaskDialog.Create(Self) do
  begin
    try
      Caption := 'Dialog Icon';
      Title := 'Information';
      Text := 'Information message dialog.';
      MainIcon := tdiInformation;
      CommonButtons := [tcbOk];
      Execute;
    finally
      Free;
    end;
  end;


Warning Icon

  with TTaskDialog.Create(Self) do
  begin
    try
      Caption := 'Dialog Icon';
      Title := 'Warning';
      Text := 'Warning message dialog.';
      MainIcon := tdiWarning;
      CommonButtons := [tcbOk, tcbCancel];
      if Execute then
      begin
        if ModalResult=mrOk then
          ShowMessage('ok')
        else
          ShowMessage('cancel');
      end;
    finally
      Free;
    end;
  end; 


Shield Icon

  with TTaskDialog.Create(Self) do
  begin
    try
      Caption := 'Dialog Icon';
      Title := 'Shield';
      Text := 'Shield message dialog.';
      MainIcon := tdiShield;
      CommonButtons := [tcbOk];
      Execute;
    finally
      Free;
    end;
  end;


Custom Icon

Print Dialog
printer.ico file should be in same folder where application exe file exists.

  with TTaskDialog.Create(Self) do
  begin
    try
      Caption := 'Dialog Custom';
      Title := 'Print';
      Text := 'Print data.';
      CustomMainIcon.LoadFromFile('printer.ico');
      Flags := [tfUseHiconMain];
      CommonButtons := [tcbYes, tcbNo];
      if Execute then
      begin
        if ModalResult=mrYes then
          ShowMessage('Done');
      end;
    finally
      Free;
    end;
  end;


Dialog with Default Button

  with TTaskDialog.Create(Self) do
  begin
    try
      Caption := 'Confirmation';
      Title := 'Invalid Data';
      Text := 'Do you want to continue ?';
      MainIcon := tdiInformation;
      CommonButtons := [tcbOk, tcbClose];
      DefaultButton := tcbClose;
      if Execute then
      begin
        if ModalResult = mrOk then
          ShowMessage('Ok')
        else
          ShowMessage('Cancel');
      end;
    finally
      Free;
    end;
  end;


Dialog with Custom Buttons

We can add extra custom buttons to dialog. We can set button caption, default, commandlink hint and enable property. We can also implement custom button click event which will fire on custom button click.

procedure TForm1.btnShowTaskDialogClick(Sender: TObject);
begin
  with TTaskDialog.Create(self) do
  begin
      try
        Title := 'Confirm removal';
        Caption := 'Confirm';
        Text := 'Remove selected item?';
        CommonButtons := [];
        with TTaskDialogButtonItem(Buttons.Add) do
        begin
          Caption := 'Demo';
          ModalResult := mrNone;
        end;
        with TTaskDialogButtonItem(Buttons.Add) do
        begin
          Caption := 'Remove';
          ModalResult := mrYes;
        end;
        with TTaskDialogButtonItem(Buttons.Add) do
        begin
          Caption := 'Keep';
          ModalResult := mrNo;
        end;
        OnButtonClicked := TaskDialogButtonClicked;
        MainIcon := tdiInformation;
        if Execute then
          if ModalResult = mrYes then
            ShowMessage('Item removed');
      finally
        Free;
      end
  end;
end;

On Button click event

procedure TForm1.TaskDialogButtonClicked(Sender: TObject;
  ModalResult: TModalResult; var CanClose: Boolean);
begin
  if TTaskDialog(Sender).Button.Index=0 then
  begin
    ShowMessage('Demo button clicked.');
    CanClose := False;
  end;
end;


Dialog with Command Links

Instead of classic buttons, the task dialog buttons can be command links. This is achieved by setting the tfUseCommandLinks flag in Flags property. Now you can also set the CommandLinkHint property for a button:

  with TTaskDialog.Create(self) do
  begin
    try
      Title := 'Confirm removal';
      Caption := 'Confirm';
      Text := 'Remove selected item?';
      CommonButtons := [];
      with TTaskDialogButtonItem(Buttons.Add) do
      begin
        Caption := 'Remove';
        ModalResult := mrYes;
        CommandLinkHint := 'Remove the Item from list.';
      end;
      with TTaskDialogButtonItem(Buttons.Add) do
      begin
        Caption := 'Keep';
        ModalResult := mrNo;
        CommandLinkHint := 'Add the Item to list.';
      end;
      MainIcon := tdiInformation;
      Flags := [tfUseCommandLinks];
      if Execute then
        if ModalResult = mrYes then
          ShowMessage('Item removed');
    finally
      Free;
    end
  end;


Dialog with Hyperlinks

To show hyperlink on a dialog we can add HTML <a href="www"> tag to the message. But to make it functional we need to implement onHyperlinkclick event. We need to active tfEnableHyperlinks property flag.

procedure TForm1.btnShowTaskDialogClick(Sender: TObject);
begin
  with TTaskDialog.Create(Self) do
  begin
    try
      Caption := 'About Us';
      Title := 'ABC Software Corp.';
      Text := 'Suit 123, Four Sqare, London, UK '+#13#10+
              'Copyright © 2011 Andreas Rejbrand'+#13#10+
              '<a href="http://www.ABCSoft.com">www.ABCSoft.com</a>';
      OnHyperlinkClicked := TaskDialogHyperlinkClicked;
      Flags := [tfEnableHyperlinks];
      CustomMainIcon := Application.Icon;
      CommonButtons := [tcbClose];
      Execute;
    finally
      Free;
    end;
  end;
end;

To open link on Hyperlink click

Uses
    ShellApi;
……
procedure TForm1.TaskDialogHyperlinkClicked(Sender: TObject);
begin
  if Sender is TTaskDialog then
    with Sender as TTaskDialog do
      ShellExecute(0, 'open', PChar(URL), nil, nil, SW_SHOWNORMAL);
end;


Dialog with CheckBox

Using the VerificationText string property, you can add a checkbox to the footer of the task dialog. The caption of the checkbox is the property. You can make the checkbox initially checked by setting the tfVerificationFlagChecked flag. OnVerificationClicked event, which is triggered every time the state of the checkbox is changed during the modality of the dialog.

procedure TForm1.btnShowTaskDialogClick(Sender: TObject);
begin
  with TTaskDialog.Create(self) do
  begin
    try
      Caption := 'Application';
      Title := 'Application Settings';
      Text := 'Do you want to continue with settings?';
      CommonButtons := [tcbYes, tcbNo];
      MainIcon := tdiInformation;
      VerificationText := 'Remember my settings.';
      Flags := [tfVerificationFlagChecked];
      OnVerificationClicked := TaskDialogVerificationClicked;
      Execute;
    finally
      Free;
    end
  end;
end;

On check click event

procedure TForm1.TaskDialogVerificationClicked(Sender: TObject);
begin
   if tfVerificationFlagChecked in TTaskDialog(Sender).Flags then
      ShowMessage('checked')
   else
      ShowMessage('not checked');
end;


Dialog with RadioButtons

Radio buttons can be implemented for multiple options and only one option can be selected. RadioButtons property is used to add list of radiobuttons and RadioButton property returns selected radiobutton in list.

procedure TForm1.btnShowTaskDialogClick(Sender: TObject);
begin
  with TTaskDialog.Create(self) do
  begin
    try
      Caption := 'Application';
      Title := 'Customer Support:';
      Text := 'How is the Customer Support?';
      CommonButtons := [tcbOk, tcbCancel];
      MainIcon := tdiShield;
      with RadioButtons.Add do
        Caption := 'Excellent';
      with RadioButtons.Add do
        Caption := 'Good';
      with RadioButtons.Add do
        Caption := 'Bad';
      OnRadioButtonClicked := TaskDialogRadioButtonClicked;
      if Execute then
        if ModalResult = mrOk then
          ShowMessage(Format('You chose %d.', [RadioButton.Index]));
    finally
      Free;
    end
  end;
end;

On RadioButton click event

procedure TForm1.TaskDialogRadioButtonClicked(Sender: TObject);
begin
  with TTaskDialog(Sender) do
  begin
    ShowMessage(RadioButtons.Items[RadioButton.Index].Caption);
  end;
end;


Dialog with ProgressBar

We can used Progressbar property to add a Progressbar to the dialog. We can set Progressbar position, state, min and max values.

  with TTaskDialog.Create(self) do
  begin
    try
      Caption := 'Application';
      Title := 'Invoice';
      Text := 'Preparing Customer Invoice report.';
      CommonButtons := [tcbOk, tcbCancel];
      MainIcon := tdiInformation;
      ProgressBar.Position := 40;
      Flags := [tfShowProgressBar];
      Execute;
    finally
      Free;
    end
  end;


Progress bar with error state

  with TTaskDialog.Create(self) do
  begin
    try
      Caption := 'Application';
      Title := 'Invoice';
      Text := 'Preparing Customer Invoice report. Error';
      CommonButtons := [tcbOk, tcbCancel];
      MainIcon := tdiInformation;
      ProgressBar.Position := 70;
      ProgressBar.State := TProgressBarState.pbsError;
      Flags := [tfShowProgressBar];
      Execute;
    finally
      Free;
    end
  end;


Progressbar in Error state with marquee.

  with TTaskDialog.Create(self) do
  begin
    try
      Caption := 'Application';
      Title := 'Importing Data';
      Text := 'It may take time.';
      CommonButtons := [tcbOk, tcbCancel];
      MainIcon := tdiInformation;
      ProgressBar.Position := 70;
      ProgressBar.MarqueeSpeed := 1;
      Flags := [tfShowMarqueeProgressBar];
      Execute;
    finally
      Free;
    end
  end;


Dialog with expand information details

We can use the properties ExpandedText and ExpandedButtonCaption to add extra text information to the dialog which will display when user clicks the expand button and if we click again then extra information will hide. tfExpandedByDefault option in Flags property can be used to show expand by default. 

  with TTaskDialog.Create(self) do
  begin
    try
      Title := 'Confirm';
      Caption := 'Cuatomer Details';
      Text := 'Are you sure that you want to delete Cuatomer data.?';
      CommonButtons := [tcbYes, tcbNo];
      ExpandButtonCaption := 'More about Cutomer';
      ExpandedText := 'If you remove the Customer all Invoice Data will be also deleted.';
      Flags := [tfExpandedByDefault];
      MainIcon := tdiInformation;
      if Execute then
        if ModalResult = mrYes then
          ShowMessage('Customer data and Invice data deleted');
    finally
      Free;
    end
  end;



tfExpandFooterArea option in Flag property can be used to show Expand text on footer.

  with TTaskDialog.Create(self) do
  begin
    try
      Title := 'Confirm';
      Caption := 'Cuatomer Details';
      Text := 'Are you sure that you want to delete Cuatomer data.?';
      CommonButtons := [tcbYes, tcbNo];
      ExpandButtonCaption := 'More about Cutomer';
      ExpandedText := 'If you remove the Customer all Invoice Data will be also deleted.';
      Flags := [tfExpandedByDefault, tfExpandFooterArea];
      MainIcon := tdiInformation;
      if Execute then
        if ModalResult = mrYes then
          ShowMessage('Customer data and Invice data deleted');
    finally
      Free;
    end
  end;
  


Dialog with Footer information details

We can use the Footer and FooterIcon properties to create a footer. Even we can add custom icons to footer by using CustomFooterIcon and ftUseHiIconFooter option in Flags property.

  with TTaskDialog.Create(self) do
  begin
    try
      Caption := 'Application';
      Title := 'Balanace Sheet Report';
      Text := 'Generating Customer wise balance sheet report for this year.';
      CommonButtons := [tcbYes, tcbNo];
      MainIcon := tdiInformation;
      FooterText := 'It make take time as so many data.';
      FooterIcon := tdiWarning;
      Execute;
    finally
      Free;
    end
  end;


VCL Styles for Taskdialogs

Only problem I found that TTaskdialog does not support VCL style provided by Delphi. So if we apply VCL style to an application then it wont effect to TTaskdialog. For example, I created an application with applying VCL style 'Aqua Light Slate' on project file but you can see TaskDialog is not showing in style.

  TStyleManager.TrySetStyle('Aqua Light Slate');


Here in above example you can see VCL style is applied to Delphi application but it is not applied to TaskDialog.

But we can apply VCL styles in TaskDialog by installing VCLStyleUtils package from https://github.com/RRUZ/vcl-styles-utils. The VCL Styles Utils is a Delphi library which extend the RAD Studio VCL Styles, adding unique features like the support for Classic and New Common dialogs, Task Dialogs, Styling of popup and shell menus, Non client area components and much more. And for Extend and improve the Delphi VCL Styles please visit to  https://theroadtodelphi.wordpress.com/

TTaskDialog support to the VCL Styles Utils library.


To activate this feature you need to add these units to your project.
• Vcl.Styles.Utils.Forms
• Vcl.Styles.Utils.SysStyleHook
• Vcl.Styles.Utils.SysControls
• Vcl.Styles.Hooks

To apply styles in a Delphi Application, please visit my blog

Applying Theme or Style to a Delphi Application 

Comments

  1. I really appreciate the information provided on this blog, this blog certainly provided enough information, though I have a question regarding the printer, the printer when asked to print is not printing, it is showing an error called epson communication error, I would appreciate any information provided on this blog.

    ReplyDelete
  2. You are really great, but for me the problem is that there is not a TTaskDialog support IN Firemonkey. I would love if you could make a tutorial about task dialogs in FMX.
    A clarification. I'f forced to use FMX because in VCL there is no support for high level graphics and effects. Bu my applications are for PC and not for mobile.
    Thank you however.

    ReplyDelete
  3. Great documentation with nicely detailed explanations - well done, Jitendra!
    When coding in Delphi, I use Fire Monkey too - VCL simply doesn't have adequate component support for some of the items I'm regularly coding. In such cases, I occasionally turn to Lazarus, but it has its restrictions too :-(
    I have been asked by a customer to replace as many user dialogs as possible with the company's standard background colour and fonts. Can this be done using TTaskDialog, and, if so, how?
    Thanks in advance!

    ReplyDelete

Post a Comment

Popular posts from this blog

ShellExecute in Delphi

How to send Email in Delphi?

Drawing Shapes in Delphi