C++ Qt:如何检查应用的Windows 10 Toast通知是否启用
解决Qt程序检查Windows 10通知开关状态的思路
嘿,我刚好处理过类似的需求,给你几个靠谱的解决方向:
先明确核心问题:QSystemTrayIcon的通知机制
首先得说清楚,QSystemTrayIcon::showMessage()调用的是Windows传统的托盘气泡通知API(Shell_NotifyIcon),而Windows 10的「新式Toast通知」是基于WinRT的ToastNotificationManager实现的。不过你要检查的「程序通知开关」是系统级的,不管用哪种通知方式,这个开关都会控制程序是否能发送通知——前提是你的程序有唯一的AppUserModelID,这是关键!
步骤1:给你的Qt程序设置AppUserModelID
Windows需要通过这个ID识别你的程序,才能在「通知和操作」列表里显示对应的开关。在程序启动时调用Win32 API设置:
#include <windows.h> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 替换成你的程序唯一标识,比如"com.yourteam.yourappname" const wchar_t* appID = L"com.yourteam.yourappname"; HRESULT hr = SetCurrentProcessExplicitAppUserModelID(appID); if (FAILED(hr)) { qDebug() << "设置AppUserModelID失败,错误码:" << hr; } // 后续初始化代码... return a.exec(); }
步骤2:检查通知开关状态
有了AppUserModelID后,有两种方法可以检查开关是否开启:
方法1:读取注册表(简单通用)
Windows会把程序的通知设置存在注册表中,直接读取即可:
#include <QSettings> bool isNotificationEnabled() { // 注意这里的AppID要和之前设置的完全一致 const QString regPath = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Notifications\\Settings\\com.yourteam.yourappname"; QSettings settings(regPath, QSettings::NativeFormat); // 默认返回开启(如果注册表项不存在,说明程序还没被系统记录) return settings.value("Enabled", 1).toInt() == 1; }
方法2:调用Win32官方API(更可靠)
如果你的程序只针对Windows 10 1607及以上版本,可以用QueryNotificationSetting函数,这是官方推荐的方式:
#include <windows.h> #include <notification.h> #pragma comment(lib, "runtimeobject.lib") // 需要链接这个库 bool isNotificationEnabled() { NOTIFICATION_SETTING setting; // 同样传入你的AppUserModelID HRESULT hr = QueryNotificationSetting(L"com.yourteam.yourappname", &setting); if (SUCCEEDED(hr)) { return setting == NOTIFICATION_SETTING_ENABLED; } // 出错时默认返回开启,或者根据需求处理 return true; }
进阶:直接集成新式Toast通知
如果你最终目标是用新式Toast,那QSystemTrayIcon的气泡通知就不太合适了。推荐直接调用WinRT的ToastNotificationManager来实现,这样不仅能完美适配Windows 10的Toast样式,还能通过UserNotificationListener更精准地检查通知权限:
#include <winrt/Windows.UI.Notifications.h> #include <winrt/Windows.ApplicationModel.Core.h> using namespace winrt::Windows::UI::Notifications; using namespace winrt::Windows::ApplicationModel; // 程序启动时初始化WinRT环境 void initWinRT() { winrt::init_apartment(); // 设置AppUserModelID CoreApplication::Current().AppUserModelId(L"com.yourteam.yourappname"); } // 检查新式Toast的权限 bool isToastNotificationAllowed() { auto listener = UserNotificationListener::Current(); auto accessStatus = listener.RequestAccessAsync().get(); return accessStatus == UserNotificationListenerAccessStatus::Allowed; } // 发送新式Toast示例 void showNewToast() { // 构造Toast内容(XML格式) const wchar_t toastXml[] = L"<toast><visual><binding template='ToastGeneric'><text>我的新式通知</text><text>这是Qt程序发送的Windows 10 Toast</text></binding></visual></toast>"; XmlDocument doc; doc.LoadXml(toastXml); ToastNotification toast(doc); ToastNotificationManager::CreateToastNotifier().Show(toast); }
注意这种方法需要用MSVC编译器(GCC对WinRT支持不好),并且在Qt的.pro文件里添加:
LIBS += -lruntimeobject
内容的提问来源于stack exchange,提问作者Marris K.
相关产品推荐
相关产品推荐

