다음을 통해 공유


디바이스에서 이벤트 처리

WPD 애플리케이션에서 수행하는 또 다른 작업은 디바이스에서 발생하는 이벤트를 처리하는 것입니다.

이벤트 처리 작업은 다음 표에 설명된 인터페이스를 사용하여 수행됩니다.

인터페이스 Description
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 도우미 함수에서 CPortableDeviceEventsCallback 클래스를 인스턴스화합니다. 이 함수는 새 연산자를 사용하여 콜백 개체의 instance 만듭니다. 그런 다음 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"";
}

IPortableDevice 인터페이스

IPortableDeviceEventCallback 인터페이스

프로그래밍 가이드