WinUI3桌面C++程序:如何获取飞行模式切换事件(非注册表线程方式)
监听Windows飞行模式切换事件(无需持续线程等待的方案)
针对WinUI3桌面C++应用,无需线程持续等待的飞行模式事件监听方案主要有以下几种:
1. 使用WinRT RadioManager API(推荐)
WinUI3基于Windows Runtime(WinRT),直接使用Windows.Devices.Radios命名空间下的API是最适配的方案——它采用事件驱动模式,系统会在飞行模式切换时自动触发回调,无需手动维护等待线程。
代码示例
#include <winrt/Windows.Devices.Radios.h> #include <winrt/Windows.Foundation.h> using namespace winrt; using namespace Windows::Devices::Radios; using namespace Windows::Foundation; // 注册飞行模式监听函数 void SetupFlightModeListener() { RadioManager radioManager = RadioManager::GetDefault(); // 订阅无线电状态变更事件 auto eventToken = radioManager.RadioStateChanged([](const IInspectable&, const RadioStateChangedEventArgs& args) { // 获取当前系统飞行模式状态 bool isFlightModeEnabled = RadioManager::GetDefault().IsFlightModeEnabled(); if (isFlightModeEnabled) { // 处理飞行模式开启逻辑 } else { // 处理飞行模式关闭逻辑 } }); // 保存eventToken,后续需要取消监听时调用radioManager.RadioStateChanged(eventToken) }
优势
- 与WinUI3开发原生适配,代码简洁
- 事件驱动机制,无需手动管理线程或等待句柄
- 直接获取飞行模式状态,无需解析注册表或其他系统数据
2. 监听Win32 WM_SETTINGCHANGE广播消息
WinUI3桌面应用本质基于Win32窗口,可通过窗口消息循环监听系统设置变更的广播消息WM_SETTINGCHANGE,当飞行模式切换时,系统会发送该消息并附带SystemRadioState标识。
代码示例
在WinUI3桌面应用的窗口过程中添加消息处理:
LRESULT CALLBACK AppWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_SETTINGCHANGE: // 判断是否为无线电状态变更(飞行模式属于此类) if (lParam != nullptr && wcscmp(reinterpret_cast<LPCWSTR>(lParam), L"SystemRadioState") == 0) { // 读取当前飞行模式状态 RadioManager radioManager = RadioManager::GetDefault(); bool isFlightModeOn = radioManager.IsFlightModeEnabled(); // 处理飞行模式切换逻辑 } break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; }
优势
- 依托Win32原生消息机制,无需额外依赖
- 无需启动额外线程,消息由系统直接投递到窗口过程
3. WMI异步事件订阅
通过Windows Management Instrumentation(WMI)异步订阅系统无线电管理事件,WMI会在事件触发时自动调用回调函数,无需持续等待。
代码示例(简化版)
#include <wbemidl.h> #include <comdef.h> #pragma comment(lib, "wbemuuid.lib") // 自定义WMI事件接收器 class CFlightModeEventSink : public IWbemObjectSink { ULONG m_refCount = 0; public: HRESULT STDMETHODCALLTYPE Indicate(long lObjCount, IWbemClassObject** ppObjArray) override { if (lObjCount <= 0 || ppObjArray == nullptr) return WBEM_S_NO_ERROR; VARIANT flightModeVar; HRESULT hr = ppObjArray[0]->Get(L"FlightModeEnabled", 0, &flightModeVar, nullptr, nullptr); if (SUCCEEDED(hr) && flightModeVar.vt == VT_BOOL) { bool isFlightModeOn = (flightModeVar.boolVal == VARIANT_TRUE); // 处理飞行模式切换逻辑 } VariantClear(&flightModeVar); return WBEM_S_NO_ERROR; } // 实现IWbemObjectSink其他纯虚函数 HRESULT STDMETHODCALLTYPE SetStatus(LONG, HRESULT, BSTR, IWbemClassObject*) override { return WBEM_S_NO_ERROR; } ULONG STDMETHODCALLTYPE AddRef() override { return InterlockedIncrement(&m_refCount); } ULONG STDMETHODCALLTYPE Release() override { ULONG count = InterlockedDecrement(&m_refCount); if (count == 0) delete this; return count; } HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) override { if (riid == IID_IUnknown || riid == IID_IWbemObjectSink) { *ppv = static_cast<IWbemObjectSink*>(this); AddRef(); return WBEM_S_NO_ERROR; } return E_NOINTERFACE; } }; // 注册WMI监听 HRESULT RegisterWmiFlightModeListener() { HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); if (FAILED(hr)) return hr; IWbemLocator* pLoc = nullptr; hr = CoCreateInstance(CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast<void**>(&pLoc)); if (FAILED(hr)) { CoUninitialize(); return hr; } IWbemServices* pSvc = nullptr; hr = pLoc->ConnectServer(_bstr_t(L"ROOT\\cimv2"), nullptr, nullptr, 0, NULL, 0, 0, &pSvc); if (FAILED(hr)) { pLoc->Release(); CoUninitialize(); return hr; } // 设置安全级别 hr = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE); if (FAILED(hr)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return hr; } IUnsecuredApartment* pUnsecApp = nullptr; hr = CoCreateInstance(CLSID_UnsecuredApartment, nullptr, CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, reinterpret_cast<void**>(&pUnsecApp)); if (FAILED(hr)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return hr; } CFlightModeEventSink* pSink = new CFlightModeEventSink(); IWbemObjectSink* pStubSink = nullptr; hr = pUnsecApp->CreateObjectStub(pSink, reinterpret_cast<IUnknown**>(&pStubSink)); if (FAILED(hr)) { pSink->Release(); pUnsecApp->Release(); pSvc->Release(); pLoc->Release(); CoUninitialize(); return hr; } // 订阅Win32_RadioManagementEvent事件 hr = pSvc->ExecNotificationQueryAsync( _bstr_t("WQL"), _bstr_t("SELECT * FROM Win32_RadioManagementEvent"), WBEM_FLAG_SEND_STATUS, nullptr, pStubSink ); // 释放临时资源(注意pStubSink和pSink由WMI持有,无需手动释放) pUnsecApp->Release(); pSvc->Release(); pLoc->Release(); return hr; }
优势
- 可监听多种系统级事件,灵活性高
- 异步回调模式,无需持续等待线程
内容的提问来源于stack exchange,提问作者Harshith
相关产品推荐
相关产品推荐

