處理來自裝置的事件
WPD 應用程式完成的另一項作業是處理裝置所引發的事件。
使用下表所述的介面來完成事件處理作業。
介面 | 描述 |
---|---|
IPortableDevice 介面 | 讓應用程式註冊以接收非同步回呼。 |
IPortableDeviceEventCallback 介面 | 包含應用程式的事件處理常式。 |
範例應用程式 DeviceEvents.cpp 模組中的 CPortableDeviceEventsCallback 類別示範應用程式如何實作 IPortableDeviceEventCallback。 這個類別中 OnEvent 方法的實作會將任何事件的參數寫入應用程式主控台視窗。 除了 OnEvent 方法之外,這個類別還會實作 AddRef 和 Release,用來維護物件的參考計數。
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;
};
範例應用程式會在其 RegisterForEventNotifications Helper 函式中具現化 CPortableDeviceEventsCallback 類別。 此函式會使用新的 運算子建立回呼物件的實例。 然後它會呼叫 IPortableDevice::Advise 方法來註冊回呼並開始接收事件。
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();
}
一旦範例應用程式通過接收事件,它會呼叫 UnregisterForEventNotifications 協助程式函式。 此函式接著會呼叫 IPortableDevice::Unadvise 方法來取消註冊接收事件的回呼。
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"";
}
相關主題