【问题标题】:How to use the TTaskDialog?如何使用 TTaskDialog?
【发布时间】:2011-02-12 17:45:45
【问题描述】:

如何使用TTaskDialog 类(在Delphi 2009 及更高版本中)? The official documentation 没有帮助。事实上,您可以通过使用 CodeInsight 或 VCL 源代码检查该类来了解更多信息。那里没有教学解释,但至少也没有错误(嗯,just a few)。

就在最近,我想知道您如何响应对话框中的超链接点击。实际上,设置tfEnableHyperlinks 标志,您可以在对话框的文本部分中包含HTML 超链接。 (好吧,文档关于标志的说法是:“如果设置,内容、页脚和扩展文本可以包含超链接。”自然,使用<A HTML 元素实现链接是“显而易见的”。)我管理弄清楚自己使用OnHyperLinkClick 事件来响应对超链接的点击。但是这个事件是TNotifyEvent,那么你怎么知道点击了哪个链接呢?好吧,文档对此只字未提,所以我不得不猜测。最终我发现对话框的URL public 属性被设置了,所以我可以这样做

procedure TmainFrm.TaskDialogHyperLinkClicked(Sender: TObject);
begin
  if Sender is TTaskDialog then
    with Sender as TTaskDialog do
      ShellExecute(0, 'open', PChar(URL), nil, nil, SW_SHOWNORMAL);
end;

官方文档说,关于这个属性:

URL 包含任务的 URL 对话框。

现在,您必须承认,这是一个很好的解释!但比这更糟糕的是:文档不仅缺乏解释,而且还包含错误。 For instance,

ExpandButtonCaption:此按钮的附加信息。

这不是很准确。什么按钮?如果您显示此特定属性的帮助,it says

ExpandButtonCaption 包含在标题展开时要显示的附加文本。

也不好。什么字幕?正确的解释是

ExpandButtonCaption 是显示在按钮旁边的文本,可让用户展开对话框以显示更多信息。例如,此属性可能是“更多详细信息”。

无论如何,目前,我正在尝试创建一个带有两个命令链接按钮的对话框。我知道操作系统可以显示这些带有标题和更长解释的按钮,但我似乎无法使用TTaskButton 使其工作。文档isn't great

但是,我不会在 SO 上问如何实现这一特定目标,而是问另一个问题:

TTaskDialog 类是否有任何(非官方)文档?

【问题讨论】:

  • 我找到了针对特定问题的解决方案,不过:with TTaskDialogButtonItem(Buttons.Add) do begin Caption := 'The caption';CommandLinkHint := 'The explanation.'; end; 这不是很明显,但它确实有效...
  • 我自己,我认为直接针对 Win32 Api 函数编写更简单,使用起来非常简单。
  • @David:是的,也许我应该这样做。
  • 如果你想支持XP,你需要降级到别的东西,所以无论如何你都必须做一些工作

标签: delphi ttaskdialog


【解决方案1】:

如果找不到文档,那么write it

任务对话框的 Hello World

with TTaskDialog.Create(Self) do
  try
    Caption := 'My Application';
    Title := 'Hello World!';
    Text := 'I am a TTaskDialog, that is, a wrapper for the Task Dialog introduced ' +
            'in the Microsoft Windows Vista operating system. Am I not adorable?';
    CommonButtons := [tcbClose];
    Execute;
  finally
    Free;
  end;

Caption 是显示在窗口标题栏中的文本,Title 是标题,Text 是对话框的正文。不用说,Execute 显示任务对话框,结果如下所示。 (我们将在一两节中返回CommonButtons 属性。)

做一个行为端正的公民

当然,如果在没有任务对话框API的Windows XP下运行,任务对话框会导致程序崩溃。如果禁用视觉主题,它也将不起作用。在任何这种情况下,我们都需要坚持老式的MessageBox。因此,在实际应用中,我们需要这样做

