Udostępnij za pośrednictwem


Powiadomienia asynchroniczne w filtrach wydruku

Ważny

Nowoczesna platforma drukowania jest preferowanym sposobem komunikacji z drukarkami w systemie Windows. Zalecamy używanie sterownika klasy skrzynki odbiorczej IPP firmy Microsoft wraz z aplikacjami do obsługi drukowania (PSA), aby dostosować środowisko drukowania w systemie Windows 10 i 11 na potrzeby opracowywania urządzeń drukarki.

Aby uzyskać więcej informacji, zobacz przewodnik dotyczący projektowania aplikacji wspierającej drukowanie .

Potok filtru wydruku ma funkcję powiadomień asynchronicznych, która jest bardzo podobna do powiadomienia asynchronicznego obsługiwanego w buforze wydruku dla aplikacji. Funkcja RouterCreatePrintAsyncNotificationChannel, dostępna w buforze wydruku, nie jest dostępna dla filtrów druku. Filtry wydruku muszą używać interfejsu IPrintClassObjectFactory do tworzenia obiektów IPrintAsyncNotify.

W tym temacie opisano sposób używania funkcji powiadomień asynchronicznych w filtrze wydruku.

Zgłaszanie powiadomień asynchronicznych z filtra druku nie jest obsługiwane w modelu sterownika druku w wersji 4.

IPrintClassObjectFactory

Interfejs IPrintClassObjectFactory zapewnia dostęp do interfejsów powiadomień. Poniższy przykład kodu ilustruje, jak filtr może uzyskać ten interfejs z zasobnika właściwości.

// 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));
}

Kanał powiadomień

Za pomocą interfejsu IPrintClassObjectFactory filtr może utworzyć jednokierunkowy lub dwukierunkowy kanał powiadomień w zależności od potrzeb filtru. Poniższy przykład kodu jest kontynuowany z poprzedniego przykładu i pokazuje, jak filtr ustanawia jednokierunkowy kanał powiadomień.

// 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...
}

Aby utworzyć dwukierunkowy kanał powiadomień, należy użyć następującego przykładu kodu zamiast poprzedniego przykładu.

// 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...
}

W poprzednim przykładzie kodu zmienna pIAsyncCallback jest wskaźnikiem do implementacji wywoływanej przez obiekt interfejsu IPrintAsyncNotifyCallback.

W niektórych przypadkach należy zwolnić dwukierunkowy kanał powiadomień po zakończeniu pracy z nim. W tym celu wywołaj metodę Release w IPrintAsyncNotifyChannel. Aby uzyskać informacje o tym, kiedy udostępnić kanał, zobacz Kanał powiadomień.

Personifikacja i powiadomienie

Filtr nie może personifikować konta użytkownika, gdy wywołuje metodę IPrintAsyncNotify::CreatePrintAsyncNotifyChannel. Mechanizm autoryzacji w buforze wydruku wymaga, aby był wywoływany z konta Local Service. Jeśli filtr musi personifikować konto użytkownika, który przesłał zadanie, filtr musi powrócić do samego siebie, zanim wywoła funkcję CreatePrintAsyncNotifyChannel. Po zakończeniu wywołania filtr może w razie potrzeby powrócić do konta użytkownika.

Mimo że wywołanie powiadomienia jest wykonywane w kontekście usługi lokalnej, powiadomienia kPerUser są nadal wysyłane do użytkownika, który przesłał zadanie na podstawie skojarzenia użytkownika z identyfikatorem zadania.

Dostosowywanie przykładowego kodu zestawu narzędzi Windows Driver Kit (WDK)

Można dostosować przykład powiadomienia z przykładowego kodu WDK do działania w filtrze wydruku, zastępując wywołanie RouterCreatePrintAsyncNotificationChannel poniższym przykładem kodu.

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...
}