Behandeln von Ereignissen vom Gerät
Ein weiterer Vorgang, der von einer WPD-Anwendung durchgeführt wird, ist die Behandlung von Ereignissen, die vom Gerät ausgelöst werden.
Ereignisbehandlungsvorgänge werden mithilfe der in der folgenden Tabelle beschriebenen Schnittstellen durchgeführt.
Schnittstelle | BESCHREIBUNG |
---|---|
IPortableDevice-Schnittstelle | Ermöglicht der Anwendung die Registrierung, um asynchrone Rückrufe zu empfangen. |
IPortableDeviceEventCallback-Schnittstelle | Enthält den Ereignishandler der Anwendung. |
Die CPortableDeviceEventsCallback-Klasse im DeviceEvents.cpp-Modul der Beispielanwendung veranschaulicht, wie eine Anwendung IPortableDeviceEventCallback implementieren kann. Die Implementierung der OnEvent-Methode in dieser Klasse schreibt die Parameter für jedes Ereignis in das Konsolenfenster der Anwendung. Zusätzlich zur OnEvent-Methode implementiert diese Klasse AddRef und Release, die verwendet werden, um die Verweisanzahl des Objekts beizubehalten.
class CPortableDeviceEventsCallback : public IPortableDeviceEventCallback
{
public:
CPortableDeviceEventsCallback() : m_cRef(1)
{
}
~CPortableDeviceEventsCallback()
{
}
HRESULT __stdcall QueryInterface(
REFIID riid,
LPVOID* ppvObj)
{
HRESULT hr = S_OK;
if (ppvObj == NULL)
{
hr = E_INVALIDARG;
return hr;
}
if ((riid == IID_IUnknown) ||
(riid == IID_IPortableDeviceEventCallback))
{
AddRef();
*ppvObj = this;
}
else
{
hr = E_NOINTERFACE;
}
return hr;
}
ULONG __stdcall AddRef()
{
InterlockedIncrement((long*) &m_cRef);
return m_cRef;
}
ULONG __stdcall Release()
{
ULONG ulRefCount = m_cRef - 1;
if (InterlockedDecrement((long*) &m_cRef) == 0)
{
delete this;
return 0;
}
return ulRefCount;
}
HRESULT __stdcall OnEvent(
IPortableDeviceValues* pEventParameters)
{
HRESULT hr = S_OK;
if (pEventParameters != NULL)
{
printf("***************************\n** Device event received **\n***************************\n");
DisplayStringProperty(pEventParameters, WPD_EVENT_PARAMETER_PNP_DEVICE_ID, L"WPD_EVENT_PARAMETER_PNP_DEVICE_ID");
DisplayGuidProperty(pEventParameters, WPD_EVENT_PARAMETER_EVENT_ID, L"WPD_EVENT_PARAMETER_EVENT_ID");
}
return hr;
}
ULONG m_cRef;
};
Die Beispielanwendung instanziiert die CPortableDeviceEventsCallback-Klasse in ihrer RegisterForEventNotifications-Hilfsfunktion. Diese Funktion erstellt mithilfe des new-Operators eine instance des Rückrufobjekts. Anschließend wird die IPortableDevice::Advise-Methode aufgerufen, um den Rückruf zu registrieren und mit dem Empfangen von Ereignissen zu beginnen.
void RegisterForEventNotifications(IPortableDevice* pDevice)
{
HRESULT hr = S_OK;
LPWSTR wszEventCookie = NULL;
CPortableDeviceEventsCallback* pCallback = NULL;
if (pDevice == NULL)
{
return;
}
// Check to see if we already have an event registration cookie. If so,
// then avoid registering again.
// NOTE: An application can register for events as many times as they want.
// This sample only keeps a single registration cookie around for
// simplicity.
if (g_strEventRegistrationCookie.GetLength() > 0)
{
printf("This application has already registered to receive device events.\n");
return;
}
// Create an instance of the callback object. This will be called when events
// are received.
if (hr == S_OK)
{
pCallback = new CPortableDeviceEventsCallback();
if (pCallback == NULL)
{
hr = E_OUTOFMEMORY;
printf("Failed to allocate memory for IPortableDeviceEventsCallback object, hr = 0x%lx\n",hr);
}
}
// Call Advise to register the callback and receive events.
if (hr == S_OK)
{
hr = pDevice->Advise(0, pCallback, NULL, &wszEventCookie);
if (FAILED(hr))
{
printf("! Failed to register for device events, hr = 0x%lx\n",hr);
}
}
// Save the event registration cookie if event registration was successful.
if (hr == S_OK)
{
g_strEventRegistrationCookie = wszEventCookie;
}
// Free the event registration cookie, if one was returned.
if (wszEventCookie != NULL)
{
CoTaskMemFree(wszEventCookie);
wszEventCookie = NULL;
}
if (hr == S_OK)
{
printf("This application has registered for device event notifications and was returned the registration cookie '%ws'", g_strEventRegistrationCookie.GetString());
}
// If a failure occurs, remember to delete the allocated callback object, if one exists.
if (pCallback != NULL)
{
pCallback->Release();
}
Sobald die Beispielanwendung Ereignisse empfängt, ruft sie die Hilfsfunktion UnregisterForEventNotifications auf. Diese Funktion wiederum ruft die IPortableDevice::Unadvise-Methode auf, um die Registrierung des Rückrufs vom Empfangen von Ereignissen aufzuheben.
void UnregisterForEventNotifications(IPortableDevice* pDevice)
{
HRESULT hr = S_OK;
if (pDevice == NULL)
{
return;
}
hr = pDevice->Unadvise(g_strEventRegistrationCookie);
if (FAILED(hr))
{
printf("! Failed to unregister for device events using registration cookie '%ws', hr = 0x%lx\n",g_strEventRegistrationCookie.GetString(), hr);
}
if (hr == S_OK)
{
printf("This application used the registration cookie '%ws' to unregister from receiving device event notifications", g_strEventRegistrationCookie.GetString());
}
g_strEventRegistrationCookie = L"";
}
Zugehörige Themen