if (Win32MajorVersion >= 6) and ThemeServices.ThemesEnabled then
  with TTaskDialog.Create(Self) do
    try
      Caption := 'My Application';
      Title := 'Hello World!';
      Text := 'I am a TTaskDialog, that is, a wrapper for the Task Dialog introduced ' +
              'in the Microsoft Windows Vista operating system. Am I not adorable?';
      CommonButtons := [tcbClose];
      Execute;
    finally
      Free;
    end
else
  MessageBox(Handle,
             'I am an ordinary MessageBox conveying the same message in order to support' +
             'older versions of the Microsoft Windows operating system (XP and below).',
             'My Application',
             MB_ICONINFORMATION or MB_OK);

在本文的其余部分,我们将假设支付了向后兼容的 tax,而是只专注于任务对话框。

对话框类型。模态结果

CommonButtons 属性的类型为TTaskDialogCommonButtons,定义为

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

这个属性决定了对话框中显示的按钮(如果没有手动添加按钮,我们稍后会这样做)。如果用户单击这些按钮中的任何一个,则相应的 TModalResult 值将在 Execute 返回后立即存储在 ModalResult 属性中。 MainIcon 属性决定了对话框中显示的图标,并且应该——当然——反映对话框的性质,按钮集也应该如此。形式上为整数,MainIcon 可以设置为任何值 tdiNonetdiWarningtdiErrortdiInformationtdiShield

with TTaskDialog.Create(Self) do
  try
    Caption := 'My Application';
    Title := 'The Process';
    Text := 'Do you want to continue even though [...]?';
    CommonButtons := [tcbYes, tcbNo];
    MainIcon := tdiNone; // There is no tdiQuestion
    if Execute then
      if ModalResult = mrYes then
        beep;
  finally
    Free;
  end;

以下是其余图标类型的示例(分别为盾牌、警告和错误):

最后应该知道,可以使用DefaultButton属性来设置对话框中的默认按钮。

with TTaskDialog.Create(Self) do
  try
    Caption := 'My Application';
    Title := 'The Process';
    Text := 'Do you want to continue even though [...]?';
    CommonButtons := [tcbYes, tcbNo];
    DefaultButton := tcbNo;
    MainIcon := tdiNone;
    if Execute then
      if ModalResult = mrYes then
        beep;
  finally
    Free;
  end;

自定义按钮

您可以将自定义按钮添加到任务对话框。事实上,您可以将CommonButtons 属性设置为空集,并完全依赖自定义按钮(以及无限数量的此类按钮)。以下真实示例显示了这样一个对话框:

with TTaskDialog.Create(self) do
  try
    Title := 'Confirm Removal';
    Caption := 'Rejbrand BookBase';
    Text := Format('Are you sure that you want to remove the book file named "%s"?', [FNameOfBook]);
    CommonButtons := [];
    with TTaskDialogButtonItem(Buttons.Add) do
    begin
      Caption := 'Remove';
      ModalResult := mrYes;
    end;
    with TTaskDialogButtonItem(Buttons.Add) do
    begin
      Caption := 'Keep';
      ModalResult := mrNo;
    end;
    MainIcon := tdiNone;
    if Execute then
      if ModalResult = mrYes then
        DoDelete;
  finally
    Free;
  end

命令链接

任务对话框按钮可以是命令链接,而不是传统的按钮。这是通过设置tfUseCommandLinks 标志(在Flags 中)来实现的。现在您还可以设置CommandLinkHint(每个按钮)属性:

