2017-08-24 14 views
2

私はデルファイでデスクトップ上で開発しています。 ToastGeneric型の通知でトースト通知を作成したい。 LToastFactory.CreateToastNotification(LXMLTemplate);ToastGenericでデルファイでトースト通知を作成するには

また、私は https://docs.microsoft.com/en-us/windows/uwp/controls-and-patterns/tiles-and-notifications-adaptive-interactive-toasts

のようにXMLを使用しています私の質問は、私はこのXMLを受け入れるようにデルファイを作ることができるかですが、私はXml_Dom_IXmlDocument型にその文字列を変換する方法を発見していません。

答えて

0

私は同じ問題を抱えていました。

私の目的は、toastGenericを使用するDelphiからToast通知を作成することでした。しかし、xmlを操作することによってこれを行う言語では例が見つかりませんでした。すべての例では、Delphiからアクセスできないクラスが使用されています。

私の解決策は、標準テンプレートを作成し、その標準テンプレートのxmlをカスタムテンプレートに必要なxmlで上書きすることでした。以下は、あなたにアイデアを与えるべきいくつかのDelphiコードです。それは完全なコンソールアプリです。このコードはDelphi 10.2 Tokyoでコンパイルされます。以前のバージョンではいくつか調整が必要な場合があります。 OverwriteToastTemplateXML機能に興味があります。 「ヒーロー」画像JPGファイルに私のXML内の参照を注意http://blog.marcocantu.com/blog/2015-june-windows10-notifications-vcl-winrt.html

私のコードはここにマルコ・カントゥのブログ記事の最後のコメントで参照標準トーストテンプレートの例を中心に基づいていました。通知が完全に機能するようにするには、c:\ notifications \ hero.jpgにjpgがあることを確認するか、xmlのその行をコメントアウトしてください。

XMLストリングをカスタムトーストテンプレートに変換するだけでなく、コードはトーストテンプレートを文字列に変換して戻します。これはデバッグに役立ちます。これはToastTemplateToString関数です。これらは、元の例に対する主な機能上の変更です。私の理解のために、サンプルコードの構造も変更しました。可変スコープと各コード行が他のコード行とどのように関係しているかがより明確になるようにしました。

これがうまくいくかどうか教えてください - 私はトースト通知がDelphiから難しい作業であることを発見しました!

乾杯

スティーブ

program ConsoleNotifier; 

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    System.SysUtils, 

    // Required to create the Toast Notification 
    WinAPI.WinRT, 
    WinAPI.DataRT, 
    WinAPI.UI.Notifications, 
    WinAPI.ActiveX, 
    WinAPI.CommonTypes, 

    // Required for creating the Desktop Shell Link 
    WinAPI.PropKey, 
    WinAPI.PropSys, 
    WinAPI.ShlObj, 
    System.Win.ComObj, 
    Windows 
    ; 

function CreateDesktopShellLink(const TargetName: string): Boolean; 

    function GetStartMenuFolder: string; 
    var 
    Buffer: array [0 .. MAX_PATH - 1] of Char; 
    begin 
    Result := ''; 
    GetEnvironmentVariable(PChar('APPDATA'), Buffer, MAX_PATH - 1); 
    Result := Buffer + '\Microsoft\Windows\Start Menu\Programs\Desktop Delphi Toasts App.lnk'; 
    end; 

var 
    IObject: IUnknown; 
    ISLink: IShellLink; 
    IPFile: IPersistFile; 
    LinkName: string; 

    LStore: WinAPI.PropSys.IPropertyStore; 
    LValue: TPropVariant; 
begin 
    Result := False; 

    IObject := CreateComObject(CLSID_ShellLink); 
    ISLink := IObject as IShellLink; 
    IPFile := IObject as IPersistFile; 
    LStore := IObject as WinAPI.PropSys.IPropertyStore; 

    with ISLink 
    do begin 
    SetPath(PChar(ParamStr(0))); 
    end; 
    ISLink.SetArguments(PChar('')); 

    if Succeeded(InitPropVariantFromStringAsVector(PWideChar('Delphi.DesktopNotification.Sample'), LValue)) 
    then begin 
    if Succeeded(LStore.SetValue(PKEY_AppUserModel_ID, LValue)) 
    then LStore.Commit; 
    end; 

    LinkName := GetStartMenuFolder; 

    if not FileExists(LinkName) 
    then 
    if IPFile.Save(PWideChar(LinkName), True) = S_OK 
    then Result := True; 
end; 

