Controlar eventos desde el dispositivo
Otra operación realizada por una aplicación WPD es el control de eventos desencadenados por el dispositivo.
Las operaciones de control de eventos se realizan mediante las interfaces descritas en la tabla siguiente.
Interfaz | Descripción |
---|---|
IPortableDevice (interfaz) | Permite que la aplicación se registre para recibir devoluciones de llamada asincrónicas. |
IPortableDeviceEventCallback (Interfaz) | Contiene el controlador de eventos de la aplicación. |
La clase CPortableDeviceEventsCallback del módulo DeviceEvents.cpp de la aplicación de ejemplo muestra cómo una aplicación puede implementar IPortableDeviceEventCallback. La implementación del método OnEvent en esta clase escribe los parámetros de cualquier evento en la ventana de la consola de la aplicación. Además del método OnEvent, esta clase implementa AddRef y Release, que se usan para mantener el recuento de referencias del objeto.
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;
};
La aplicación de ejemplo crea una instancia de la clase CPortableDeviceEventsCallback en su función auxiliar RegisterForEventNotifications. Esta función crea una instancia del objeto de devolución de llamada mediante el operador new. A continuación, llama al método IPortableDevice::Advise para registrar la devolución de llamada y empezar a recibir eventos.
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();
}
Una vez que la aplicación de ejemplo pasa por recibir eventos, llama a la función auxiliar UnregisterForEventNotifications. Esta función, a su vez, llama al método IPortableDevice::Unadvise para anular el registro de la devolución de llamada de los eventos receptores.
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"";
}
Temas relacionados