#include "stdafx.h" #include using namespace Microsoft::WRL; static mir_cs csNotifications; static LIST lstNotifications(10, PtrKeySortT); void HideAllToasts() { mir_cslock lck(csNotifications); for (auto &it : lstNotifications.rev_iter()) if (it->IsValid()) delete it; lstNotifications.destroy(); } ///////////////////////////////////////////////////////////////////////////////////////// ToastNotification::ToastNotification( _In_ wchar_t *text, _In_ wchar_t *caption, _In_ wchar_t *imagePath, MCONTACT hContact, WNDPROC pWndProc, void *pData) : _text(text), _caption(caption), _imagePath(imagePath), _hContact(hContact), _pfnPopupProc(pWndProc), _pvPopupData(pData) { { mir_cslock lck(csNotifications); lstNotifications.insert(this); } if (FAILED(Windows::Foundation::GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), ¬ificationManager))) return; if (FAILED(notificationManager->CreateToastNotifierWithId(StringReferenceWrapper(::AppUserModelID).Get(), ¬ifier))) return; if (FAILED(Create(¬ification))) return; notification->add_Activated(Callback(this, &ToastNotification::OnActivate).Get(), &_ertActivated); notification->add_Dismissed(Callback(this, &ToastNotification::OnDismiss).Get(), &_ertDismissed); notification->add_Failed(Callback(this, &ToastNotification::OnFail).Get(), &_ertFailed); notifier->Show(notification.Get()); CallPopupProc(UM_INITPOPUP); } ToastNotification::~ToastNotification() { _signature = 0; if (_pvPopupData != nullptr) CallPopupProc(UM_FREEPLUGINDATA); if (notification) notifier->Hide(notification.Get()); } HRESULT ToastNotification::CreateXml(_Outptr_ ABI::Windows::Data::Xml::Dom::IXmlDocument **xml) { ComPtr xmlDocument; CHECKHR(Windows::Foundation::ActivateInstance(StringReferenceWrapper(RuntimeClass_Windows_Data_Xml_Dom_XmlDocument).Get(), &xmlDocument)); TiXmlDocument doc; TiXmlElement *xmlToast = doc.NewElement("toast"); doc.InsertEndChild(xmlToast); TiXmlElement *xmlAudioNode = doc.NewElement("audio"); xmlToast->InsertEndChild(xmlAudioNode); xmlAudioNode->SetAttribute("silent", "true"); TiXmlElement *xmlVisualNode = doc.NewElement("visual"); xmlToast->InsertEndChild(xmlVisualNode); TiXmlElement *xmlBindingNode = doc.NewElement("binding"); xmlVisualNode->InsertEndChild(xmlBindingNode); xmlBindingNode->SetAttribute("template", "ToastImageAndText02"); if (_imagePath) { TiXmlElement *xmlImageNode = doc.NewElement("image"); xmlBindingNode->InsertEndChild(xmlImageNode); xmlImageNode->SetAttribute("id", 1); xmlImageNode->SetAttribute("src", CMStringW(FORMAT, L"file:///%s", _imagePath)); } TiXmlElement *xmlTitleNode = doc.NewElement("text"); xmlBindingNode->InsertEndChild(xmlTitleNode); xmlTitleNode->SetAttribute("id", 1); xmlTitleNode->SetText(_caption != nullptr ? _caption : L"Miranda NG"); if (_text) { TiXmlElement *xmlTextNode = doc.NewElement("text"); xmlBindingNode->InsertEndChild(xmlTextNode); xmlTextNode->SetAttribute("id", 2); xmlTextNode->SetText(_text); } tinyxml2::XMLPrinter printer(0, true); doc.Print(&printer); Utf2T xtmp(printer.CStr()); CHECKHR(xmlDocument->LoadXml(StringReferenceWrapper(xtmp, (UINT32)mir_wstrlen(xtmp)).Get())); return xmlDocument.CopyTo(xml); } HRESULT ToastNotification::Create(_Outptr_ ABI::Windows::UI::Notifications::IToastNotification **_notification) { ComPtr xml; CHECKHR(CreateXml(&xml)); ComPtr factory; CHECKHR(Windows::Foundation::GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &factory)); return factory->CreateToastNotification(xml.Get(), _notification); } HRESULT ToastNotification::OnActivate(_In_ ABI::Windows::UI::Notifications::IToastNotification *, IInspectable *) { if (_signature == TOAST_SIGNATURE) { CallPopupProc(WM_COMMAND); Destroy(); } return S_OK; } HRESULT ToastNotification::OnDismiss(_In_ ABI::Windows::UI::Notifications::IToastNotification *, _In_ ABI::Windows::UI::Notifications::IToastDismissedEventArgs *e) { if (_signature == TOAST_SIGNATURE) { ABI::Windows::UI::Notifications::ToastDismissalReason tdr; CHECKHR(e->get_Reason(&tdr)); if (tdr == ABI::Windows::UI::Notifications::ToastDismissalReason_UserCanceled) CallPopupProc(WM_CONTEXTMENU); Destroy(); } return S_OK; } HRESULT ToastNotification::OnFail(_In_ ABI::Windows::UI::Notifications::IToastNotification *, _In_ ABI::Windows::UI::Notifications::IToastFailedEventArgs *) { if (_signature == TOAST_SIGNATURE) Destroy(); return S_OK; } void ToastNotification::Destroy() { if (_signature != TOAST_SIGNATURE) return; { mir_cslock lck(csNotifications); lstNotifications.remove(this); } delete this; }