【问题标题】:How to add a text node to a toast notification如何将文本节点添加到 toast 通知
【发布时间】:2015-08-19 20:44:49
【问题描述】:

此 Toast 通知在 XE8 和 Windows 10 的桌面上运行良好,但我不知道如何在通知中添加文本行。显示 iTitle 但不显示 iMessage。这对我来说是全新的,所以我不知道该追求哪个方向。

第五次修改......

Remy 出色的 show toast 程序是对原始 Embaracdero 代码的一大改进,但我认为 Remy 并未实际测试过代码,因为它不会按照编写的方式编译。我必须将 TWindowString 更改为 TWindowsString 并将 IXmlNode 更改为 Xml_Dom_IXmlNode 才能编译。

以下内容实际上可以编译,但会在 GetActivationFactory 函数中产生访问冲突。

如果我们能让它正确运行,这将是对原始 Embarcadero 代码的一大改进,并且应该对其他开发人员有价值。

 procedure TForm1.ShowToast(const AMessage: String; const ATitle: String = '');
{ Send a Toast Notification }
var
  LINotificationManagerStatics: IToastNotificationManagerStatics;
  LToast: IToastNotification;
  LToastFactory: IToastNotificationFactory;
  LToastNotifier: IToastNotifier;
  LToastTemplateType: ToastTemplateType;
  LAccepted: TAcceptedEventHandler;
  LXMLTemplate: Xml_Dom_IXmlDocument;
  iTextNode: Xml_Dom_IXmlNode;
  LTextNodeList: Xml_Dom_IXmlNodeList;

  function GetActivationFactory(const ClassId: String; const Iid: String): IInspectable;
  begin
    OleCheck(RoGetActivationFactory(TWindowsString(ClassId), TGUID.Create(Iid), Result));
   // This produces an access violation at run time
  end;

begin
  LINotificationManagerStatics := GetActivationFactory(SToastNotificationManager, '{50AC103F-D235-4598-BBEF-98FE4D1A3AD4}') as IToastNotificationManagerStatics;
  LToastNotifier := LINotificationManagerStatics.CreateToastNotifier(TWindowsString(Edit1.Text));
  if ATitle <> '' then begin
    LToastTemplateType := ToastTemplateType.ToastText02;
  end else begin
    LToastTemplateType := ToastTemplateType.ToastText01;
  end;
  LXMLTemplate := LINotificationManagerStatics.GetTemplateContent(LToastTemplateType);
  LTextNodeList := LXMLTemplate.getElementsByTagName(TWindowsString('text'));
  if ATitle <> '' then
  begin
    LTextNodeList.Item(0).AppendChild(LXMLTemplate.CreateTextNode(TWindowsString(ATitle)) as Xml_Dom_IXmlNode);
    iTextNode := LTextNodeList.Item(1);
  end else begin
    iTextNode := LTextNodeList.Item(0);
  end;
  iTextNode.AppendChild(LXMLTemplate.CreateTextNode(TWindowsString(AMessage)) as Xml_Dom_IXmlNode);
  LToastFactory := GetActivationFactory(SToastNotification, '{04124B20-82C6-4229-B109-FD9ED4662B53}') as IToastNotificationFactory;
  LToast := LToastFactory.CreateToastNotification(LXMLTemplate);
  LAccepted := TAcceptedEventHandler.Create;
  LToast.add_Activated(LAccepted);
  LToastNotifier.Show(LToast);
end;