with TTaskDialog.Create(self) do
  try
    Title := 'Confirm Removal';
    Caption := 'Rejbrand BookBase';
    Text := Format('Are you sure that you want to remove the book file named "%s"?', [FNameOfBook]);
    CommonButtons := [];
    with TTaskDialogButtonItem(Buttons.Add) do
    begin
      Caption := 'Remove';
      CommandLinkHint := 'Remove the book from the catalogue.';
      ModalResult := mrYes;
    end;
    with TTaskDialogButtonItem(Buttons.Add) do
    begin
      Caption := 'Keep';
      CommandLinkHint := 'Keep the book in the catalogue.';
      ModalResult := mrNo;
    end;
    Flags := [tfUseCommandLinks];
    MainIcon := tdiNone;
    if Execute then
      if ModalResult = mrYes then
        DoDelete;
  finally
    Free;
  end

tfAllowDialogCancellation 标志将恢复关闭系统菜单项(和标题栏按钮——事实上,它将恢复整个系统菜单)。

不要向最终用户提供技术细节

您可以使用属性ExpandedTextExpandedButtonCaption 添加一段文本(前者),该文本仅在用户单击按钮(在后者属性中的文本左侧)后才显示以请求它.

with TTaskDialog.Create(self) do
  try
    Title := 'Confirm Removal';
    Caption := 'Rejbrand BookBase';
    Text := Format('Are you sure that you want to remove the book file named "%s"?', [FNameOfBook]);
    CommonButtons := [];
    with TTaskDialogButtonItem(Buttons.Add) do
    begin
      Caption := 'Remove';
      CommandLinkHint := 'Remove the book from the catalogue.';
      ModalResult := mrYes;
    end;
    with TTaskDialogButtonItem(Buttons.Add) do
    begin
      Caption := 'Keep';
      CommandLinkHint := 'Keep the book in the catalogue.';
      ModalResult := mrNo;
    end;
    Flags := [tfUseCommandLinks, tfAllowDialogCancellation];
    ExpandButtonCaption := 'Technical information';
    ExpandedText := 'If you remove the book item from the catalogue, the corresponding *.book file will be removed from the file system.';
    MainIcon := tdiNone;
    if Execute then
      if ModalResult = mrYes then
        DoDelete;
  finally
    Free;
  end

下图显示了用户单击按钮以显示其他详细信息后的对话框。

如果您添加 tfExpandFooterArea 标志,则附加文本将显示在页脚中:

在任何情况下,您都可以通过添加tfExpandedByDefault 标志来打开已展开详细信息的对话框。

自定义图标

您可以在任务对话框中使用任何自定义图标,方法是使用tfUseHiconMain 标志并在CustomMainIcon 属性中指定要使用的TIcon

with TTaskDialog.Create(self) do
  try
    Caption := 'About Rejbrand BookBase';
    Title := 'Rejbrand BookBase';
    CommonButtons := [tcbClose];
    Text := 'File Version: ' + GetFileVer(Application.ExeName) + #13#10#13#10'Copyright © 2011 Andreas Rejbrand'#13#10#13#10'http://english.rejbrand.se';
    Flags := [tfUseHiconMain, tfAllowDialogCancellation];
    CustomMainIcon := Application.Icon;
    Execute;
  finally
    Free;
  end

超链接

如果您只添加 tfEnableHyperlinks 标志,您甚至可以在对话框中使用类似 HTML 的超链接(在 TextFooter,ExpandedText):

with TTaskDialog.Create(self) do
  try
    Caption := 'About Rejbrand BookBase';
    Title := 'Rejbrand BookBase';
    CommonButtons := [tcbClose];
    Text := 'File Version: ' + GetFileVer(Application.ExeName) + #13#10#13#10'Copyright © 2011 Andreas Rejbrand'#13#10#13#10'<a href="http://english.rejbrand.se">http://english.rejbrand.se</a>';
    Flags := [tfUseHiconMain, tfAllowDialogCancellation, tfEnableHyperlinks];
    CustomMainIcon := Application.Icon;
    Execute;
  finally
    Free;
  end

但是请注意,当您单击该链接时没有任何反应。链接的动作必须手动实现,这当然是一件好事。为此,请响应OnHyperlinkClicked 事件,即TNotifyEvent。链接的URL(即a元素的href)存储在TTaskDialogURL公共属性中:

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;

