From 475e6f00c02b625b1485fab1ba458c97dc58671d Mon Sep 17 00:00:00 2001 From: Mohammed Boujemaoui Boulaghmoudi Date: Thu, 11 May 2017 22:00:45 +0200 Subject: [PATCH 1/6] Move string Wrapper to cpp file. --- src/wintoastlib.cpp | 47 +++++++++++++++++++++++++-------------------- src/wintoastlib.h | 10 ---------- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/wintoastlib.cpp b/src/wintoastlib.cpp index 1a21ca9..c6416a1 100644 --- a/src/wintoastlib.cpp +++ b/src/wintoastlib.cpp @@ -10,7 +10,6 @@ #else #define DEBUG_MSG(str) do { std::wcout << str << std::endl; } while( false ) #endif - using namespace WinToastLib; namespace DllImporter { @@ -64,6 +63,30 @@ namespace DllImporter { } } +class WinToastStringWrapper { +public: + WinToastStringWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() { + HRESULT hr = DllImporter::WindowsCreateStringReference(stringRef, length, &_header, &_hstring); + if (!SUCCEEDED(hr)) { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); + } + } + WinToastStringWrapper(_In_ const std::wstring &stringRef) throw() { + HRESULT hr = DllImporter::WindowsCreateStringReference(stringRef.c_str(), static_cast(stringRef.length()), &_header, &_hstring); + if (FAILED(hr)) { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); + } + } + ~WinToastStringWrapper() { + DllImporter::WindowsDeleteString(_hstring); + } + inline HSTRING Get() const throw() { return _hstring; } +private: + HSTRING _hstring; + HSTRING_HEADER _header; + +}; + namespace Util { inline HRESULT defaultExecutablePath(_In_ WCHAR* path, _In_ DWORD nSize = MAX_PATH) { DWORD written = GetModuleFileNameEx(GetCurrentProcess(), nullptr, path, nSize); @@ -146,6 +169,8 @@ namespace Util { } } + + WinToast* WinToast::_instance = nullptr; WinToast* WinToast::instance() { if (_instance == nullptr) { @@ -462,26 +487,6 @@ void WinToastHandler::toastDismissed(WinToastHandler::WinToastDismissalReason st } -WinToastStringWrapper::WinToastStringWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() { - HRESULT hr = DllImporter::WindowsCreateStringReference(stringRef, length, &_header, &_hstring); - if (!SUCCEEDED(hr)) { - RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); - } -} -WinToastStringWrapper::WinToastStringWrapper(const std::wstring &stringRef) -{ - HRESULT hr = DllImporter::WindowsCreateStringReference(stringRef.c_str(), static_cast(stringRef.length()), &_header, &_hstring); - if (FAILED(hr)) { - RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); - } -} - -WinToastStringWrapper::~WinToastStringWrapper() { - DllImporter::WindowsDeleteString(_hstring); -} -HSTRING WinToastStringWrapper::Get() const throw() { - return _hstring; -} diff --git a/src/wintoastlib.h b/src/wintoastlib.h index 2fc1aff..bd4d634 100644 --- a/src/wintoastlib.h +++ b/src/wintoastlib.h @@ -27,17 +27,7 @@ using namespace Windows::Foundation; #define DEFAULT_LINK_FORMAT L".lnk" namespace WinToastLib { - class WinToastStringWrapper { - public: - WinToastStringWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw(); - WinToastStringWrapper(_In_ const std::wstring &stringRef) throw(); - ~WinToastStringWrapper(); - HSTRING Get() const throw(); - private: - HSTRING _hstring; - HSTRING_HEADER _header; - }; class WinToastHandler { From d204012849d37b284cf8fbbab42cc54ddcf11380 Mon Sep 17 00:00:00 2001 From: Mohammed Boujemaoui Boulaghmoudi Date: Thu, 11 May 2017 22:02:02 +0200 Subject: [PATCH 2/6] Just set the enumeration in a inline definition. --- src/wintoastlib.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/wintoastlib.h b/src/wintoastlib.h index bd4d634..dfe25f1 100644 --- a/src/wintoastlib.h +++ b/src/wintoastlib.h @@ -27,9 +27,6 @@ using namespace Windows::Foundation; #define DEFAULT_LINK_FORMAT L".lnk" namespace WinToastLib { - - - class WinToastHandler { public: enum WinToastDismissalReason { @@ -48,12 +45,7 @@ namespace WinToastLib { class WinToastTemplate { public: - enum TextField { - FirstLine = 0, - SecondLine, - ThirdLine, - LineCount - }; + enum TextField { FirstLine = 0, SecondLine, ThirdLine }; enum WinToastTemplateType { ImageAndText01 = ToastTemplateType::ToastTemplateType_ToastImageAndText01, From 8aa2f6936fcb211c4239e83d1a749c476c3cef43 Mon Sep 17 00:00:00 2001 From: Mohammed Boujemaoui Boulaghmoudi Date: Thu, 11 May 2017 22:05:12 +0200 Subject: [PATCH 3/6] Make the creator public to enable creation of custom notifier. Make some function protected to modify internal parameters. --- src/wintoastlib.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/wintoastlib.h b/src/wintoastlib.h index dfe25f1..8e32fdf 100644 --- a/src/wintoastlib.h +++ b/src/wintoastlib.h @@ -81,6 +81,7 @@ namespace WinToastLib { class WinToast { public: + WinToast(void); static WinToast* instance(); static bool isCompatible(); static std::wstring configureAUMI(_In_ const std::wstring& company, @@ -95,6 +96,13 @@ namespace WinToastLib { std::wstring appUserModelId() const; void setAppUserModelId(_In_ const std::wstring& appName); void setAppName(_In_ const std::wstring& appName); + + protected: + inline IXmlDocument* xmlDocument() const { return _xmlDocument.Get(); } + inline IToastNotifier* notifier() const { return _notifier.Get(); } + inline IToastNotificationFactory* notificationFactory() const { return _notificationFactory.Get(); } + inline IToastNotificationManagerStatics* notificationManager() const { return _notificationManager.Get(); } + inline IToastNotification* notification() const { return _notification.Get(); } private: bool _isInitialized; std::wstring _appName; @@ -106,13 +114,6 @@ namespace WinToastLib { ComPtr _notification; static WinToast* _instance; - WinToast(void); - IXmlDocument* xmlDocument() const { return _xmlDocument.Get(); } - IToastNotifier* notifier() const { return _notifier.Get(); } - IToastNotificationFactory* notificationFactory() const { return _notificationFactory.Get(); } - IToastNotificationManagerStatics* notificationManager() const { return _notificationManager.Get(); } - IToastNotification* notification() const { return _notification.Get(); } - HRESULT validateShellLink(); HRESULT createShellLink(); HRESULT setImageField(_In_ const std::wstring& path); From a85ca5d680e85a5023464e5c089869685643ee23 Mon Sep 17 00:00:00 2001 From: Mohammed Boujemaoui Boulaghmoudi Date: Thu, 11 May 2017 22:11:05 +0200 Subject: [PATCH 4/6] Interface to customize your own notifier. --- src/wintoastlib.cpp | 3 +++ src/wintoastlib.h | 19 +++++-------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/wintoastlib.cpp b/src/wintoastlib.cpp index c6416a1..7553200 100644 --- a/src/wintoastlib.cpp +++ b/src/wintoastlib.cpp @@ -184,6 +184,9 @@ WinToast::WinToast() : _isInitialized(false) DllImporter::initialize(); } +WinToast::~WinToast() { +} + void WinToast::setAppName(_In_ const std::wstring& appName) { _appName = appName; } diff --git a/src/wintoastlib.h b/src/wintoastlib.h index 8e32fdf..a447c3c 100644 --- a/src/wintoastlib.h +++ b/src/wintoastlib.h @@ -25,7 +25,6 @@ using namespace Windows::Foundation; #define DEFAULT_SHELL_LINKS_PATH L"\\Microsoft\\Windows\\Start Menu\\Programs\\" #define DEFAULT_LINK_FORMAT L".lnk" - namespace WinToastLib { class WinToastHandler { public: @@ -34,19 +33,15 @@ namespace WinToastLib { ApplicationHidden = ToastDismissalReason::ToastDismissalReason_ApplicationHidden, TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut }; - virtual ~WinToastHandler() {} - virtual void toastActivated() const; virtual void toastDismissed(WinToastDismissalReason state) const; virtual void toastFailed() const; }; - class WinToastTemplate - { + class WinToastTemplate { public: enum TextField { FirstLine = 0, SecondLine, ThirdLine }; - enum WinToastTemplateType { ImageAndText01 = ToastTemplateType::ToastTemplateType_ToastImageAndText01, ImageAndText02 = ToastTemplateType::ToastTemplateType_ToastImageAndText02, @@ -61,7 +56,6 @@ namespace WinToastLib { WinToastTemplate(_In_ const WinToastTemplateType& type = ImageAndText02); ~WinToastTemplate(); - int textFieldsCount() const { return _textFields.size(); } bool hasImage() const { return _hasImage; } std::vector textFields() const { return _textFields; } @@ -82,6 +76,7 @@ namespace WinToastLib { class WinToast { public: WinToast(void); + virtual ~WinToast(); static WinToast* instance(); static bool isCompatible(); static std::wstring configureAUMI(_In_ const std::wstring& company, @@ -89,9 +84,9 @@ namespace WinToastLib { _In_ const std::wstring& surname, _In_ const std::wstring& versionInfo ); - bool initialize(); - bool isInitialized() const { return _isInitialized; } - bool showToast(_In_ const WinToastTemplate& toast, _In_ WinToastHandler* handler); + virtual bool initialize(); + virtual bool isInitialized() const { return _isInitialized; } + virtual bool showToast(_In_ const WinToastTemplate& toast, _In_ WinToastHandler* handler); std::wstring appName() const; std::wstring appUserModelId() const; void setAppUserModelId(_In_ const std::wstring& appName); @@ -119,9 +114,5 @@ namespace WinToastLib { HRESULT setImageField(_In_ const std::wstring& path); HRESULT setTextField(_In_ const std::wstring& text, _In_ int pos); }; - - - } - #endif // WINTOASTLIB_H From 77c42f5478dcee5f0282e0ee0ec27513345a0c25 Mon Sep 17 00:00:00 2001 From: Mohammed Boujemaoui Boulaghmoudi Date: Thu, 11 May 2017 22:12:49 +0200 Subject: [PATCH 5/6] WinToast Handler is an interface --- .../WinToastExample/mainwindow.cpp | 4 +- src/wintoastlib.cpp | 41 ++----------------- src/wintoastlib.h | 11 +++-- 3 files changed, 11 insertions(+), 45 deletions(-) diff --git a/example/qt-gui-example/WinToastExample/mainwindow.cpp b/example/qt-gui-example/WinToastExample/mainwindow.cpp index 52cfd9d..edb2687 100644 --- a/example/qt-gui-example/WinToastExample/mainwindow.cpp +++ b/example/qt-gui-example/WinToastExample/mainwindow.cpp @@ -41,7 +41,7 @@ void MainWindow::on_showToast_clicked() templ.setTextField(ui->secondLine->text().toStdWString(), WinToastTemplate::SecondLine); templ.setTextField(ui->secondLine->text().toStdWString(), WinToastTemplate::ThirdLine); - if (!WinToast::instance()->showToast(templ, new WinToastHandler)) { + /* if (!WinToast::instance()->showToast(templ, new IWinToastHandler)) { QMessageBox::warning(this, "Error", "Could not launch your toast notification!"); - } + }*/ } diff --git a/src/wintoastlib.cpp b/src/wintoastlib.cpp index 7553200..021dafc 100644 --- a/src/wintoastlib.cpp +++ b/src/wintoastlib.cpp @@ -132,7 +132,7 @@ namespace Util { return hr; } - inline HRESULT setEventHandlers(_In_ IToastNotification* notification, _In_ std::shared_ptr eventHandler) { + inline HRESULT setEventHandlers(_In_ IToastNotification* notification, _In_ std::shared_ptr eventHandler) { EventRegistrationToken activatedToken, dismissedToken, failedToken; HRESULT hr = notification->add_Activated( Callback < Implements < RuntimeClassFlags, @@ -151,7 +151,7 @@ namespace Util { ToastDismissalReason reason; if (SUCCEEDED(e->get_Reason(&reason))) { - eventHandler->toastDismissed(static_cast(reason)); + eventHandler->toastDismissed(static_cast(reason)); } return S_OK; }).Get(), &dismissedToken); @@ -366,7 +366,7 @@ HRESULT WinToast::createShellLink() { -bool WinToast::showToast(_In_ const WinToastTemplate& toast, _In_ WinToastHandler* handler) { +bool WinToast::showToast(_In_ const WinToastTemplate& toast, _In_ IWinToastHandler* handler) { if (!isInitialized()) { DEBUG_MSG("Error when launching the toast. WinToast is not initialized =("); return _isInitialized; @@ -383,7 +383,7 @@ bool WinToast::showToast(_In_ const WinToastTemplate& toast, _In_ WinToastHandl if (SUCCEEDED(hr)) { hr = _notificationFactory->CreateToastNotification(xmlDocument(), &_notification); if (SUCCEEDED(hr)) { - hr = Util::setEventHandlers(notification(), std::shared_ptr(handler)); + hr = Util::setEventHandlers(notification(), std::shared_ptr(handler)); if (SUCCEEDED(hr)) { hr = _notifier->Show(notification()); } @@ -441,7 +441,6 @@ WinToastTemplate::WinToastTemplate(const WinToastTemplateType& type) : initComponentsFromType(); } - WinToastTemplate::~WinToastTemplate() { _textFields.clear(); @@ -461,35 +460,3 @@ void WinToastTemplate::initComponentsFromType() { _hasImage = _type < Text01; _textFields = std::vector(TextFieldsCount[_type], L""); } - - -void WinToastHandler::toastActivated() const { - std::wcout << L"The user clicked in this toast" << std::endl; - -} - -void WinToastHandler::toastFailed() const { - std::wcout << L"Error showing current toast" << std::endl; -} - -void WinToastHandler::toastDismissed(WinToastHandler::WinToastDismissalReason state) const { - switch (state) { - case UserCanceled: - std::wcout << L"The user dismissed this toast" << std::endl; - break; - case ApplicationHidden: - std::wcout << L"The application hid the toast using ToastNotifier.hide()" << std::endl; - break; - case TimedOut: - std::wcout << L"The toast has timed out" << std::endl; - break; - default: - std::wcout << L"Toast not activated" << std::endl; - break; - } -} - - - - - diff --git a/src/wintoastlib.h b/src/wintoastlib.h index a447c3c..9548d04 100644 --- a/src/wintoastlib.h +++ b/src/wintoastlib.h @@ -26,17 +26,16 @@ using namespace Windows::Foundation; #define DEFAULT_SHELL_LINKS_PATH L"\\Microsoft\\Windows\\Start Menu\\Programs\\" #define DEFAULT_LINK_FORMAT L".lnk" namespace WinToastLib { - class WinToastHandler { + class IWinToastHandler { public: enum WinToastDismissalReason { UserCanceled = ToastDismissalReason::ToastDismissalReason_UserCanceled, ApplicationHidden = ToastDismissalReason::ToastDismissalReason_ApplicationHidden, TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut }; - virtual ~WinToastHandler() {} - virtual void toastActivated() const; - virtual void toastDismissed(WinToastDismissalReason state) const; - virtual void toastFailed() const; + virtual void toastActivated() const = 0; + virtual void toastDismissed(WinToastDismissalReason state) const = 0; + virtual void toastFailed() const = 0; }; class WinToastTemplate { @@ -86,7 +85,7 @@ namespace WinToastLib { ); virtual bool initialize(); virtual bool isInitialized() const { return _isInitialized; } - virtual bool showToast(_In_ const WinToastTemplate& toast, _In_ WinToastHandler* handler); + virtual bool showToast(_In_ const WinToastTemplate& toast, _In_ IWinToastHandler* handler); std::wstring appName() const; std::wstring appUserModelId() const; void setAppUserModelId(_In_ const std::wstring& appName); From 7f81d42a5bae66074785f74bec6028886faadb39 Mon Sep 17 00:00:00 2001 From: Mohammed Boujemaoui Boulaghmoudi Date: Thu, 11 May 2017 22:17:50 +0200 Subject: [PATCH 6/6] Fixing example. --- .../WinToastExample/mainwindow.cpp | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/example/qt-gui-example/WinToastExample/mainwindow.cpp b/example/qt-gui-example/WinToastExample/mainwindow.cpp index edb2687..1f8070e 100644 --- a/example/qt-gui-example/WinToastExample/mainwindow.cpp +++ b/example/qt-gui-example/WinToastExample/mainwindow.cpp @@ -33,6 +33,33 @@ void MainWindow::on_imagePathSelector_clicked() } +class CustomHandler : public IWinToastHandler { +public: + void toastActivated() const { + std::wcout << L"The user clicked in this toast" << std::endl; + } + + void toastFailed() const { + std::wcout << L"Error showing current toast" << std::endl; + } + void toastDismissed(WinToastDismissalReason state) const { + switch (state) { + case UserCanceled: + std::wcout << L"The user dismissed this toast" << std::endl; + break; + case ApplicationHidden: + std::wcout << L"The application hid the toast using ToastNotifier.hide()" << std::endl; + break; + case TimedOut: + std::wcout << L"The toast has timed out" << std::endl; + break; + default: + std::wcout << L"Toast not activated" << std::endl; + break; + } + } +}; + void MainWindow::on_showToast_clicked() { WinToastTemplate templ = WinToastTemplate(WinToastTemplate::ImageAndText04); @@ -41,7 +68,9 @@ void MainWindow::on_showToast_clicked() templ.setTextField(ui->secondLine->text().toStdWString(), WinToastTemplate::SecondLine); templ.setTextField(ui->secondLine->text().toStdWString(), WinToastTemplate::ThirdLine); - /* if (!WinToast::instance()->showToast(templ, new IWinToastHandler)) { + + + if (!WinToast::instance()->showToast(templ, new CustomHandler())) { QMessageBox::warning(this, "Error", "Could not launch your toast notification!"); - }*/ + } }