Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Zabalené a rozbalené desktopové aplikace můžou posílat interaktivní app oznámení stejně jako aplikace pro Univerzální platformu Windows (UPW). To zahrnuje zabalené aplikace (viz
Pro aplikaci ve formě nepoužitého balíčku na ploše app však existuje několik speciálních kroků. To je způsobeno různými aktivačními schématy a chybějící identitou balíčku za běhu.
Note
Termín "toast oznámení" se nahrazuje "app oznámením". Oba tyto termíny odkazují na stejnou funkci Windows, ale v průběhu času postupně přestaneme používat výraz "toast oznámení" v dokumentaci.
Important
Pokud píšete UPW app, projděte si dokumentaci k UPW. Informace o jiných desktopových jazycích najdete v tématu Desktop C#.
Krok 1: Povolení sady Windows SDK
Pokud jste nepovolili sadu Windows SDK pro váš app, musíte to udělat jako první. Existuje několik klíčových kroků.
- Přidejte
runtimeobject.libk Další závislosti. - Zaměřit se na Windows SDK.
Klikněte pravým tlačítkem na projekt a vyberte Vlastnosti.
V horní nabídce Konfigurace vyberte Všechny konfigurace, aby se následující změna použila pro konfigurace Debug i Release.
V části Linker –> Vstup, přidejte runtimeobject.lib do Další závislosti.
Potom v části Obecnése ujistěte, že je verze Windows SDK nastavena na verzi 10.0 nebo novější.
Krok 2: Zkopírování kódu knihovny pro kompatibilitu
Zkopírujte soubor DesktopNotificationManagerCompat.h a DesktopNotificationManagerCompat.cpp z GitHubu do projektu. Kompatibilní knihovna abstrahuje většinu složitostí oznámení na ploše. Následující pokyny vyžadují kompatibilní knihovnu.
Pokud používáte předkompilované hlavičky, nezapomeňte vložit #include "stdafx.h" jako první řádek souboru DesktopNotificationManagerCompat.cpp.
Krok 3: Zahrňte soubory hlaviček a obory názvů
Zahrňte hlavičkový soubor kompatibilitní knihovny a hlavičkové soubory a obory názvů související s používáním API pro oznámení ve Windows.
#include "DesktopNotificationManagerCompat.h"
#include <NotificationActivationCallback.h>
#include <windows.ui.notifications.h>
using namespace ABI::Windows::Data::Xml::Dom;
using namespace ABI::Windows::UI::Notifications;
using namespace Microsoft::WRL;
Krok 4: Implementace aktivátoru
Musíte implementovat obslužnou rutinu pro app aktivaci oznámení, tak aby když uživatel klikne na vaše oznámení, app může provést určitou akci. Toto je vyžadováno, aby oznámení zůstalo v Centru akcí (protože na oznámení může být kliknuto i dny poté, co je váš app zavřen). Tuto třídu lze umístit kamkoli do projektu.
Implementujte rozhraní INotificationActivationCallback, jak je znázorněno níže, včetně UUID, a také volejte CoCreatableClass pro označení třídy jako vytvořitelnou pomocí COM. Pro UUID vytvořte jedinečný identifikátor GUID pomocí jednoho z mnoha online generátorů GUID. Tento identifikátor GUID CLSID (identifikátor třídy) je způsob, jakým Centrum akcí zjistí, jakou třídu má COM aktivovat.
// The UUID CLSID must be unique to your app. Create a new GUID if copying this code.
class DECLSPEC_UUID("replaced-with-your-guid-C173E6ADF0C3") NotificationActivator WrlSealed WrlFinal
: public RuntimeClass<RuntimeClassFlags<ClassicCom>, INotificationActivationCallback>
{
public:
virtual HRESULT STDMETHODCALLTYPE Activate(
_In_ LPCWSTR appUserModelId,
_In_ LPCWSTR invokedArgs,
_In_reads_(dataCount) const NOTIFICATION_USER_INPUT_DATA* data,
ULONG dataCount) override
{
// TODO: Handle activation
}
};
// Flag class as COM creatable
CoCreatableClass(NotificationActivator);
Krok 5: Registrace na platformě oznámení
Pak se musíte zaregistrovat na platformě oznámení. Existují různé kroky podle toho, zda je váš app zabalený nebo rozbalený. Pokud obojí podporujete, musíte provést obě sady kroků (není však nutné forkovat kód, protože to za vás zpracovává naše knihovna).
Packaged
Pokud je váš app zabalen (viz Vytvoření nového projektu pro balíček plochy WinUI 3app) nebo je zabalen s externím umístěním (viz Udělení identity balíčku balením s externím umístěním), nebo pokud podporujete obojí, přidejte v souboru Package.appxmanifest:
- Deklarace pro xmlns:com
- Deklarace pro xmlns:desktop
- V atributu IgnorableNamespaces jsou com a desktop
-
com:Extension pro aktivátor COM s identifikátorem GUID z kroku 4. Ujistěte se, že zahrnujete
Arguments="-ToastActivated", abyste věděli, že vaše spuštění proběhlo z app oznámení. - desktop:Extension pro windows.toastNotificationActivation pro deklaraci app ID aktivátoru oznámení (GUID z kroku 4).
Package.appxmanifest
<Package
...
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
IgnorableNamespaces="... com desktop">
...
<Applications>
<Application>
...
<Extensions>
<!--Register COM CLSID LocalServer32 registry key-->
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="YourProject\YourProject.exe" Arguments="-ToastActivated" DisplayName="Toast activator">
<com:Class Id="replaced-with-your-guid-C173E6ADF0C3" DisplayName="Toast activator"/>
</com:ExeServer>
</com:ComServer>
</com:Extension>
<!--Specify which CLSID to activate when toast clicked-->
<desktop:Extension Category="windows.toastNotificationActivation">
<desktop:ToastNotificationActivation ToastActivatorCLSID="replaced-with-your-guid-C173E6ADF0C3" />
</desktop:Extension>
</Extensions>
</Application>
</Applications>
</Package>
Unpackaged
Pokud váš app není přebalený (viz Vytvoření nového projektu pro nebalený desktop WinUI 3 app), nebo pokud podporujete obojí, musíte deklarovat ID modelu uživatele aplikace (AUMID) a toast aktivační CLSID (GUID z kroku 4) na zástupci vašeho app ve Startu.
Vyberte jedinečný identifikátor AUMID, který identifikuje vaši app. Obvykle to má podobu [CompanyName].[AppName]. Ale chcete zajistit, aby byla jedinečná ve všech aplikacích (takže můžete na konci přidat nějaké číslice).
Krok 5.1: Instalační program WiX
Pokud pro instalační program používáte WiX, upravte soubor Product.wxs a přidejte do zástupce nabídky Start dvě klávesové zkratky, jak je znázorněno níže. Ujistěte se, že váš identifikátor GUID z kroku 4 je uzavřen v {}, jak je uvedeno níže.
Product.wxs
<Shortcut Id="ApplicationStartMenuShortcut" Name="Wix Sample" Description="Wix Sample" Target="[INSTALLFOLDER]WixSample.exe" WorkingDirectory="INSTALLFOLDER">
<!--AUMID-->
<ShortcutProperty Key="System.AppUserModel.ID" Value="YourCompany.YourApp"/>
<!--COM CLSID-->
<ShortcutProperty Key="System.AppUserModel.ToastActivatorCLSID" Value="{replaced-with-your-guid-C173E6ADF0C3}"/>
</Shortcut>
Important
Chcete-li skutečně používat oznámení, musíte před normálním laděním jednou nainstalovat app pomocí instalátoru, aby byl k dispozici zástupce Start s vaším AUMID a CLSID. Po zobrazení zástupce Start můžete ladit pomocí klávesy F5 ze sady Visual Studio.
Krok 5.2: Registrace serveru AUMID a serveru COM
Pak, bez ohledu na instalační program, ve app spouštěcím kódu (před voláním rozhraní API pro oznámení) volejte metodu RegisterAumidAndComServer a zadejte třídu aktivátoru oznámení ze kroku č. 4 a výše použité AUMID.
// Register AUMID and COM server (for a packaged app, this is a no-operation)
hr = DesktopNotificationManagerCompat::RegisterAumidAndComServer(L"YourCompany.YourApp", __uuidof(NotificationActivator));
Pokud vaše app podporuje jak zabalené, tak rozbalené nasazení, můžete tuto metodu bez obav volat kdykoli. Pokud spouštíte zabalené (tj. s identitou balíčku za běhu), tato metoda se jednoduše okamžitě vrátí. Není potřeba váš kód forkovat.
Tato metoda umožňuje volat kompatibilní rozhraní API pro odesílání a správu oznámení, aniž byste museli neustále poskytovat AUMID. A vloží klíč registru LocalServer32 pro server COM.
Krok 6: Registrace aktivátoru COM
U zabalených i rozbalených aplikací musíte zaregistrovat typ aktivátoru oznámení, abyste mohli zpracovávat toast aktivace.
V úvodním appkódu zavolejte následující metodu RegisterActivator. Abyste mohli přijímat jakékoliv toast aktivace, musí být toto provedeno.
// Register activator type
hr = DesktopNotificationManagerCompat::RegisterActivator();
Krok 7: Odeslání oznámení
Odeslání oznámení je shodné s aplikacemi pro UWP, s tím rozdílem, že k vytvoření ToastNotifierpoužijete DesktopNotificationManagerCompat. Kompatibilní knihovna automaticky zpracovává rozdíl mezi zabalenými a rozbalenými aplikacemi, takže není potřeba upravovat kód samostatně. U rozbaleného appbalíčku ukládá knihovna compat do mezipaměti AUMID, kterou jste zadali, když jste volali RegisterAumidAndComServer , takže se nemusíte starat o to, kdy poskytnout nebo nezadávat AUMID.
Ujistěte se, že používáte vazbu ToastGeneric, jak je uvedeno níže, protože starší šablony oznámení Windows 8.1 toast neaktivují aktivátor oznámení COM, který jste vytvořili v kroku 4.
Important
Image HTTP se podporují jenom v zabalených aplikacích, které mají v manifestu funkci internetu. Rozbalené aplikace nepodporují http obrázky; Musíte stáhnout obrázek do místních app dat a odkazovat na něj místně.
// Construct XML
ComPtr<IXmlDocument> doc;
hr = DesktopNotificationManagerCompat::CreateXmlDocumentFromString(
L"<toast><visual><binding template='ToastGeneric'><text>Hello world</text></binding></visual></toast>",
&doc);
if (SUCCEEDED(hr))
{
// See full code sample to learn how to inject dynamic text, buttons, and more
// Create the notifier
// Desktop apps must use the compat method to create the notifier.
ComPtr<IToastNotifier> notifier;
hr = DesktopNotificationManagerCompat::CreateToastNotifier(¬ifier);
if (SUCCEEDED(hr))
{
// Create the notification itself (using helper method from compat library)
ComPtr<IToastNotification> toast;
hr = DesktopNotificationManagerCompat::CreateToastNotification(doc.Get(), &toast);
if (SUCCEEDED(hr))
{
// And show it!
hr = notifier->Show(toast.Get());
}
}
}
Important
Desktopové aplikace nemůžou používat starší toast šablony (například ToastText02). Aktivace starších šablon selže, když je zadán identifikátor CLSID modelu COM. Musíte použít šablony Windows ToastGeneric, jak je vidět výše.
Krok 8: Proveďte aktivaci
Když uživatel klikne na oznámení app nebo tlačítka v oznámení, vyvolá se metoda Activate třídy NotificationActivator .
Uvnitř metody Activate můžete analyzovat argy, které jste zadali v oznámení, a získat uživatelský vstup, který uživatel zadal nebo vybral, a pak odpovídajícím způsobem aktivovat app .
Note
Metoda Activate je volána na odděleném vlákně, mimo hlavní vlákno.
// The GUID must be unique to your app. Create a new GUID if copying this code.
class DECLSPEC_UUID("replaced-with-your-guid-C173E6ADF0C3") NotificationActivator WrlSealed WrlFinal
: public RuntimeClass<RuntimeClassFlags<ClassicCom>, INotificationActivationCallback>
{
public:
virtual HRESULT STDMETHODCALLTYPE Activate(
_In_ LPCWSTR appUserModelId,
_In_ LPCWSTR invokedArgs,
_In_reads_(dataCount) const NOTIFICATION_USER_INPUT_DATA* data,
ULONG dataCount) override
{
std::wstring arguments(invokedArgs);
HRESULT hr = S_OK;
// Background: Quick reply to the conversation
if (arguments.find(L"action=reply") == 0)
{
// Get the response user typed.
// We know this is first and only user input since our toasts only have one input
LPCWSTR response = data[0].Value;
hr = DesktopToastsApp::SendResponse(response);
}
else
{
// The remaining scenarios are foreground activations,
// so we first make sure we have a window open and in foreground
hr = DesktopToastsApp::GetInstance()->OpenWindowIfNeeded();
if (SUCCEEDED(hr))
{
// Open the image
if (arguments.find(L"action=viewImage") == 0)
{
hr = DesktopToastsApp::GetInstance()->OpenImage();
}
// Open the app itself
// User might have clicked on app title in Action Center which launches with empty args
else
{
// Nothing to do, already launched
}
}
}
if (FAILED(hr))
{
// Log failed HRESULT
}
return S_OK;
}
~NotificationActivator()
{
// If we don't have window open
if (!DesktopToastsApp::GetInstance()->HasWindow())
{
// Exit (this is for background activation scenarios)
exit(0);
}
}
};
// Flag class as COM creatable
CoCreatableClass(NotificationActivator);
Pokud chcete správně podporovat spuštění zatímco je app uzavřený, bylo by dobré zjistit ve funkci WinMain, jestli se spouštíte z app oznámení, nebo ne. Pokud se spustí z oznámení, zobrazí se spouštěcí zpráva "-ToastActivated". Až to uvidíte, měli byste přestat provádět jakýkoli normální aktivační kód pro spuštění a v případě potřeby povolit, aby funkce NotificationActivator zpracovávala spouštění oken.
// Main function
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR cmdLineArgs, _In_ int)
{
RoInitializeWrapper winRtInitializer(RO_INIT_MULTITHREADED);
HRESULT hr = winRtInitializer;
if (SUCCEEDED(hr))
{
// Register AUMID and COM server (for a packaged app, this is a no-operation)
hr = DesktopNotificationManagerCompat::RegisterAumidAndComServer(L"WindowsNotifications.DesktopToastsCpp", __uuidof(NotificationActivator));
if (SUCCEEDED(hr))
{
// Register activator type
hr = DesktopNotificationManagerCompat::RegisterActivator();
if (SUCCEEDED(hr))
{
DesktopToastsApp app;
app.SetHInstance(hInstance);
std::wstring cmdLineArgsStr(cmdLineArgs);
// If launched from toast
if (cmdLineArgsStr.find(TOAST_ACTIVATED_LAUNCH_ARG) != std::string::npos)
{
// Let our NotificationActivator handle activation
}
else
{
// Otherwise launch like normal
app.Initialize(hInstance);
}
app.RunMessageLoop();
}
}
}
return SUCCEEDED(hr);
}
Posloupnost aktivací událostí
Aktivační sekvence je následující...
Pokud už app máte spuštěný:
- Aktivace ve vašem NotificationActivatoru je volána
Pokud vaše app není spuštěné:
- Váš app soubor EXE je spuštěn a získáte parametry příkazového řádku "-ToastActivated".
- Aktivace ve vašem NotificationActivatoru je volána
Aktivace popředí vs. pozadí
U desktopových aplikací se aktivace na popředí a na pozadí zpracovává stejně – volá se váš COM aktivátor. Záleží na kódu vašeho app, jestli se má zobrazit okno nebo jednoduše provést nějakou práci a pak ukončit. Proto zadání aktivačního typupozadí v app obsahu oznámení nezmění chování.
Krok 9: Odebrání a správa oznámení
Odebrání a správa oznámení je shodné s aplikacemi pro UPW. Doporučujeme ale použít naši kompat knihovnu k získání DesktopNotificationHistoryCompat , takže si nemusíte dělat starosti s poskytováním AUMID pro stolní počítač app.
std::unique_ptr<DesktopNotificationHistoryCompat> history;
auto hr = DesktopNotificationManagerCompat::get_History(&history);
if (SUCCEEDED(hr))
{
// Remove a specific toast
hr = history->Remove(L"Message2");
// Clear all toasts
hr = history->Clear();
}
Krok 10: Nasazení a ladění
Aby bylo možné nasadit a ladit váš zabalený app, přečtěte si Spustit, ladit a testovat zabalenou desktopovou aplikaci app.
Pokud chcete nasadit a ladit plochu app, musíte před normálním laděním nainstalovat app instalační program prostřednictvím instalačního programu, aby byl k dispozici zástupce Start s AUMID a CLSID. Po zobrazení zástupce Start můžete ladit pomocí klávesy F5 ze sady Visual Studio.
Pokud se vaše oznámení jednoduše nezobrazí na ploše app (a nejsou vyvolány žádné výjimky), pravděpodobně to znamená, že zástupce Start není přítomen (nainstalujte svůj app pomocí instalačního programu) nebo že AUMID, který jste použili v kódu, neodpovídá AUMID ve zástupci Start.
Pokud se vaše oznámení zobrazí, ale v Centru akcí se neuchovávají (po zavření automaticky otevíraného okna zmizí), znamená to, že jste aktivátor com neimplementovali správně.
Pokud jste nainstalovali zabalenou i rozbalenou verzi aplikace app, mějte na paměti, že zabalená aplikace app nahradí rozbalenou verzi aplikace app při zpracování aktivací toast. To znamená, že app oznámení z rozbaleného app spustí balíčkovaný app, když na ně kliknete. Odinstalace balíčku app spustí návrat k aktivaci rozbaleného app.
Pokud obdržíte HRESULT 0x800401f0 CoInitialize has not been called., nezapomeňte ve své CoInitialize(nullptr) zavolat app před voláním rozhraní API.
Pokud se vám při volání rozhraní API pro kompatibilitu zobrazí HRESULT 0x8000000e A method was called at an unexpected time., pravděpodobně jste neprovedli volání požadovaných metod Register (nebo, pokud je app zabalený, váš app aktuálně neběží v rámci zabaleného kontextu).
Pokud dojde k mnoha chybám kompilace unresolved external symbol, pravděpodobně jste zapomněli přidat runtimeobject.lib do další závislosti v kroku 1 (nebo jste ho přidali pouze do konfigurace ladění a ne do konfigurace vydané verze).
Zpracování starších verzí Windows
Pokud podporujete Windows 8.1 nebo nižší verze, měli byste za běhu zkontrolovat, zda běžíte na Windows, než zavoláte jakékoli rozhraní DesktopNotificationManagerCompat API nebo odešlete informační oznámení ToastGeneric.
Windows 8 zavedl toast oznámení, ale používal starší toast šablony, jako je ToastText01. Aktivace byla zpracována událostí Aktivováno třídy ToastNotification, protože oznámení byla pouze krátkými vyskakovacími okny, která se neukládala. Windows 10 zavedl interaktivní toasty ToastGenerica také představil Centrum akcí, kde se oznámení uchovávají po několik dnů. Zavedení Centra akcí vyžadovalo zavedení COM aktivátoru, aby toast mohlo být aktivováno i dny po jeho vytvoření.
| OS | ToastGeneric | Aktivátor COM | Starší toast šablony |
|---|---|---|---|
| Platforma: Windows 10 a novější | Supported | Supported | Podporováno (ale neaktivuje se server COM) |
| Windows 8.1 / 8 | N/A | N/A | Supported |
| Windows 7 a nižší | N/A | N/A | N/A |
Pokud chcete zkontrolovat, jestli používáte Windows 10 nebo novější, zahrňte hlavičku <VersionHelpers.h> a zkontrolujte metodu IsWindows10OrGreater . Pokud se vrátí true, pokračujte voláním všech metod popsaných v této dokumentaci.
#include <VersionHelpers.h>
if (IsWindows10OrGreater())
{
// Running on Windows 10 or later, continue with sending toasts!
}
Známé problémy
OPRAVENO: App se nestane aktivním po kliknutí na toast: V buildech 15063 a starších se práva v popředí nepřenesla do vaší aplikace, když jsme aktivovali server COM. Proto by se prostě app blikalo, když jste se ho pokusili přesunout do popředí. Pro tento problém nebylo žádné alternativní řešení. Opravili jsme to v buildech 16299 nebo novějších.
Resources
Windows developer