Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Les applications de bureau empaquetées et non empaquetées peuvent envoyer des notifications toast interactives comme les applications de plateforme Windows universelle (UWP). Cela inclut des applications empaquetées (voir Créer un projet pour une application de bureau WinUI 3 empaquetée) ; applications empaquetées avec emplacement externe (voir Accorder une identité de package en empaquetant avec un emplacement externe) ; et applications non empaquetées (voir Créer un projet pour une application de bureau WinUI 3 non empaquetée).
Toutefois, pour une application de bureau non empaquetée, 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.
Importante
Si vous écrivez une application UWP, 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 application, vous devez d’abord le faire. Il existe quelques étapes clés.
- Ajouter
runtimeobject.lib
aux 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 Linker -> Input, 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 espaces de noms
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 Windows Toast.
#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 mettre en œuvre un gestionnaire d'activation de Toast, de manière à ce que lorsque l'utilisateur clique sur votre Toast, votre application puisse faire quelque chose. Cela est nécessaire pour que votre Toast persiste dans le Centre d'action (puisque le Toast peut être cliqué quelques jours plus tard lorsque votre application est fermée). Cette classe peut être placée n’importe où dans votre projet.
Implémentez l’interface INotificationActivationCallback comme montré ci-dessous, comprenant également un UUID, et appelez aussi CoCreatableClass pour signaler que votre classe est créable COM. 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 application est empaquetée ou non empaquetée. 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).
Empaqueté
Si votre application est empaquetée (voir Créer un projet pour une application de bureau WinUI 3 empaquetée) ou empaquetée avec un emplacement externe (voir Accorder l’identité du package par empaquetage avec emplacement externe), ou si vous prenez en charge les deux, puis dans votre Package.appxmanifest ajouter :
- 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 le
Arguments="-ToastActivated"
pour que vous sachiez que votre lancement a été effectué à partir d'un toast - desktop:Extension pour windows.toastNotificationActivation pour déclarer le CLSID de votre activateur de notifications toast (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>
Non empaqueté
Si votre application n’est pas empaquetée (voir Créer un projet pour une application de bureau WinUI 3 non empaquetée), ou si vous prenez en charge les deux, vous devez déclarer votre ID de modèle utilisateur d’application (AUMID) et activer toast CLSID (GUID de l’étape 4) sur le raccourci de votre application dans Démarrer.
Choisissez un AUMID unique qui identifiera votre application. 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. Veillez à ce que le GUID obtenu à l'étape 4 soit entouré de {}
, 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>
Importante
Pour utiliser réellement des notifications, vous devez installer votre application 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.
Étape 5.2 : Inscrire le serveur AUMID et COM
Ensuite, quel que soit votre programme d’installation, dans le code de démarrage de votre application (avant d’appeler des API de notification), appelez la méthode RegisterAumidAndComServer, en spécifiant votre classe d’activateur de notification de l’étape 4 et votre AUMID utilisé 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 application prend en charge le déploiement empaqueté et non empaqueté, n’hésitez pas à appeler cette méthode, quel que soit le 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 cloner 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 packagées et non packagées, vous devez enregistrer votre type d'activateur de notification, afin de pouvoir gérer les activations Toast.
Dans le code de démarrage de votre application, appelez la méthode suivante RegisterActivator. Cet activateur doit être appelé pour que vous puissiez recevoir des activations 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 une application non empaquetée, 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 non l’AUMID.
Veillez à utiliser la liaison ToastGeneric comme indiqué ci-dessous, car les modèles notification de Toast de Windows 8.1 n'activeront pas l'activateur de notification COM que vous avez créé à l'étape 4.
Importante
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 d’application locale 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());
}
}
}
Importante
Les applications de bureau ne peuvent pas utiliser les anciens modèles 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 : Gestion de l’activation
Lorsque l'utilisateur clique sur votre toast ou sur les boutons du toast, la méthode Activate de votre classe NotificationActivator est invoquée.
Dans la méthode Activate, vous pouvez analyser les arguments que vous avez spécifiés dans le toast et obtenir l’entrée utilisateur que l’utilisateur a tapé ou sélectionné, puis activer votre application en conséquence.
Remarque
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 prendre en charge correctement le lancement lorsque votre application est fermée, dans votre fonction WinMain, vous devez déterminer si vous êtes lancé à partir d'un Toast ou non. Si vous êtes lancé à partir d'un Toast, l'arg de lancement sera « -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 application est déjà en cours d’exécution :
- Activate est appelé dans votre NotificationActivator
Si votre application n’est pas en cours d’exécution :
- Votre application est lancée par EXE, vous obtenez un argue de ligne de commande de « -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é. Il appartient au code de votre application de décider s’il faut afficher une fenêtre ou simplement effectuer un travail, puis quitter. Par conséquent, le fait de spécifier un activationType de background dans votre contenu de toast ne change 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 une application de bureau.
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 application empaquetée, consultez Exécuter, déboguer et tester une application de bureau empaquetée.
Pour déployer et déboguer votre application de bureau, vous devez installer votre application 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 simplement pas dans votre application de bureau (et qu'aucune exception n'est levée), cela signifie probablement que le raccourci "Démarrer" n'est pas présent (installez votre application via le programme d'installation), ou que l'AUMID que vous avez entré dans le code ne correspond pas à l'AUMID dans votre 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 application de bureau empaquetée et non empaquetée, notez que l’application empaquetée remplace l’application non empaquetée lors de la gestion des activations toast. Cela signifie que les toasts de l'application non packagée lanceront l'application packagée lorsque vous cliquerez dessus. La désinstallation de l’application empaquetée rétablit les activations à l’application non empaquetée.
Si vous recevez HRESULT 0x800401f0 CoInitialize has not been called.
, veillez à appeler CoInitialize(nullptr)
dans votre application 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 une application empaquetée, vous n’exécutez pas votre application dans le contexte empaqueté).
Si vous obtenez de nombreuses erreurs de compilation unresolved external symbol
, vous avez probablement oublié d'ajouter runtimeobject.lib
aux Additional Dependencies à l'étape #1 (ou vous ne l'avez ajouté qu'à la configuration Debug et non à la configuration Release).
Gestion des versions antérieures de Windows
Si vous prenez en charge Windows 8.1 ou une version inférieure, vous devrez vérifier au moment de l'exécution si vous travaillez sous Windows avant d'appeler les API DesktopNotificationManagerCompat ou d'envoyer des toasts ToastGeneric.
Windows 8 a introduit les notifications toast, mais a utilisé les anciens modèles de toast, comme ToastText01. L'activation était gérée par l'événement Activated en mémoire de la classe ToastNotification, car les toasts n'étaient que de brèves fenêtres contextuelles qui n'étaient pas conservées. 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'introduction d'un activateur COM, afin que votre toast puisse être activé quelques jours après sa création.
Système d’exploitation | ToastGeneric | Activateur COM | Anciens modèles de Toast |
---|---|---|---|
Windows 10 et versions ultérieures | Pris en charge | Pris en charge | Prise en charge (mais n’active pas le serveur COM) |
Windows 8.1 / 8 | N/A | N/A | Pris en charge |
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
CORRIGÉ : l'application ne devient pas centrée après avoir cliqué sur toast : Dans les builds 15063 et antérieures, les droits de premier plan n'étaient pas transférés à votre application lorsque nous activions le serveur COM. Par conséquent, votre application clignote simplement lorsque vous avez essayé de la 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.
Ressources
Windows developer