Partager via


Notifications asynchrones dans les filtres d'impression

Important

La plateforme d’impression moderne est le moyen privilégié de Windows pour communiquer avec les imprimantes. Nous vous recommandons d’utiliser le pilote de classe IPP en boîte de Microsoft, ainsi que les applications de support d’impression (PSA), pour personnaliser l’expérience d’impression dans Windows 10 et 11 pour le développement de périphériques d’impression.

Pour plus d’informations, veuillez consulter les articles Plateforme d’impression moderne et Guide de conception des applications de support d’impression.

Le pipeline de filtre d’impression propose une fonctionnalité de notification asynchrone très similaire à la notification asynchrone prise en charge dans le spouleur d’impression pour les applications. La fonction RouterCreatePrintAsyncNotificationChannel disponible dans le spouleur d’impression n’est pas disponible pour les filtres d’impression. Les filtres d’impression doivent utiliser l’interface IPrintClassObjectFactory pour créer des objets IPrintAsyncNotify.

Cette rubrique explique comment utiliser la fonctionnalité de notification asynchrone dans un filtre d’impression.

La levée de notifications asynchrones à partir d’un filtre d’impression n’est pas prise en charge dans le modèle de pilote d’impression v4.

IPrintClassObjectFactory

L’interface IPrintClassObjectFactory permet d’accéder aux interfaces de notification. L’exemple de code suivant montre comment un filtre peut obtenir cette interface à partir du conteneur de propriétés.

// This interface is defined as a private member variable in the filter class
IPrintClassObjectFactory  *m_pPrintClassFactory;

// The following code goes in the IntializeFilter method of the filter
VARIANT var;
VariantInit(&var);

HRESULT hr = pIPropertyBag->GetProperty(
    XPS_FP_PRINT_CLASS_FACTORY,
    &var);

if (SUCCEEDED(hr))
{
    hr = V_UNKNOWN(&var)->QueryInterface(
 IID_IPrintClassObjectFactory,
 reinterpret_cast<void **>(&m_pPrintClassFactory));
}

Canal de notification

Avec l’interface IPrintClassObjectFactory, le filtre peut créer un canal de notification unidirectionnel ou bidirectionnel, en fonction des besoins du filtre. L’exemple de code suivant est la suite de l’exemple précédent et montre comment un filtre établit un canal de notification unidirectionnel.

// Create a unidirectional notification channel
IPrintAsyncNotifyChannel  *pIAsyncNotifyChannel;
IPrintAsyncNotify  *pIAsyncNotify;

HRESULT hr = m_pPrintClassFactory->GetPrintClassObject(
 m_bstrPrinter,      // The printer name that was read from the property bag
 IID_IPrintAsyncNotify,
 reinterpret_cast<void**>(&pIAsyncNotify)));

if (SUCCEEDED(hr))
{
    hr = pIAsyncNotify->CreatePrintAsyncNotifyChannel(
 m_jobId,
 const_cast<GUID*>(&MS_ASYNCNOTIFY_UI),
 kPerUser,
 kUniDirectional,
        NULL,
        &pIAsyncNotifyChannel));

   // etc...
}

Pour créer un canal de notification bidirectionnel, vous devez utiliser l’exemple de code suivant à la place de l’exemple précédent.

// Create a bidirectional notification channel
IPrintAsyncNotifyChannel *pIAsyncNotifyChannel;
IPrintAsyncNotify *pIAsyncNotify;

HRESULT hr = m_pPrintClassFactory->GetPrintClassObject(
 m_bstrPrinterName,   // The printer name that was read from the property bag
 IID_IPrintAsyncNotify,
 reinterpret_cast<void**>(&pIAsyncNotify)));

if (SUCCEEDED(hr))
{
    hr = pIAsyncNotify->CreatePrintAsyncNotifyChannel(
 m_jobId,
 const_cast<GUID*>(& SAMPLE_ASYNCNOTIFY_UI),
 kPerUser,
 kBiDirectional,
 pIAsyncCallback,
        &pIAsyncNotifyChannel));

    // etc...
}

Dans l’exemple de code précédent, la variable pIAsyncCallback est un pointeur vers l’implémentation de l’appelant de l’interface IPrintAsyncNotifyCallback.

Dans certains cas, vous devez libérer le canal de notification bidirectionnel lorsque vous avez terminé de l'utiliser. Pour ce faire, appelez la méthode Release sur IPrintAsyncNotifyChannel. Pour plus d’informations sur la libération d’un canal, consultez Canal de notification.

Emprunt d’identité et notification

Le filtre ne doit pas emprunter l’identité du compte utilisateur lorsqu’il appelle la méthode IPrintAsyncNotify::CreatePrintAsyncNotifyChannel. Le mécanisme d’autorisation dans le spouleur d’impression impose qu’il soit appelé à partir du compte de service local. Si le filtre doit emprunter l’identité du compte de l’utilisateur qui a soumis la tâche, le filtre doit être rétabli avant d’appeler CreatePrintAsyncNotifyChannel. Une fois l’appel retourné, le filtre peut revenir au compte utilisateur si nécessaire.

Même si l’appel de notification est effectué dans le contexte du service local, les notifications kPerUser sont toujours envoyées à l’utilisateur qui a envoyé la tâche en fonction de l’association utilisateur de l’ID de tâche.

Adaptation de l’exemple de code du WDK

Vous pouvez adapter l’exemple de notification dans l’exemple de code du WDK pour travailler dans un filtre d’impression en remplaçant l’appel RouterCreatePrintAsyncNotificationChannel par l’exemple de code suivant.

IPrintAsyncNotify  *pIAsyncNotify;

HRESULT hr = m_pPrintClassFactory->GetPrintClassObject(
 m_bstrPrinterName,      // get it from the property bag
 IID_IPrintAsyncNotify,
 reinterpret_cast<void**>(&pIAsyncNotify)));

if (SUCCEEDED(hr))
{
    hr = pIAsyncNotify->CreatePrintAsyncNotifyChannel(
 // the same arguments as for
 // RouterCreatePrintAsyncNotificationChannel
        );

    // etc...
}