#include "stdafx.h" ToastNotification::ToastNotification(_In_ wchar_t* text, _In_ wchar_t* caption, _In_ wchar_t* imagePath) : _text(text), _caption(caption), _imagePath(imagePath) { } ToastNotification::~ToastNotification() { } HRESULT ToastNotification::GetNodeByTag(_In_ HSTRING tagName, _Outptr_ ABI::Windows::Data::Xml::Dom::IXmlNode **node, _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument* xml) { Microsoft::WRL::ComPtr nodeList; HRESULT hr = xml->GetElementsByTagName(tagName, &nodeList); if (FAILED(hr)) return hr; UINT32 length; hr = nodeList->get_Length(&length); if (FAILED(hr)) return hr; if (length == 0) return E_INVALIDARG; return nodeList->Item(0, node); } HRESULT ToastNotification::AddNode(_In_ HSTRING name, _Outptr_ ABI::Windows::Data::Xml::Dom::IXmlNode **node, _In_ ABI::Windows::Data::Xml::Dom::IXmlNode *rootNode, _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument* xml) { Microsoft::WRL::ComPtr element; HRESULT hr = xml->CreateElement(name, &element); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr tempNode; hr = element.As(&tempNode); if (FAILED(hr)) return hr; return rootNode->AppendChild(tempNode.Get(), node); } HRESULT ToastNotification::SetNodeValueString(_In_ HSTRING inputString, _In_ ABI::Windows::Data::Xml::Dom::IXmlNode* node, _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument* xml) { Microsoft::WRL::ComPtr inputText; HRESULT hr = xml->CreateTextNode(inputString, &inputText); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr inputTextNode; hr = inputText.As(&inputTextNode); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr pAppendedChild; return hr = node->AppendChild(inputTextNode.Get(), &pAppendedChild); } HRESULT ToastNotification::SetTextValues(_In_reads_(textValuesCount) wchar_t** textValues, _In_ UINT32 textValuesCount, _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument* xml) { HRESULT hr = textValues != nullptr && textValuesCount > 0 ? S_OK : E_INVALIDARG; if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr nodeList; hr = xml->GetElementsByTagName(StringReferenceWrapper(L"text").Get(), &nodeList); if (FAILED(hr)) return hr; UINT32 nodeListLength; hr = nodeList->get_Length(&nodeListLength); if (FAILED(hr)) return hr; hr = textValuesCount <= nodeListLength ? S_OK : E_INVALIDARG; if (FAILED(hr)) return hr; for (UINT32 i = 0; i < textValuesCount; i++) { Microsoft::WRL::ComPtr textNode; hr = nodeList->Item(i, &textNode); if (FAILED(hr)) return hr; hr = SetNodeValueString(StringReferenceWrapper(textValues[i], (UINT32)wcslen(textValues[i])).Get(), textNode.Get(), xml); if (FAILED(hr)) return hr; } return S_OK; } HRESULT ToastNotification::SetImageSrc(_In_z_ wchar_t* imagePath, _In_ ABI::Windows::Data::Xml::Dom::IXmlDocument* xml) { wchar_t imageSrc[MAX_PATH] = L"file:///"; HRESULT hr = StringCchCat(imageSrc, ARRAYSIZE(imageSrc), imagePath); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr imageNode; hr = GetNodeByTag(StringReferenceWrapper(L"image").Get(), &imageNode, xml); Microsoft::WRL::ComPtr attributes; hr = imageNode->get_Attributes(&attributes); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr srcAttribute; hr = attributes->GetNamedItem(StringReferenceWrapper(L"src").Get(), &srcAttribute); if (FAILED(hr)) return hr; return hr = SetNodeValueString(StringReferenceWrapper(imageSrc).Get(), srcAttribute.Get(), xml); } HRESULT ToastNotification::Setup(_In_ ABI::Windows::Data::Xml::Dom::IXmlDocument* xml) { Microsoft::WRL::ComPtr toastNode; HRESULT hr = GetNodeByTag(StringReferenceWrapper(L"toast").Get(), &toastNode, xml); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr audioNode; hr = AddNode(StringReferenceWrapper(L"audio").Get(), &audioNode, toastNode.Get(), xml); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr attributes; hr = audioNode->get_Attributes(&attributes); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr silentAttribute; hr = xml->CreateAttribute(StringReferenceWrapper(L"silent").Get(), &silentAttribute); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr silentAttributeNode; hr = silentAttribute.As(&silentAttributeNode); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr tempNode; hr = attributes->SetNamedItem(silentAttributeNode.Get(), &tempNode); if (FAILED(hr)) return hr; return SetNodeValueString(StringReferenceWrapper(L"true").Get(), silentAttributeNode.Get(), xml); } HRESULT ToastNotification::CreateXml(_Outptr_ ABI::Windows::Data::Xml::Dom::IXmlDocument** xml) { Microsoft::WRL::ComPtr notificationManager; HRESULT hr = Windows::Foundation::GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), ¬ificationManager); if (FAILED(hr)) RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); ABI::Windows::UI::Notifications::ToastTemplateType templateId = _imagePath == nullptr ? ABI::Windows::UI::Notifications::ToastTemplateType_ToastText02 : ABI::Windows::UI::Notifications::ToastTemplateType_ToastImageAndText02; hr = notificationManager->GetTemplateContent(templateId, xml); if (FAILED(hr)) return hr; hr = Setup(*xml); if (FAILED(hr)) return hr; if (_imagePath) { hr = SetImageSrc(_imagePath, *xml); if (FAILED(hr)) return hr; } wchar_t* textValues[] = { _caption == nullptr ? L"Miranda NG" : _caption, _text }; return SetTextValues(textValues, _countof(textValues), *xml); } HRESULT ToastNotification::Create(_Outptr_ ABI::Windows::UI::Notifications::IToastNotification** notification) { Microsoft::WRL::ComPtr xml; HRESULT hr = CreateXml(&xml); if (FAILED(hr)) return hr; Microsoft::WRL::ComPtr factory; hr = Windows::Foundation::GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &factory); if (FAILED(hr)) return hr; return hr = factory->CreateToastNotification(xml.Get(), notification); } HRESULT ToastNotification::Show() { return Show(new ToastEventHandler(nullptr)); } HRESULT ToastNotification::Show(_In_ ToastEventHandler* handler) { Microsoft::WRL::ComPtr notificationManager; HRESULT hr = Windows::Foundation::GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), ¬ificationManager); if (FAILED(hr)) return hr; //RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); hr = notificationManager->CreateToastNotifierWithId(StringReferenceWrapper(::AppUserModelID).Get(), ¬ifier); if (FAILED(hr)) return hr; hr = Create(¬ification); if (FAILED(hr)) return hr; EventRegistrationToken activatedToken, dismissedToken, failedToken; Microsoft::WRL::ComPtr eventHandler(handler); hr = notification->add_Activated(eventHandler.Get(), &activatedToken); if (FAILED(hr)) return hr; notification->add_Activated(eventHandler.Get(), &activatedToken); notification->add_Dismissed(eventHandler.Get(), &dismissedToken); notification->add_Failed(eventHandler.Get(), &failedToken); return notifier->Show(notification.Get()); } HRESULT ToastNotification::Hide() { return notifier->Hide(notification.Get()); }