Nasıl Yapılır: WRL Kullanarak Olayları İşleme
Bu belge nasıl kullanılacağını gösterir Windows Çalışma Zamanı C++ Şablon Kitaplığı (WRL) abone olun ve olaylarını işlemek için bir Windows Çalışma Zamanı nesne.
Bu bileşenin bir örneğini oluşturur ve bir özellik değerini alır bir daha temel örnek için bkz: Nasıl yapılır: WRL Kullanarak Windows Çalışma Zamanı Bileşenini Etkinleştirme ve Kullanma.
Olayları işleme ve abone olma
Aşağıdaki başlangıç adımları bir ABI::Windows::System::Threading::IDeviceWatcher nesne ve ilerlemeyi izlemek için olay işleyicilerini kullanın.IDeviceWatcher Arabirim, zaman uyumsuz olarak veya arka planda aygıtları numaralandırmak ve aygıtları eklenen, kaldırılan veya değiştirilen zaman bildirim almak sağlar.Geri işlevdir önemli bir kısmını Bu örnek, arka plan işlemi sonuçları işleyen olay işleyicileri belirtmek sağladığından.Tam bir örnek aşağıda verilmiştir.
Uyarı |
---|
Genellikle kullanmanıza rağmen WRL , bir Windows Mağazası app, bu örnek, bir konsol uygulaması gösterim amacıyla kullanır.Gibi işlevleri wprintf_s kullanılamaz bir Windows Mağazası app.Türleri ve kullanabileceğiniz fonksiyonlar hakkında daha fazla bilgi için bir Windows Mağazası app, bkz: /ZW ile desteklenmeyen CRT işlevlerinin ve Win32 ve COM için Windows Store apps. |
İçerir (#include) gerektiği gibi Windows Çalışma Zamanı, WRL, ya da standart C++ Kitaplığı üstbilgileri.
#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 aygıtları numaralandırmak için gereken türler bildirir.
Öneririz, kullanan using namespace kodunu daha kolay okunur hale getirmek için .cpp dosyasındaki yönergesi.
Uygulama için yerel değişkenleri bildirir.Bu örnek, numaralandırılan aygıtları ve daha sonra olay aboneliği etkinleştirmek kayıt belirteçleri sayısı sayısını tutar.
// 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;
Başlatma Windows Çalışma Zamanı.
// Initialize the Windows Runtime. RoInitializeWrapper initialize(RO_INIT_MULTITHREADED); if (FAILED(initialize)) { return PrintError(__LINE__, initialize); }
Oluşturma bir olayı ana App numaralandırma işleminin tamamlanması eşitler nesne.
// 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)); HRESULT hr = enumerationCompleted.IsValid() ? S_OK : HRESULT_FROM_WIN32(GetLastError()); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
[!NOT]
Bu olay bir konsol uygulaması bir parçası olarak yalnızca tanıtım içindir.Bu örnek olay app çıkar önce eş zamanlı olmayan işlemin tamamlanmasını sağlamak için kullanır.Çoğu uygulamalar genelde zaman uyumsuz işlemler için vakit kaybetmeden.
Oluşturmak için bir etkinleştirme Fabrika IDeviceWatcher arabirim.
// Get the activation factory for the IDeviceWatcher interface. ComPtr<IDeviceInformationStatics> watcherFactory; hr = ABI::Windows::Foundation::GetActivationFactory(HStringReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &watcherFactory); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
Windows Çalışma Zamanı Türlerini tanımlamak için tam adını kullanır.RuntimeClass_Windows_Devices_Enumeration_DeviceInformation Parametresi tarafından sağlanan bir dize olan Windows Çalışma Zamanı ve gerekli olan çalışma zamanı sınıf adını içerir.
Oluşturma IDeviceWatcher nesne.
// Create a IDeviceWatcher object from the factory. ComPtr<IDeviceWatcher> watcher; hr = watcherFactory->CreateWatcher(&watcher); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
Kullanım Callback abone olmak için işlev Added, EnumerationCompleted, ve Stopped olaylar.
// 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 Olay işleyicisi numaralandırılmış aygıtların sayısını artırır.On aygıtları bulunduktan sonra numaralandırma işlemini durdurur.
Stopped Olay işleyicisi, olay işleyicileri kaldırır ve tamamlama olayı belirler.
EnumerationCompleted Olay işleyicisi numaralandırma işlemini durdurur.10'dan az aygıtları olasılığına Biz bu olayı işleyin.
İpucu Bu örnekte lambda ifadesi geri çağırmalar tanımlamak için kullanılır.Function nesneleri (functors), işlev işaretçileri de kullanabilirsiniz veya std::function nesneler.Lambda ifadeleri hakkında daha fazla bilgi için bkz: C++'deki Lambda İfadeleri.
Numaralandırma işlemi başlatın.
wprintf_s(L"Starting device enumeration...\n"); hr = watcher->Start(); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
Doldurun ve ardından iletiyi yazdırmak numaralandırma işleminin bitmesini bekleyin.Tüm ComPtr ve RAII nesne kapsam bırakın ve otomatik olarak serbest bırakılır.
// 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.
Tam bir örnek aşağıdadır:
// 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));
HRESULT hr = enumerationCompleted.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;
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.
*/
Kod Derleniyor
Kodu derlemek için kopyalayın ve ardından Visual Studio projesinde yapıştırın veya adlı bir dosyaya yapıştırın wrl tüketen events.cpp ve Visual Studio komut istemi penceresinde aşağıdaki komutu çalıştırın.
cl.exe wrl-consume-events.cpp runtimeobject.lib