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