Freigeben über


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"";
}

IPortableDevice-Schnittstelle

IPortableDeviceEventCallback-Schnittstelle

Programmierhandbuch