【问题讨论】:

    标签: delphi delphi-xe8


    【解决方案1】:

    IXmlDocument.CreateTextNode() 创建并返回一个新的文本节点,但不将其添加到 XML 文档中。您必须单独添加它。这甚至在 Toast 文档中得到了证明:

    Quickstart: Sending a toast notification (HTML)

    Quickstart: Sending a toast notification (XAML)

    例如:

    var
      ...
      LTagName: HString;
    
    ...    
    if Succeeded(WindowsCreateString(PWideChar(iMessage), Length(iMessage), LString3)) then
    try
      if Succeeded(WindowsCreateString(PWideChar('text'), 4, LTagName)) then
      try
        LXMLTemplate.getElementsByTagName(LTagName).Item(0).AppendChild(LXMLTemplate.CreateTextNode(LString3) as IXmlNode);
        ...
      finally
        WindowsDeleteString(LTagName);
      end;
      ...
    finally
      WindowsDeleteString(LString3);
    end;
    ...
    

    或者,使用IXmlNode.InnerText 属性而不是IXmlDocument.CreateTextNode() 方法:

    LXMLTemplate.getElementsByTagName(LTagName).Item(0).InnerText := LString3;
    

    坦率地说,您的代码所基于的Embarcadero's example 有点混乱。它可能需要进行一些认真的清理工作。

    试试这样的:

    uses
      ...,
      System.SysUtils,
      System.Win.ComObj,
      Winapi.Data,
      System.WinrtHelpers; // see https://github.com/tgerdes/DelphiWinRT/blob/master/System.WinrtHelpers.pas
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ShowToast('The recycle bin is empty', 'Recycle Bin Is Empty');
    end;
    
    procedure TForm1.ShowToast(const AMessage: String; const ATitle: String = '');
    { Send a Toast Notification }
    var
      LINotificationManagerStatics: IToastNotificationManagerStatics;
      LToast: IToastNotification;
      LToastFactory: IToastNotificationFactory;
      LToastNotifier: IToastNotifier;
      LToastTemplateType: ToastTemplateType;
      LAccepted: TAcceptedEventHandler;
      LXMLTemplate: Xml_Dom_IXmlDocument;
      iTextNode: Xml_Dom_IXmlNode;
      LTextNodeList: Xml_Dom_IXmlNodeList;
    
      function GetActivationFactory(const ClassId: String; const Iid: String): IInspectable;
      begin
        OleCheck(RoGetActivationFactory(TWindowsString(ClassId), TGUID.Create(Iid), Result));
      end;
    
    begin
      LINotificationManagerStatics := GetActivationFactory(SToastNotificationManager, '{50AC103F-D235-4598-BBEF-98FE4D1A3AD4}') as IToastNotificationManagerStatics;
      LToastNotifier := LINotificationManagerStatics.CreateToastNotifier(TWindowString(Edit1.Text));
      if ATitle <> '' then begin
        LToastTemplateType := ToastTemplateType.ToastText02;
      end else begin
        LToastTemplateType := ToastTemplateType.ToastText01;
      end;
      LXMLTemplate := LINotificationManagerStatics.GetTemplateContent(LToastTemplateType);
      LTextNodeList := LXMLTemplate.getElementsByTagName(TWindowString('text'));
      if ATitle <> '' then
      begin
        LTextNodeList.Item(0).AppendChild(LXMLTemplate.CreateTextNode(TWindowString(ATitle)) as IXmlNode);
        iTextNode := LTextNodeList.Item(1);
      end else begin
        iTextNode := LTextNodeList.Item(0);
      end;
      iTextNode.AppendChild(LXMLTemplate.CreateTextNode(TWindowString(AMessage)) as IXmlNode);
      LToastFactory := GetActivationFactory(SToastNotification, '{04124B20-82C6-4229-B109-FD9ED4662B53}') as IToastNotificationFactory;
      LToast := LToastFactory.CreateToastNotification(LXMLTemplate);
      LAccepted := TAcceptedEventHandler.Create;
      LToast.add_Activated(LAccepted);
      LToastNotifier.Show(LToast);
    end;
    

    【讨论】:

    • 两种方式都不能用 XE8 编译?
    • 请更具体。
    • 查看我的 dcc32 错误已添加到您的帖子中。显然它不喜欢'文本'......因为那是指针在错误之后的位置。我尝试将语句分解为其组成部分以尝试解决,但我还没有成功。
    • 请不要编辑我的答案以包含编译器错误。我拒绝了那个编辑。请编辑您的原始问题,以显示您尝试过的更新代码及其报告的错误。
    • 显然,在调用getElementsByTagNames() 时,您必须调用WindowsCreateString()string 值转换为HString,因为这是编译器所抱怨的。你试过了吗?
    【解决方案2】:

    经过多次调试,我终于成功让 Toast 通知显示标题和消息。事实证明,我必须将 Remy 答案的修改版本与 Embaracdero 的一些原始演示代码结合使用才能使其正常工作。

    谢谢雷米!我不认为我会到达那里,但我最终做到了。 为了拯救其他试图这样做的人很多悲伤,我的工作代码如下所示:

    procedure TForm1.ShowToast(const AMessage: String; const ATitle: String = '');
    { Send a Toast Notification }
    var
      LINotificationManagerStatics: IToastNotificationManagerStatics;
      LToast: IToastNotification;
      LToastFactory: IToastNotificationFactory;
      LToastNotifier: IToastNotifier;
      LClassId: HString;
      LAccepted: TAcceptedEventHandler;
      LXMLTemplate: Xml_Dom_IXmlDocument;
      iTextNode: Xml_Dom_IXmlNode;
      LTextNodeList: Xml_Dom_IXmlNodeList;
      LTagName: HString;
      LTitle: HString;
      LMessage: HString;
    
      function GetActivationFactory(const ClassId: String; const Iid: String)
        : IInspectable;
      begin
        if Succeeded(WindowsCreateString(PWideChar(ClassId), Length(ClassId),
          LClassId)) then
          OleCheck(RoGetActivationFactory(LClassId, TGUID.Create(Iid), Result));
      end;
    
    begin
      LINotificationManagerStatics := GetActivationFactory
        (SToastNotificationManager, '{50AC103F-D235-4598-BBEF-98FE4D1A3AD4}')
        as IToastNotificationManagerStatics;
      if Succeeded(WindowsCreateString(PWideChar(NotificationTitle1.Text),
        Length(NotificationTitle1.Text), LClassId)) then
        LToastNotifier := LINotificationManagerStatics.CreateToastNotifier
          (LClassId);
      LXMLTemplate := LINotificationManagerStatics.GetTemplateContent
        (ToastTemplateType.ToastText02);
      if Succeeded(WindowsCreateString(PWideChar('text'), Length('text'), LTagName))
      then
        LTextNodeList := LXMLTemplate.getElementsByTagName(LTagName);
      if ATitle <> '' then
      begin
        if Succeeded(WindowsCreateString(PWideChar(ATitle), Length(ATitle), LTitle))
        then
          LTextNodeList.Item(0).AppendChild(LXMLTemplate.CreateTextNode(LTitle)
            as Xml_Dom_IXmlNode);
        iTextNode := LTextNodeList.Item(1);
      end
      else
      begin
        iTextNode := LTextNodeList.Item(0);
      end;
      if Succeeded(WindowsCreateString(PWideChar(AMessage), Length(AMessage),
        LMessage)) then
        iTextNode.AppendChild(LXMLTemplate.CreateTextNode(LMessage)
          as Xml_Dom_IXmlNode);
      LToastFactory := GetActivationFactory(SToastNotification,
        '{04124B20-82C6-4229-B109-FD9ED4662B53}') as IToastNotificationFactory;
      LToast := LToastFactory.CreateToastNotification(LXMLTemplate);
      LAccepted := TAcceptedEventHandler.Create;
      LToast.add_Activated(LAccepted);
      LToastNotifier.Show(LToast);
    end;
    

    用法:

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ShowToast(NotificationMessage1.Text, NotificationTitle1.Text);
    end;
    

    【讨论】:

      猜你喜欢
      • 2021-10-20
      • 1970-01-01
      • 1970-01-01
      • 2011-12-03
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多