You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:23:53