Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
Les applications de bureau empaquetées et non empaquetées peuvent envoyer des notifications interactives comme les applications de plateforme Windows universelle app (UWP). Cela inclut les applications empaquetées (voir Créer un projet pour un bureau appWinUI 3 empaqueté) ; applications empaquetées avec emplacement externe (voir Accorder l’identité du package en empaquetant avec un emplacement externe) ; et applications non empaquetées (voir Créer un projet pour un bureau appWinUI 3 non empaqueté).
Toutefois, pour un ordinateur de bureau app non empaqueté, il existe quelques étapes spéciales. Cela est dû aux différents schémas d’activation et à l’absence d’identité de package au moment de l’exécution.
Note
Le terme «toast notification » est remplacé par «app notification ». Ces termes font tous deux référence à la même fonctionnalité de Windows, mais au fil du temps, nous allons abandonner progressivement l'utilisation de «toast notification » dans la documentation.
Important
Si vous écrivez un UWP app, consultez la documentation UWP. Pour d’autres langages de bureau, consultez Desktop C#.
Étape 1 : Activer le Kit de développement logiciel (SDK) Windows
Si vous n’avez pas activé le Kit de développement logiciel (SDK) Windows pour votre appapplication, vous devez d’abord le faire. Il existe quelques étapes clés.
- Ajoutez
runtimeobject.libà dépendances supplémentaires. - Ciblez le Kit de développement logiciel (SDK) Windows.
Cliquez avec le bouton droit sur votre projet et sélectionnez Propriétés.
Dans le menu supérieur Configuration, sélectionnez Toutes les configurations afin que la modification suivante soit appliquée à la fois à Debug et à Release.
Sous Éditeur de liens -> Entrée, ajoutez runtimeobject.lib aux dépendances supplémentaires.
Ensuite, sous Général, vérifiez que la version du SDK Windows est définie sur la version 10.0 ou ultérieure.
Étape 2 : Copier le code de la bibliothèque compat
Copiez le fichier DesktopNotificationManagerCompat.h et DesktopNotificationManagerCompat.cpp à partir de GitHub dans votre projet. La bibliothèque compat extrait une grande partie de la complexité des notifications de bureau. Les instructions suivantes nécessitent la bibliothèque compat.
Si vous utilisez des en-têtes précompilés, veillez à #include "stdafx.h" comme première ligne du fichier DesktopNotificationManagerCompat.cpp.
Étape 3 : Inclure les fichiers d’en-tête et les namespaces
Incluez le fichier d’en-tête de la bibliothèque compat, ainsi que les fichiers d’en-tête et les espaces de noms liés à l’utilisation des API de notification 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;
Étape 4 : Implémenter l’activateur
Vous devez implémenter un gestionnaire pour l’activation de la notification, afin que vous puissiez faire quelque chose lorsque l’utilisateur clique sur votre notification. Cela est requis pour que votre notification persiste dans le Centre de notifications (car la notification peut être cliquée quelques jours plus tard lorsque votre app est fermé). Cette classe peut être placée n’importe où dans votre projet.
Implémentez l'interface INotificationActivationCallback comme indiqué ci-dessous, y compris un UUID, et appelez également CoCreatableClass pour marquer votre classe comme COM créable. Pour votre UUID, créez un GUID unique à l’aide de l’un des nombreux générateurs de GUID en ligne. Ce GUID CLSID (identifiant de classe) permet à Action Center de savoir quelle classe doit être activée par COM.
// 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);
Étape 5 : S’inscrire auprès de la plateforme de notification
Ensuite, vous devez vous inscrire auprès de la plateforme de notification. Il existe différentes étapes selon que votre app package est empaqueté ou non empaqueté. Si vous prenez en charge les deux, vous devez effectuer les deux ensembles d’étapes (toutefois, il n’est pas nécessaire de fork votre code, car notre bibliothèque gère cela pour vous).
Packaged
Si votre app fichier est packagé (voir Créer un projet pour un bureau appWinUI 3 packagé) ou packagé avec un emplacement externe (voir Accorder une identité de package en empaquetant avec un emplacement externe), ou si vous prenez en charge les deux, puis, dans votre package.appxmanifest, ajoutez :
- Déclaration pour xmlns:com
- Déclaration pour xmlns:desktop
- Dans l’attribut IgnorableNamespaces, com et desktop
-
com :Extension pour l’activateur COM à l’aide du GUID de l’étape 4. Veillez à inclure l’élément
Arguments="-ToastActivated"afin que vous sachiez que votre lancement provient d’une app notification - desktop :Extension vers windows.toastNotificationActivation afin de déclarer votre CLSID pour l’activation de notification (le GUID de l’étape 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
Si app n'est pas empaqueté (voir Créer un projet WinUI 3 de bureau non empaqueté app), ou si vous prenez en charge les deux, vous devez déclarer votre ID de modèle utilisateur d'application (AUMID) et toast l'activateur CLSID (le GUID de l'étape 4) sur le raccourci de votre application dans le menu Démarrer.
Choisissez un AUMID unique qui identifiera votre app. Il s’agit généralement de [CompanyName]. [AppName]. Mais vous souhaitez vous assurer qu’il est unique dans toutes les applications (n’hésitez donc pas à ajouter des chiffres à la fin).
Étape 5.1 : Programme d’installation De WiX
Si vous utilisez WiX pour votre programme d’installation, modifiez le fichier Product.wxs pour ajouter les deux propriétés de raccourci à votre raccourci de menu Démarrer, comme indiqué ci-dessous. Assurez-vous que votre GUID de l’étape 4 est placé dans {} comme indiqué ci-dessous.
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
Pour utiliser réellement des notifications, vous devez installer votre app une fois via le programme d’installation avant de déboguer normalement, afin que le raccourci Démarrer avec votre AUMID et CLSID soit présent. Une fois le raccourci Démarrer présent, vous pouvez déboguer à l’aide de F5 à partir de Visual Studio.
Étape 5.2 : Inscrire le serveur AUMID et COM
Ensuite, quel que soit votre programme d’installation, dans votre appcode de démarrage (avant d’appeler des API de notification), appelez la méthode RegisterAumidAndComServer , en spécifiant votre classe d’activateur de notification à partir de l’étape 4 et de votre AUMID utilisée ci-dessus.
// Register AUMID and COM server (for a packaged app, this is a no-operation)
hr = DesktopNotificationManagerCompat::RegisterAumidAndComServer(L"YourCompany.YourApp", __uuidof(NotificationActivator));
Si votre composant app prend en charge le déploiement empaqueté et non empaqueté, n’hésitez pas à appeler cette méthode dans tous les cas. Si vous exécutez empaqueté (autrement dit, avec l’identité du package au moment de l’exécution), cette méthode retourne simplement immédiatement. Il n’est pas nécessaire de forker votre code.
Cette méthode vous permet d’appeler les API de compatibilité pour envoyer et gérer des notifications sans avoir à fournir constamment votre AUMID. Il insère la clé de Registre LocalServer32 pour le serveur COM.
Étape 6 : Inscrire l’activateur COM
Pour les applications empaquetées et non empaquetées, vous devez inscrire votre type d’activateur de notification afin de pouvoir gérer toast les activations.
Dans votre appcode de démarrage, appelez la méthode RegisterActivator suivante. Cela doit être appelé pour que vous receviez une quelconque activation toast.
// Register activator type
hr = DesktopNotificationManagerCompat::RegisterActivator();
Étape 7 : Envoyer une notification
L’envoi d’une notification est identique aux applications UWP, sauf que vous utiliserez DesktopNotificationManagerCompat pour créer un ToastNotifier. La bibliothèque compat gère automatiquement la différence entre les applications empaquetées et non empaquetées. Vous n’avez donc pas besoin de fork votre code. Pour un package non empaqueté app, la bibliothèque compat met en cache l’AUMID que vous avez fournie lorsque vous avez appelé RegisterAumidAndComServer afin que vous n’ayez pas à vous soucier du moment où fournir ou ne pas fournir l’AUMID.
Veillez à utiliser la liaison ToastGeneric comme indiqué ci-dessous, car les modèles de notification Windows 8.1 toast hérités n’activent pas l’activateur de notification COM que vous avez créé à l’étape 4.
Important
Les images HTTP sont prises en charge uniquement dans les applications empaquetées qui ont la fonctionnalité Internet dans leur manifeste. Les applications non empaquetées ne prennent pas en charge les images HTTP ; vous devez télécharger l’image sur vos données locales app et les référencer localement.
// 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
Les applications de bureau ne peuvent pas utiliser de modèles hérités toast (tels que ToastText02). L’activation des modèles hérités échoue lorsque le CLSID COM est spécifié. Vous devez utiliser les modèles Windows ToastGeneric, comme indiqué ci-dessus.
Étape 8 : Gérer l’activation
Lorsque l’utilisateur clique sur votre app notification ou sur des boutons dans la notification, la méthode Activate de votre classe NotificationActivator est appelée.
Dans la méthode Activate, vous pouvez analyser les arguments que vous avez spécifiés dans la notification et obtenir l’entrée utilisateur que l’utilisateur a tapé ou sélectionné, puis activer vos app données en conséquence.
Note
La méthode Activate est appelée sur un fil d'exécution distinct de votre fil d'exécution principal.
// 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);
Pour bien prendre en charge le lancement alors que votre app est fermé, dans votre fonction WinMain, vous devez déterminer si vous êtes lancé à partir d’une app notification ou non. S’il est lancé à partir d’une notification, un argument de lancement est « -ToastActivated ». Lorsque vous voyez cela, vous devez arrêter d’exécuter n’importe quel code d’activation de lancement normal et autoriser votre NotificationActivator à gérer le lancement de windows si nécessaire.
// 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);
}
Séquence d’activation d’événements
La séquence d’activation est la suivante...
Si votre app est déjà en cours :
- Activate est appelé dans votre NotificationActivator
Si votre application app ne fonctionne pas :
- Votre app exe est lancé, vous obtenez un argument de ligne de commande « -ToastActivated »
- Activate est appelé dans votre NotificationActivator
Activation en avant-plan ou en arrière-plan
Pour les applications de bureau, l’activation au premier plan et en arrière-plan est gérée de façon identique : votre activateur COM est appelé. C’est à votre appcode de décider s’il faut afficher une fenêtre ou simplement effectuer un travail, puis quitter. Par conséquent, la spécification d’un type d’activationd’arrière-plan dans votre app contenu de notification ne modifie pas le comportement.
Étape 9 : Supprimer et gérer les notifications
La suppression et la gestion des notifications sont identiques aux applications UWP. Toutefois, nous vous recommandons d’utiliser notre bibliothèque compat pour obtenir un DesktopNotificationHistoryCompat afin que vous n’ayez pas à vous soucier de fournir l’AUMID pour un bureau 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();
}
Étape 10 : Déploiement et débogage
Pour déployer et déboguer votre package packagé, app consultez Exécuter, déboguer et tester votre application de bureau app empaquetée.
Pour déployer et déboguer votre bureau app, vous devez installer votre app via le programme d’installation une fois avant de déboguer normalement, afin que le raccourci Démarrer avec votre AUMID et CLSID soit présent. Une fois le raccourci Démarrer présent, vous pouvez déboguer à l’aide de F5 à partir de Visual Studio.
Si vos notifications ne s’affichent pas sur le bureau de votre ordinateur app (et qu’aucune exception n’est levée), cela signifie probablement que le raccourci Démarrer n’est pas présent (installez votre app via le programme d’installation), ou que l’AUMID que vous avez utilisé dans le code ne correspond pas à l’AUMID du raccourci Démarrer.
Si vos notifications s’affichent, mais ne sont pas conservées dans le Centre de notifications (qui disparaît une fois la fenêtre contextuelle ignorée), cela signifie que vous n’avez pas implémenté correctement l’activateur COM.
Si vous avez installé votre bureau appempaqueté et non empaqueté, notez que le package app remplacera celui-ci app lors de la gestion toast des activations. Cela signifie que les app notifications du package non empaqueté app lanceront le package app lorsqu'on clique dessus. La désinstallation du package app rétablit les activations dans le package non empaqueté app.
Si vous recevez HRESULT 0x800401f0 CoInitialize has not been called., veillez à appeler CoInitialize(nullptr) dans votre app avant d’appeler les API.
Si vous recevez HRESULT 0x8000000e A method was called at an unexpected time. lors de l’appel des API Compat, cela signifie probablement que vous n’avez pas pu appeler les méthodes Register requises (ou si app est empaqueté, vous n’exécutez pas actuellement votre app sous le contexte empaqueté).
Si vous obtenez de nombreuses erreurs de compilation unresolved external symbol, vous avez probablement oublié d'ajouter runtimeobject.lib aux Dépendances supplémentaires à l'étape #1 (ou vous l'avez ajouté uniquement à la configuration Debug et non à la configuration Release).
Gérer les versions antérieures de Windows
Si vous prenez en charge Windows 8.1 ou une version inférieure, vous devez vérifier au moment de l'exécution si vous êtes sur Windows avant d'appeler des DesktopNotificationManagerCompat APIs ou d'envoyer des toasts ToastGeneric.
Windows 8 a introduit toast des notifications, mais a utilisé les anciens modèlestoast, tels que ToastText01. L’activation a été gérée par l'événement en mémoire Activated sur la classe ToastNotification, car les toasts n'étaient que de brèves notifications contextuelles qui n'étaient pas persistantes. Windows 10 a introduit les toasts interactifs ToastGeneric, ainsi que le Centre d'action où les notifications sont conservées pendant plusieurs jours. L’introduction du Centre d’action a nécessité l’ajout d’un activateur COM, permettant ainsi à votre toast d’être activé plusieurs jours après que vous l’ayez créé.
| OS | ToastGeneric | Activateur COM | Modèles anciens toast |
|---|---|---|---|
| Windows 10 et versions ultérieures | Supported | Supported | Prise en charge (mais n’active pas le serveur COM) |
| Windows 8.1 / 8 | N/A | N/A | Supported |
| Windows 7 et inférieur | N/A | N/A | N/A |
Pour vérifier si vous exécutez Windows 10 ou version ultérieure, incluez l’en-tête <VersionHelpers.h> et vérifiez la méthode IsWindows10OrGreater. Si cela retourne true, continuez à appeler toutes les méthodes décrites dans cette documentation.
#include <VersionHelpers.h>
if (IsWindows10OrGreater())
{
// Running on Windows 10 or later, continue with sending toasts!
}
Problèmes connus
RÉSOLU : App ne se concentre pas après avoir cliqué sur toast: Dans les builds 15063 et antérieures, les droits de premier plan n’étaient pas transférés vers votre application lorsque nous avons activé le serveur COM. Par conséquent, votre app clignoterait simplement lorsque vous essayez de le déplacer au premier plan. Il n’y a pas eu de solution de contournement pour ce problème. Nous avons résolu cela dans les builds 16299 ou ultérieures.
Resources
Windows developer