procedure TForm1.FormCreate(Sender: TObject);
begin
  with TTaskDialog.Create(self) do
    try
      Caption := 'About Rejbrand BookBase';
      Title := 'Rejbrand BookBase';
      CommonButtons := [tcbClose];
      Text := 'File Version: ' + GetFileVer(Application.ExeName) + #13#10#13#10'Copyright © 2011 Andreas Rejbrand'#13#10#13#10'<a href="http://english.rejbrand.se">http://english.rejbrand.se</a>';
      Flags := [tfUseHiconMain, tfAllowDialogCancellation, tfEnableHyperlinks];
      OnHyperlinkClicked := TaskDialogHyperlinkClicked;
      CustomMainIcon := Application.Icon;
      Execute;
    finally
      Free;
    end
end;

页脚

您可以使用FooterFooterIcon 属性来创建页脚。 icon 属性接受与MainIcon 属性相同的值。

with TTaskDialog.Create(self) do
  try
    Caption := 'My Application';
    Title := 'A Question';
    Text := 'This is a really tough one...';
    CommonButtons := [tcbYes, tcbNo];
    MainIcon := tdiNone;
    FooterText := 'If you do this, then ...';
    FooterIcon := tdiWarning;
    Execute;
  finally
    Free;
  end

使用tfUseHiconFooter 标志和CustomFooterIcon 属性,您可以在页脚中使用任何自定义图标,就像您可以选择自己的主图标一样。

复选框

使用VerificationText 字符串属性,您可以在任务对话框的页脚添加一个复选框。复选框的标题是属性。

with TTaskDialog.Create(self) do
  try
    Caption := 'My Application';
    Title := 'A Question';
    Text := 'This is a really tough one...';
    CommonButtons := [tcbYes, tcbNo];
    MainIcon := tdiNone;
    VerificationText := 'Remember my choice';
    Execute;
  finally
    Free;
  end

您可以通过指定tfVerificationFlagChecked 标志来使复选框最初被选中。不幸的是,由于TTaskDialog 的VCL 实现中的错误(?),当Execute 返回时包含此标志并不能反映复选框的最终状态。为了跟踪复选框,应用程序因此需要记住初始状态并切换一个内部标志作为对每个OnVerificationClicked 事件的响应,每次在对话框模式期间更改复选框的状态时都会触发该事件。

单选按钮

单选按钮的实现方式类似于添加自定义按钮(或命令链接按钮):

with TTaskDialog.Create(self) do
  try
    Caption := 'My Application';
    Title := 'A Question';
    Text := 'This is a really tough one...';
    CommonButtons := [tcbOk, tcbCancel];
    MainIcon := tdiNone;
    with RadioButtons.Add do
      Caption := 'This is one option';
    with RadioButtons.Add do
      Caption := 'This is another option';
    with RadioButtons.Add do
      Caption := 'This is a third option';
    if Execute then
      if ModalResult = mrOk then
        ShowMessage(Format('You chose %d.', [RadioButton.Index]));
  finally
    Free;
  end

【讨论】:

  • 不错的文章。为额外的努力 +1。
  • +1 给@Chris。当有人受到很多批评时,你总是发表很好的评论(c.f. stackoverflow.com/questions/3017743/…)。应该有一个徽章,例如“友谊”或“支持”。
  • 自私的想法:你会考虑创建一个在 Windows XP 下优雅降级的组件吗?我喜欢 TMS 组件的想法,但我已经有一个第三方包,不想再添加一个...如果您创建一个小型 google 代码项目,我可以提供一些帮助... :-)跨度>
  • @Leonardo:也许你现在已经自己发现了它,但有SynTaskDialog。它的模拟并没有涵盖微软的任务对话框可以做的所有事情,它看起来有点粗糙,但它可以工作。
  • Embarcadero 应该使用您的代码并奖励您免费许可证。
