从 C++/WinRT DLL 激活
Activation from C++/WinRT DLL
我正在尝试为 Windows 10 个通知编写通用包装器作为 DLL。我已经设法编写了一个 DLL,几乎可以完成 API 提供的所有功能,除了我无法收到移动到操作中心的通知。据我所知,我需要注册 COM INotificationActivationCallback 才能让通知保留在操作中心中,尽管我不明白为什么。
我希望这个库可以从旧的 MinGW 编译的代码库访问,因此已经制作了一个 API 基于使用 C 风格函数访问 C++ class。支持实现如下,为简洁起见省略了一些错误处理和其他细节。
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_);
}
这工作得很好,除了提到的缺少操作中心持久性。由于 DLL 是通用的(不特定于我的一个应用程序),我想避免将 COM 激活烘焙到 DLL 中。我不需要在调用进程的生命周期之后保留通知,但如果通知在 5 秒后不会永远消失就好了。
如果需要,我可以创建一个包含 Visual Studio 2017 解决方案的要点。
为了从桌面使用通知 API,它需要注册的 COM 服务器和 shell 快捷方式。我不知道为什么这是必要的,但据我所知,这是让它发挥作用的唯一方法。这个问题经常出现,所以我在这里写了一个简单的 C++/WinRT 示例:
https://gist.github.com/kennykerr/d983767262118ae0366ef1ec282e428a
希望对您有所帮助。
我正在尝试为 Windows 10 个通知编写通用包装器作为 DLL。我已经设法编写了一个 DLL,几乎可以完成 API 提供的所有功能,除了我无法收到移动到操作中心的通知。据我所知,我需要注册 COM INotificationActivationCallback 才能让通知保留在操作中心中,尽管我不明白为什么。
我希望这个库可以从旧的 MinGW 编译的代码库访问,因此已经制作了一个 API 基于使用 C 风格函数访问 C++ class。支持实现如下,为简洁起见省略了一些错误处理和其他细节。
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_);
}
这工作得很好,除了提到的缺少操作中心持久性。由于 DLL 是通用的(不特定于我的一个应用程序),我想避免将 COM 激活烘焙到 DLL 中。我不需要在调用进程的生命周期之后保留通知,但如果通知在 5 秒后不会永远消失就好了。
如果需要,我可以创建一个包含 Visual Studio 2017 解决方案的要点。
为了从桌面使用通知 API,它需要注册的 COM 服务器和 shell 快捷方式。我不知道为什么这是必要的,但据我所知,这是让它发挥作用的唯一方法。这个问题经常出现,所以我在这里写了一个简单的 C++/WinRT 示例:
https://gist.github.com/kennykerr/d983767262118ae0366ef1ec282e428a
希望对您有所帮助。