【问题标题】:Activation from C++/WinRT DLL从 C++/WinRT DLL 激活
【发布时间】:2018-08-22 06:45:25
【问题描述】:

我正在尝试将 Windows 10 通知的通用包装器编写为 DLL。我已经设法编写了一个 DLL,它几乎可以完成 API 提供的所有功能,但我无法收到移动到操作中心的通知。据我所知,我需要注册 COM INotificationActivationCallback 才能让通知留在操作中心,尽管我不明白为什么。

我希望这个库可以从较旧的 MinGW 编译代码库中访问,因此制作了一个基于使用 C 样式函数访问 C++ 类的 API。支持实现如下,为简洁起见省略了一些错误处理和其他细节。

using namespace winrt::Windows;
using namespace UI;


class Win10NotificationManager {
public:
    Win10NotificationManager(NotificationCallback, const wchar_t * appUserModelID, void * userdata);
    virtual ~Win10NotificationManager();

    void createNotification(const wchar_t * xml);
    void clearNotifications();

private:
    void toast_Failed(const Notifications::ToastNotification &, const Notifications::ToastFailedEventArgs & args);
    void toast_Dismissed(const Notifications::ToastNotification &, const Notifications::ToastDismissedEventArgs & args);
    void toast_Activated(const Notifications::ToastNotification &, const Foundation::IInspectable & object);

    std::wstring appUserModelID_;
    NotificationCallback cb_;
    void * userdata_;
};


Win10NotificationManager::Win10NotificationManager(NotificationCallback cb, const wchar_t * appUserModelID, void * userdata)
    : appUserModelID_(appUserModelID)
    , cb_(cb)
    , userdata_(userdata)
{
}

Win10NotificationManager::~Win10NotificationManager() {
}

void Win10NotificationManager::createNotification(const wchar_t * xml) {
    // Create an XmlDocument from string
    Xml::Dom::XmlDocument xmlDoc;
    xmlDoc.LoadXml(xml);

    // Create a toast object
    Notifications::ToastNotification toast(xmlDoc);

    // register event handlers
    toast.Dismissed(Foundation::TypedEventHandler<Notifications::ToastNotification, Notifications::ToastDismissedEventArgs>(this, &Win10NotificationManager::toast_Dismissed));
    toast.Failed(Foundation::TypedEventHandler<Notifications::ToastNotification, Notifications::ToastFailedEventArgs>(this, &Win10NotificationManager::toast_Failed));
    toast.Activated(Foundation::TypedEventHandler<Notifications::ToastNotification, Foundation::IInspectable>(this, &Win10NotificationManager::toast_Activated));

    // show
    auto notifier = Notifications::ToastNotificationManager::CreateToastNotifier(appUserModelID_);
    notifier.Show(toast);
}

void Win10NotificationManager::toast_Failed(const Notifications::ToastNotification &, const Notifications::ToastFailedEventArgs & args) {
    HRESULT hr = args.ErrorCode();
    winrt::check_hresult(hr);
}

void Win10NotificationManager::toast_Dismissed(const Notifications::ToastNotification &, const Notifications::ToastDismissedEventArgs &) {
    cb_(nullptr, userdata_);
}

void Win10NotificationManager::toast_Activated(const Notifications::ToastNotification &, const Foundation::IInspectable & object) {
    Notifications::IToastActivatedEventArgs args = winrt::unbox_value<Notifications::IToastActivatedEventArgs>(object);
    cb_(args.Arguments().begin(), userdata_);
}

void Win10NotificationManager::clearNotifications() {
    auto history = Notifications::ToastNotificationManager::History();
    history.Clear(appUserModelID_);
}

这很好用,除了提到的缺少 Action Center 持久性。由于 DLL 是通用的(不是特定于我的一个应用程序),我想避免将 COM 激活烘焙到 DLL 中。我不需要让通知在调用进程的生命周期之后持续存在,但如果通知在 5 秒后不会永远消失,那就太好了。

如果需要,我可以使用 Visual Studio 2017 解决方案创建一个要点。

【问题讨论】:

    标签: notifications com c++-winrt


    【解决方案1】:

    为了从桌面使用通知 API,它需要注册的 COM 服务器以及 shell 快捷方式。我不知道为什么这是必要的,但据我所知,这是使它工作的唯一方法。这个问题经常出现,所以我在这里写了一个简单的 C++/WinRT 示例:

    https://gist.github.com/kennykerr/d983767262118ae0366ef1ec282e428a

    希望对您有所帮助。

    【讨论】:

    • 我从要点成功地将缺失的部分合并到我的代码中。有时间我会考虑将生成的代码作为开源项目。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    • 1970-01-01
    • 2019-11-10
    • 1970-01-01
    相关资源
    最近更新 更多