【解决方案2】:

这是旧东西,但为了完整起见,我在这里添加:

Open Source SynTaskDialog unit for XP,Vista,Seven

TTaskDialog 单元在 XP(带 VCL)下工作,但在 Vista+ 下使用系统 TaskDialog。

【讨论】:

    【解决方案3】:

    TMS 有一个很好的包装器,它还模拟了在 XP 上运行时的新行为。这是一个快速插入。但它不是免费的,也不能真正回答您的“如何做”问题。

    http://www.tmssoftware.com/site/vtd.asp

    他们也有一些文章讨论对话框,如果你想制作自己的包装器,还有一些源代码可能对你有用。

    http://www.tmssoftware.com/site/atbdev5.asp

    http://www.tmssoftware.com/site/atbdev7.asp

    【讨论】:

    • 是的,我知道这个包装器,但我更喜欢在没有第三方组件的情况下做事。
    • 说实话,我不认为任务对话框在 XP 上看起来不错。他们看起来错位了。恕我直言,这样做的方法是在 Vista/7 上使用任务对话框,在 XP 上使用老式的 MessageBoxes,就像我在 specials.rejbrand.se/TTaskDialog 上所做的那样。
    • 但是,它不会破坏您在 XP 上的应用程序。即使安德烈亚斯不认为这是一个坏主意。其他专业软件社区对这样的限制并不友好。如果您的软件是玩具,那很好。对你来说,看起来好比完全的功能损坏更重要?
    • @Warren P:我所有的应用程序都可以在 Windows XP 上完美运行。我总是在 Vista/7 上使用TTaskDialog,在 XP 上使用MessageBox。如果您在 XP 上称其为“破坏”应用程序,那么这就是您(以及 Embarcadero 的?)的观点。
    • TMS 任务对话框在使用 VCL 样式时会出现一些丑陋的问题。
    【解决方案4】:

    这是我的简短文档:

    1. 不要使用它,除非您不希望您的应用程序在 XP 上运行。

    2. 建议改进 delphi doc wiki 内容,就像其他人所做的那样,但请注意短语“注意:任务对话框需要 Vista 或 Windows 7”。那是“不要使用它!”的代码。基本上,有人想到要完全支持新的 Windows Vista 对话框,而这样做的方式是编写只调用对话框 API 的包装器代码。由于没有为您提供后备功能,因此您在 XP 上不走运。

    【讨论】:

    • 我总是测试操作系统版本和视觉主题的可用性(是的,TTaskDialog 在没有启用 Aero 的情况下无法在 Vista/7 上运行),如果可能,请使用 TTaskDialog,以及普通MessageBox,如果不是,如specials.rejbrand.se/TTaskDialogTTaskDialog 美妙的视觉风格使这一切都值得额外的工作。 (但老实说,我真的觉得“今天谁在使用 XP?”)
    • 我认为责怪 Embarcadero 没有让 TTaskDialog 在 XP 上运行是不明智的,因为 TTaskDialog 只是操作系统 API 的包装器,而这对 Vista 来说是新的.是的,如果TTaskDialog 在 XP(或没有视觉主题)上进行一些自定义处理,以简化(略微)开发人员的生活(如果他们什么都不使用,这种简化就不会存在),也许会很好但本机 OS API),但我认为您不应该需要包装器来这样做。
    • 披露:我为 Embarcadero 工作。但我个人仍然不喜欢不适用于所有常见 Windows 版本的组件。如果你想写你的应用程序,最好不要在 XP 上工作。但请记住,stackoverflow 不仅与您和您的问题有关,还与稍后会来阅读此信息的人有关。所以投反对票。但其他人可能会出现并需要知道这一点。
    • @Warren,请参阅 Andreas 的文章。他的例子展示了如何让它很好地回退到 XP。
    • @Warren P,我认为投反对票是因为帖子的语气。看起来很啰嗦:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    相关资源
    最近更新 更多