방법: WRL을 사용하여 이벤트 처리
이 문서를 사용 하는 방법을 보여 줍니다 있는 Windows 런타임 C++ 템플릿 라이브러리 (WRL) 구독 하 고 이벤트를 처리 하는 Windows 런타임 개체입니다.
해당 구성 요소의 인스턴스를 만들고 속성 값을 검색 하는 기본적인 예제를 보려면 방법: WRL을 사용하여 Windows 런타임 구성 요소 활성화 및 사용.
구독 및 이벤트 처리
다음 단계에 따라 시작은 ABI::Windows::System::Threading::IDeviceWatcher 개체 및 이벤트 처리기를 사용 하 여 진행률을 모니터링할 수 있습니다.IDeviceWatcher 인터페이스를 사용 하면 장치 또는 백그라운드에서 비동기적으로 열거 하 고 장치를 추가, 제거 또는 변경 될 때 알림 받기.콜백 함수 백그라운드 작업의 결과 처리 하는 이벤트 처리기를 지정 하 여 사용할 수 있으므로이 예제는 중요 한 부분입니다.다음은 완성된 예제입니다.
주의 |
---|
일반적으로 사용 되지만 WRL 에 있는 Windows 스토어 응용 프로그램,이 예제 그림을 사용 하 여 콘솔 응용 프로그램.같은 함수 wprintf_s 에서 사용할 수 없습니다는 Windows 스토어 응용 프로그램입니다.형식에 사용할 수 있는 함수에 대 한 자세한 내용은 Windows 스토어 응용 프로그램을 참조 하십시오 CRT 함수가 /zw에 지원 되지 않습니다 및 Win32 및 Windows 저장소에 대 한 COM 응용 프로그램. |
포함 (#include)은 필요한 Windows 런타임, WRL, 또는 표준 c + + 라이브러리 헤더입니다.
#include <Windows.Devices.Enumeration.h> #include <wrl/event.h> #include <stdio.h> using namespace ABI::Windows::Devices::Enumeration; using namespace ABI::Windows::Foundation; using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers;
Windows.Devices.Enumeration.h 장치를 열거 하는 데 필요한 형식을 선언 합니다.
활용 하는 것이 좋습니다 있는 using namespace 지시문.cpp 파일에 코드를 쉽게 읽을 수 있도록 합니다.
응용 프로그램에 대 한 지역 변수를 선언 합니다.이 예제에서는 장치를 열거 하 고 나중에 이벤트에서 등록을 취소할 수 있도록 하는 등록 토큰의 개수를 보유 합니다.
// Counts the number of enumerated devices. unsigned int deviceCount = 0; // Event registration tokens that enable us to later unsubscribe from events. EventRegistrationToken addedToken; EventRegistrationToken stoppedToken; EventRegistrationToken enumCompletedToken;
초기화는 Windows 런타임.
// Initialize the Windows Runtime. RoInitializeWrapper initialize(RO_INIT_MULTITHREADED); if (FAILED(initialize)) { return PrintError(__LINE__, initialize); }
만들기는 이벤트 열거형 프로세스에는 주 응용 프로그램을 동기화 하는 개체입니다.
// Create an event that is set after device enumeration completes. We later use this event to wait for the timer to complete. // This event is for demonstration only in a console app. In most apps, you typically don't wait for async operations to complete. Event enumerationCompleted(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS)); hr = threadCompleted.IsValid() ? S_OK : HRESULT_FROM_WIN32(GetLastError()); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
[!참고]
이 이벤트는 콘솔 응용 프로그램의 일부로 데모입니다.이벤트를 사용 하 여 비동기 작업 응용 프로그램 종료 하기 전에 완료 하도록 하는 예제입니다.일반적으로 대부분의 응용 프로그램에 비동기 작업이 완료 기다려야 하지 마십시오.
만들기는 정품 인증 공장에 있는 IDeviceWatcher 인터페이스.
// Get the activation factory for the IDeviceWatcher interface. ComPtr<IDeviceInformationStatics> watcherFactory; HRESULT hr = ABI::Windows::Foundation::GetActivationFactory(HStringReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &watcherFactory); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
Windows 런타임 정규화 된 이름을 사용 하 여 형식을 식별 합니다.RuntimeClass_Windows_Devices_Enumeration_DeviceInformation 매개 변수에서 제공 하는 문자열입니다를 Windows 런타임 및 필요한 런타임 클래스 이름을 포함 합니다.
만들기는 IDeviceWatcher 개체입니다.
// Create a IDeviceWatcher object from the factory. ComPtr<IDeviceWatcher> watcher; hr = watcherFactory->CreateWatcher(&watcher); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
사용 된 Callback 함수를 구독 하는 Added, EnumerationCompleted, 및 Stopped 이벤트.
// Subscribe to the Added event. hr = watcher->add_Added(Callback<AddedHandler>([&deviceCount](IDeviceWatcher* watcher, IDeviceInformation*) -> HRESULT { // Print a message and increment the device count. // When we reach 10 devices, stop enumerating devices. wprintf_s(L"Added device...\n"); deviceCount++; if (deviceCount == 10) { return watcher->Stop(); } return S_OK; }).Get(), &addedToken); if (FAILED(hr)) { return PrintError(__LINE__, hr); } hr = watcher->add_Stopped(Callback<StoppedHandler>([=, &enumerationCompleted](IDeviceWatcher* watcher, IInspectable*) -> HRESULT { wprintf_s(L"Device enumeration stopped.\nRemoving event handlers..."); // Unsubscribe from the events. This is shown for demonstration. // The need to remove event handlers depends on the requirements of // your app. For instance, if you only need to handle an event for // a short period of time, you might remove the event handler when you // no longer need it. If you handle an event for the duration of the app, // you might not need to explicitly remove it. HRESULT hr1 = watcher->remove_Added(addedToken); HRESULT hr2 = watcher->remove_Stopped(stoppedToken); HRESULT hr3 = watcher->remove_EnumerationCompleted(enumCompletedToken); // Set the completion event and return. SetEvent(enumerationCompleted.Get()); return FAILED(hr1) ? hr1 : FAILED(hr2) ? hr2 : hr3; }).Get(), &stoppedToken); if (FAILED(hr)) { return PrintError(__LINE__, hr); } // Subscribe to the EnumerationCompleted event. hr = watcher->add_EnumerationCompleted(Callback<EnumerationCompletedHandler>([](IDeviceWatcher* watcher, IInspectable*) -> HRESULT { wprintf_s(L"Enumeration completed.\n"); return watcher->Stop(); }).Get(), &enumCompletedToken); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
Added 이벤트 처리기 열거 장치 개수를 증가 시킵니다.10 개의 장치를 찾은 다음 열거형 프로세스를 중지 합니다.
Stopped 이벤트 처리기는 이벤트 처리기를 제거 및 완료 이벤트를 설정 합니다.
EnumerationCompleted 이벤트 처리기 열거형 프로세스를 중지 합니다.10 개 이하의 장치가 있는 경우이 이벤트를 처리 합니다.
팁 람다 식은 콜백을 정의 하는 예제입니다.함수 포인터, 함수 개체 (functors)를 사용할 수도 있습니다 또는 std::function 개체입니다.람다 식에 대한 자세한 내용은 C + +에서 람다 식을 참조하십시오.
열거 프로세스를 시작 합니다.
wprintf_s(L"Starting device enumeration...\n"); hr = watcher->Start(); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
열거형 프로세스 완료 하 고 다음 메시지를 인쇄 하기 위해 대기 합니다.모든 ComPtr 및 RAII 개체 범위를 두고 자동으로 해제 됩니다.
// Wait for the operation to complete. WaitForSingleObjectEx(enumerationCompleted.Get(), INFINITE, FALSE); wprintf_s(L"Enumerated %u devices.\n", deviceCount); // All smart pointers and RAII objects go out of scope here.
전체 예제는 다음과 같습니다.
// wrl-consume-events.cpp
// compile with: runtimeobject.lib
#include <Windows.Devices.Enumeration.h>
#include <wrl/event.h>
#include <stdio.h>
using namespace ABI::Windows::Devices::Enumeration;
using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
// Prints an error string for the provided source code line and HRESULT
// value and returns the HRESULT value as an int.
int PrintError(unsigned int line, HRESULT hr)
{
wprintf_s(L"ERROR: Line:%d HRESULT: 0x%X\n", line, hr);
return hr;
}
int wmain()
{
// Type define the event handler types to make the code more readable.
typedef __FITypedEventHandler_2_Windows__CDevices__CEnumeration__CDeviceWatcher_Windows__CDevices__CEnumeration__CDeviceInformation AddedHandler;
typedef __FITypedEventHandler_2_Windows__CDevices__CEnumeration__CDeviceWatcher_IInspectable EnumerationCompletedHandler;
typedef __FITypedEventHandler_2_Windows__CDevices__CEnumeration__CDeviceWatcher_IInspectable StoppedHandler;
// Counts the number of enumerated devices.
unsigned int deviceCount = 0;
// Event registration tokens that enable us to later unsubscribe from events.
EventRegistrationToken addedToken;
EventRegistrationToken stoppedToken;
EventRegistrationToken enumCompletedToken;
// Initialize the Windows Runtime.
RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
if (FAILED(initialize))
{
return PrintError(__LINE__, initialize);
}
// Create an event that is set after device enumeration completes. We later use this event to wait for the timer to complete.
// This event is for demonstration only in a console app. In most apps, you typically don't wait for async operations to complete.
Event enumerationCompleted(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS));
hr = threadCompleted.IsValid() ? S_OK : HRESULT_FROM_WIN32(GetLastError());
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Get the activation factory for the IDeviceWatcher interface.
ComPtr<IDeviceInformationStatics> watcherFactory;
HRESULT hr = ABI::Windows::Foundation::GetActivationFactory(HStringReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &watcherFactory);
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Create a IDeviceWatcher object from the factory.
ComPtr<IDeviceWatcher> watcher;
hr = watcherFactory->CreateWatcher(&watcher);
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Subscribe to the Added event.
hr = watcher->add_Added(Callback<AddedHandler>([&deviceCount](IDeviceWatcher* watcher, IDeviceInformation*) -> HRESULT
{
// Print a message and increment the device count.
// When we reach 10 devices, stop enumerating devices.
wprintf_s(L"Added device...\n");
deviceCount++;
if (deviceCount == 10)
{
return watcher->Stop();
}
return S_OK;
}).Get(), &addedToken);
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
hr = watcher->add_Stopped(Callback<StoppedHandler>([=, &enumerationCompleted](IDeviceWatcher* watcher, IInspectable*) -> HRESULT
{
wprintf_s(L"Device enumeration stopped.\nRemoving event handlers...");
// Unsubscribe from the events. This is shown for demonstration.
// The need to remove event handlers depends on the requirements of
// your app. For instance, if you only need to handle an event for
// a short period of time, you might remove the event handler when you
// no longer need it. If you handle an event for the duration of the app,
// you might not need to explicitly remove it.
HRESULT hr1 = watcher->remove_Added(addedToken);
HRESULT hr2 = watcher->remove_Stopped(stoppedToken);
HRESULT hr3 = watcher->remove_EnumerationCompleted(enumCompletedToken);
// Set the completion event and return.
SetEvent(enumerationCompleted.Get());
return FAILED(hr1) ? hr1 : FAILED(hr2) ? hr2 : hr3;
}).Get(), &stoppedToken);
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Subscribe to the EnumerationCompleted event.
hr = watcher->add_EnumerationCompleted(Callback<EnumerationCompletedHandler>([](IDeviceWatcher* watcher, IInspectable*) -> HRESULT
{
wprintf_s(L"Enumeration completed.\n");
return watcher->Stop();
}).Get(), &enumCompletedToken);
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
wprintf_s(L"Starting device enumeration...\n");
hr = watcher->Start();
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Wait for the operation to complete.
WaitForSingleObjectEx(enumerationCompleted.Get(), INFINITE, FALSE);
wprintf_s(L"Enumerated %u devices.\n", deviceCount);
// All smart pointers and RAII objects go out of scope here.
}
/*
Sample output:
Starting device enumeration...
Added device...
Added device...
Added device...
Added device...
Added device...
Added device...
Added device...
Added device...
Added device...
Added device...
Device enumeration stopped.
Removing event handlers...
Enumerated 10 devices.
*/
코드 컴파일
코드를 컴파일하려면 복사한 다음 Visual Studio 프로젝트에 붙여 넣을 하거나 라는 파일에 붙여 넣을 wrl 소비 events.cpp 및 다음 Visual Studio 명령 프롬프트 창에서 다음 명령을 실행 합니다.
cl.exe wrl-consume-events.cpp runtimeobject.lib