function HStr(Value:String): HString; 
begin 
    if NOT Succeeded(
    WindowsCreateString(PWideChar(Value), Length(Value), Result) 
) 
    then raise Exception.CreateFmt('Unable to create HString for %s', [ Value ]); 
end; 

function ToastTemplateToString(Const Template:Xml_Dom_IXmlDocument): String; 

    function HStringToString(Src: HSTRING): String; 
    var 
    c: Cardinal; 
    begin 
    c := WindowsGetStringLen(Src); 
    Result := WindowsGetStringRawBuffer(Src, @c); 
    end; 

begin 
    Result := HStringToString(
    (Template.DocumentElement as Xml_Dom_IXmlNodeSerializer).GetXml 
); 
end; 

function GetFactory(Const Name:String; Const GUID:String): IInspectable; 
var 
    FactoryHString : HString; 
    FactoryGUID : TGUID; 
begin 
    FactoryHString := HStr(Name); 
    try 
    FactoryGUID := TGUID.Create(GUID); 

    if NOT Succeeded(
     RoGetActivationFactory(FactoryHString, FactoryGUID, Result) 
    ) 
    then raise Exception.CreateFmt('Error creating factory: %s %s', [ Name, GUID ]); 
    finally 
    WindowsDeleteString(FactoryHString); 
    end; 
end; 

procedure OverwriteToastTemplateXML(Const Template: Xml_Dom_IXmlDocument; Const XML:String); 
var 
    hXML: HSTRING; 
begin 
    hXML := HStr(XML); 
    try 
    (Template as Xml_Dom_IXmlDocumentIO).LoadXml(hXML); 
    finally 
    WindowsDeleteString(hXML); 
    end; 
end; 

procedure SteveNotification(Const AppID:String; Const XML:String); 
var 
    ToastNotificationManagerStatics : IToastNotificationManagerStatics; 
    ToastTemplate     : Xml_Dom_IXmlDocument; 
    LToastNotification    : IToastNotification; 
    ToastNotificationManagerFactory : IInspectable; 
    ToastNotificationFactory  : IInspectable; 
    hAppID       : HString; 
begin 
    ToastNotificationManagerFactory := GetFactory(sToastNotificationManager, '{50AC103F-D235-4598-BBEF-98FE4D1A3AD4}'); 
    ToastNotificationManagerStatics := IToastNotificationManagerStatics(ToastNotificationManagerFactory); 
    ToastTemplate := ToastNotificationManagerStatics.GetTemplateContent(ToastTemplateType.ToastText01); 

    OverwriteToastTemplateXML(ToastTemplate, XML); 

    WriteLn('XML: ', ToastTemplateToString(ToastTemplate)); 

    ToastNotificationFactory := GetFactory(SToastNotification, '{04124B20-82C6-4229-B109-FD9ED4662B53}'); 

    LToastNotification := IToastNotificationFactory(ToastNotificationFactory).CreateToastNotification(ToastTemplate); 

    hAppID := HStr(AppID); 
    try 
    ToastNotificationManagerStatics 
    .CreateToastNotifier(hAppID) 
    .Show(LToastNotification); 
    finally 
    WindowsDeleteString(hAppID); 
    end; 
end; 

Const 
    AppID = 'My Application ID'; 
    XML = '<toast activationType="protocol" launch="http://www.ecutek.com" >' 
     + ' <visual>' 
     + ' <binding template="ToastGeneric">' 
     + '  <text>Body Text ABC</text>' 
     + '  <text>More Text</text>' 
     + '  <image placement="hero" src="file:///c:\notifications\hero.jpg"/>' 
     + ' </binding>' 
     + ' </visual>' 
     + ' <actions>' 
     + ' <action content="Open Google" activationType="protocol" arguments="http://www.google.com" />' 
     + ' </actions>' 
     + '</toast>'; 

var 
    c : char; 
begin 
    try 
    if TOSVersion.Major < 10 
    then raise Exception.Create('Windows 10 Required'); 

    RoInitialize(RO_INIT_MULTITHREADED); 

    CreateDesktopShellLink(ParamStr(0)); 

    SteveNotification(AppID, XML); 

    // Wait for a KeyPress 
    Read(c); write(c); 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
end. 
+0

これは有望に見えたが、残念ながらベルリンでは動作しませんでした。コードをステップ実行すると、呼び出しは成功し、エラーは生成されません。コンソールアプリケーションがWindowsの通知送信者として登録されていないことに気付きました。これを行うために必要なコードがありますか? – lowrider

関連する問題