HSPでWindows8のトースト通知(WinRTAPI使用)をしてみるサンプル Ver 0.01 (なぜか日本語が使えない)
改造大歓迎デス。
やってる内容としては、
1. AppUserModelID を含んだショートカットをプログラム一覧に作成
2. AppUserModelID を自分のウィンドウに反映
3. AppUserModelID 渡してトースト通知する
の3手順になっています。1.と2.の手順がないと、トースト通知されません。
HSPでWindows8のトースト通知(WinRTAPI使用)をしてみるサンプル Ver 0.01 (なぜか日本語が使えない)
改造大歓迎デス。
やってる内容としては、
1. AppUserModelID を含んだショートカットをプログラム一覧に作成
2. AppUserModelID を自分のウィンドウに反映
3. AppUserModelID 渡してトースト通知する
の3手順になっています。1.と2.の手順がないと、トースト通知されません。
#include "user32.as"#include "kernel32.as"#include "shell32.as"// HString#module mHString#uselib "msvcrt"#func calloc "calloc" int, int#func free "free" int#uselib "api-ms-win-core-winrt-string-l1-1-0.dll"#func WindowsCreateString "WindowsCreateString" wptr, int, sptr#func WindowsDeleteString "WindowsDeleteString" wptr// 文字列の長さ#func WindowsGetStringLen "WindowsGetStringLen" sptr// HSTRING_HEADERが返ってくるバージョンみたい?#func WindowsCreateStringReference "WindowsCreateStringReference" wptr, int, sptr, sptr#func WindowsGetStringRawBuffer "WindowsGetStringRawBuffer" sptr, sptr#defcfunc Unicode2HString str assdim ws, strlen(as)*2 + 2cnvstow ws, ashString = 0WindowsCreateString varptr(ws), strlen(as), varptr(hString)return hString// 未使用のため#defcfunc Unicode2HStringEx str as, var HSTRING_HEADERsdim ws, strlen(as)*2 + 2cnvstow ws, ashString = 0dim HSTRING_HEADER, 6WindowsCreateStringReference varptr(ws), strlen(as), varptr(HSTRING_HEADER), varptr(hString)return hString#deffunc DeleteHString int _hStringWindowsDeleteString _hStringreturn stat#defcfunc GetHStringLength int _hStringWindowsGetStringLen _hStringreturn stat#defcfunc HString2Unicode int _hStringif _hString == 0 : return ""size = GetHStringLength(_hString) * 2if size <= 0 : return ""WindowsGetStringRawBuffer _hString, varptr(size)dupptr buf, stat, GetHStringLength(_hString) * 2, 2return cnvwtos(buf)#global#module mCOMOBJMACRO#define global ctype SUCCEEDED(%1) ((%1) >= 0)#define global SafeRelease(%1) if ((varuse(%1)) && (vartype(%1) == 6)){ \delcom %1: \%1 = 0 \}#global// ショートカット作成#module mSHORTCUT#uselib "Propsys"#func InitPropVariantFromStringVector "InitPropVariantFromStringVector" wptr, int, sptr#uselib "Ole32"#func PropVariantClear "PropVariantClear" sptr#define CLSID_ShellLink "{00021401-0000-0000-C000-000000000046}"#define IID_IShellLink "{000214EE-0000-0000-C000-000000000046}"#usecom IShellLink IID_IShellLink CLSID_ShellLink#comfunc IShellLink_SetArguments 11 str#comfunc IShellLink_SetIconLocation 17 str, int#comfunc IShellLink_SetPath 20 str#define IID_IPersistFile "{0000010b-0000-0000-C000-000000000046}"#usecom IPersistFile IID_IPersistFile#comfunc IPersistFile_Save 6 wstr, int#define IID_IPropertyStore "{886d8eeb-8cf2-4446-8d02-cdba1dbdcf99}"#define CLSID_PropertyStore "{e4796550-df61-448b-9193-13fc1341b163}"#usecom IPropertyStore IID_IPropertyStore CLSID_PropertyStore#comfunc IPropertyStore_SetValue 6 sptr, sptr#comfunc IPropertyStore_Commit 7#deffunc CreateShortcut str file_path, str arg, str icon_path, int icon_idx, str AppUserModelID, str out_path, \local pShellLink, \local pPropStore, \local wstring, \local wstrings, \local ppropvar, \local PKEY_AppUserModel_ID, \local hrhr = 0pShellLink = 0pPropStore = 0newcom pShellLink, IShellLinkif varuse(pShellLink) == 0 : return -1IShellLink_SetPath pShellLink, file_path : hr = statif SUCCEEDED(hr){IShellLink_SetArguments pShellLink, arg : hr = statif SUCCEEDED(hr){IShellLink_SetIconLocation pShellLink, icon_path, icon_idx : hr = statif SUCCEEDED(hr){querycom pPropStore, pShellLink, IPropertyStoreif varuse(pPropStore){// Unicodeに変換sdim wstring, strlen(AppUserModelID) * 2 + 2cnvstow wstring, AppUserModelID// 配列なので(今回は1つしかないけど)wstrings = varptr(wstring)// PROPVARIANT 構造体dim ppropvar, 4// Unicode文字列→PROPVARIANT に変換InitPropVariantFromStringVector varptr(wstrings), 1/*今回は1つだけなので*/, varptr(ppropvar) : hr = statif SUCCEEDED(hr){PKEY_AppUserModel_ID = 0x9F4C2855, 0x4B399F79, 0xD4E1D0A8, 0xF3D5E12D, 5IPropertyStore_SetValue pPropStore, varptr(PKEY_AppUserModel_ID), varptr(ppropvar) : hr = statif SUCCEEDED(hr){IPropertyStore_Commit pPropStore : hr = statif SUCCEEDED(hr){IPersistFile_Save pShellLink, out_path, 1 : hr = stat}}PropVariantClear varptr(ppropvar)}}}}}// SafeReleaseSafeRelease pPropStoreSafeRelease pShellLinkreturn hr#global// AppUserModel_IDを設定(任意のタイミングで変更可能)#module mAPPIDS#uselib "shell32"#func SHGetPropertyStoreForWindow "SHGetPropertyStoreForWindow" sptr, sptr, sptr#func GetCurrentProcessExplicitAppUserModelID "GetCurrentProcessExplicitAppUserModelID" wptr#func SetCurrentProcessExplicitAppUserModelID "SetCurrentProcessExplicitAppUserModelID" wstr#uselib "Propsys"#func InitPropVariantFromString "InitPropVariantFromString" wstr, sptr#func InitPropVariantFromStringVector "InitPropVariantFromStringVector" wptr, int, sptr#func PropVariantToStringAlloc "PropVariantToStringAlloc" sptr, wptr#uselib "Ole32"#func PropVariantClear "PropVariantClear" sptr#define IID_IPropertyStore "{886d8eeb-8cf2-4446-8d02-cdba1dbdcf99}"#define CLSID_PropertyStore "{e4796550-df61-448b-9193-13fc1341b163}"#usecom IPropertyStore IID_IPropertyStore CLSID_PropertyStore#comfunc IPropertyStore_SetValue 6 sptr, sptr#comfunc IPropertyStore_Commit 7#deffunc SetAppUserModelID int _hwnd, str AppUserModelID, \local propStorePtr, \local IID_IPropertyStore_Array, \local pPropStore, \local wstring, \local wstrings, \local ppropvar, \local hrhr = 0pPropStore = 0propStorePtr = 0IID_IPropertyStore_Array = 0x886d8eeb, 0x44468cf2, 0xbacd028d, 0x99cfbd1dPKEY_AppUserModel_ID = 0x9F4C2855, 0x4B399F79, 0xD4E1D0A8, 0xF3D5E12D, 5SHGetPropertyStoreForWindow _hwnd, varptr(IID_IPropertyStore_Array), varptr(propStorePtr)if stat == 0 && propStorePtr != 0{newcom pPropStore, IPropertyStore, -1, propStorePtrif varuse(pPropStore){// Win7 では廃止されているらしい// propsys.dll 7.0/*mes varptr(InitPropVariantFromString)InitPropVariantFromString "net.hinekure.test.hsp3", varptr(ppropvar)*/// Unicodeに変換sdim wstring, strlen(AppUserModelID) * 2 + 2cnvstow wstring, AppUserModelID// 配列なので(今回は1つしかないけど)wstrings = varptr(wstring)// PROPVARIANT 構造体dim ppropvar, 4// Unicode文字列→PROPVARIANT に変換InitPropVariantFromStringVector varptr(wstrings), 1, varptr(ppropvar) : hr = statif SUCCEEDED(hr){IPropertyStore_SetValue pPropStore, varptr(PKEY_AppUserModel_ID), varptr(ppropvar) : hr = statif SUCCEEDED(hr){IPropertyStore_Commit pPropStore : hr = stat}PropVariantClear varptr(ppropvar)}}}// SafeReleaseSafeRelease pPropStorereturn hr#global#module mToast#uselib "Combase.dll"#func RoGetActivationFactory "RoGetActivationFactory" sptr, sptr, sptr#func RoActivateInstance "RoActivateInstance" sptr, sptr#func RoInitialize "RoInitialize" int#func RoUninitialize "RoUninitialize"#define IID_IToastNotificationManagerStatics "{50ac103f-d235-4598-bbef-98fe4d1a3ad4}"#define CLSID_ToastNotificationManagerStatics "{6db7cd52-e3b7-4ecc-bb1f-388aeef6bb50}"#usecom IToastNotificationManagerStatics IID_IToastNotificationManagerStatics CLSID_ToastNotificationManagerStatics// WinRT は0~5まで使ってる#comfunc IToastNotificationManagerStatics_CreateToastNotifier 6 sptr#comfunc IToastNotificationManagerStatics_CreateToastNotifierWithId 7 sptr, sptr#comfunc IToastNotificationManagerStatics_GetTemplateContent 8 int, sptr;#define CLSID_XMLDocument "{CFC399AF-D876-11d0-9C10-00C04FC99C8E}";#define IID_IXMLDocument "{F52E2B61-18A1-11d1-B105-00805F49916B}"#define CLSID_XMLDocument "{AF75D6AD-E307-4052-8CB1-BF2052E734F0}"#define IID_IXMLDocument "{F7F3A506-1E87-42D6-BCFB-B8C809FA5494}"#usecom IXMLDocument IID_IXMLDocument CLSID_XMLDocument// WinRT は0~5まで使ってる#comfunc IXMLDocument_CreateTextNode 11 sptr, sptr#comfunc IXMLDocument_GetElementsByTagName 16 sptr, sptr#define CLSID_XmlNodeList "{AF75D6AD-E307-4052-8CB1-BF2052E734F0}"#define IID_IXmlNodeList "{8C60AD77-83A4-4EC1-9C54-7BA429E13DA6}"#usecom IXmlNodeList IID_IXmlNodeList CLSID_XmlNodeList// WinRT は0~5まで使ってる#comfunc IXmlNodeList_get_Length 6 sptr#comfunc IXmlNodeList_Item 7 int, sptr#define CLSID_XmlNode "{AF75D6AD-E307-4052-8CB1-BF2052E734F0}"#define IID_IXmlNode "{1C741D59-2122-47D5-A856-83F3D4214875}"#usecom IXmlNode IID_IXmlNode CLSID_XmlNode#comfunc IXmlNode_get_NodeValue 6 sptr#comfunc IXmlNode_get_NodeType 8 sptr#comfunc IXmlNode_AppendChild 22 sptr, sptr#define CLSID_XmlText "{AF75D6AD-E307-4052-8CB1-BF2052E734F0}"#define IID_IXmlText "{F931A4CB-308D-4760-A1D5-43B67450AC7E}"#usecom IXmlText IID_IXmlText CLSID_XmlText#comfunc IXmlText_QueryInterface 0 sptr, sptr// IToastNotificationManager のことらしい#define IID_IToastNotifier "{75927B93-03F3-41EC-91D3-6E5BAC1B38E7}"#define CLSID_ToastNotifier "{6db7cd52-e3b7-4ecc-bb1f-388aeef6bb50}"#usecom IToastNotifier IID_IToastNotifier CLSID_ToastNotifier#comfunc IToastNotifier_Show 6 sptr#comfunc IToastNotifier_Hide 7 sptr#define IID_IToastNotificationFactory "{04124B20-82C6-4229-B109-FD9ED4662B53}"#define CLSID_ToastNotificationFactory "{6db7cd52-e3b7-4ecc-bb1f-388aeef6bb50}"#usecom IToastNotificationFactory IID_IToastNotificationFactory CLSID_ToastNotificationFactory#comfunc IToastNotificationFactory_CreateToastNotification 6 sptr, sptr#define IID_IToastNotification "{997E2675-059E-4E60-8B06-1760917C8B80}"#define CLSID_ToastNotification "{6db7cd52-e3b7-4ecc-bb1f-388aeef6bb50}"#usecom IToastNotification IID_IToastNotification CLSID_ToastNotification#define IID_IXmlNodeSerializer "{5CC5B382-E6DD-4991-ABEF-06D8D2E7BD0C}"#define CLSID_XmlNodeSerializer "{AF75D6AD-E307-4052-8CB1-BF2052E734F0}"#usecom IXmlNodeSerializer IID_IXmlNodeSerializer CLSID_XmlNodeSerializer#comfunc IXmlNodeSerializer_GetXml 6 sptr#comfunc IXmlNodeSerializer_get_InnerText 7 sptr#comfunc IXmlNodeSerializer_put_InnerText 8 sptr#deffunc WinRTAPIInitRoInitialize 1return stat#deffunc WinRTAPIUnInitRoUninitializereturn stat#deffunc CreateToastXml var _pTnms_, int _Template, var _pXml_, \local inputXmlPtr, \local _pTnms, \local hr_pXml = _pXml__pTnms = _pTnms_inputXmlPtr = 0// ToastTemplateType_ToastText01 = 4IToastNotificationManagerStatics_GetTemplateContent _pTnms, _Template/*4*/, varptr(inputXmlPtr) : hr = statif SUCCEEDED(hr){newcom _pXml, IXMLDocument, -1, inputXmlPtrif varuse(_pXml){hr = 0}else{hr = -1}_pXml_ = _pXml}/*querycom pXns, _pXml_, IXmlNodeSerializerhString_test = 0IXmlNodeSerializer_GetXml pXns, varptr(hString_test)dialog strf("0x%08x, %d", stat, stat)dialog HString2Unicode(hString_test)*/return hr#deffunc SetImageSrc str _ImagePath, var _pXml2_if _ImagePath == "" : return 0return#deffunc SetTextValues array Text, var _pXml_, \local num, \local nodeListPtr, \local hString2, \local pNodeList, \local nodeListLength, \local hString3, \local textNodePtr, \local pTextNode, \local pInputText, \local AppendedChildPtr, \local inputTextPtr, \local pTmp, \local hrpNodeList = 0nodeListPtr = 0hString2 = Unicode2HString("text")IXMLDocument_GetElementsByTagName _pXml_, hString2, varptr(nodeListPtr) : hr = statif SUCCEEDED(hr){newcom pNodeList, IXmlNodeList, -1, nodeListPtrif varuse(pNodeList){nodeListLength = 0IXmlNodeList_get_Length pNodeList, varptr(nodeListLength) : hr = statif SUCCEEDED(hr){// 短いほうを選ぶif nodeListLength < length(Text){num = nodeListLength}else{num = length(Text)}repeat limit(num, 1, 3)hString3 = Unicode2HString(Text(cnt));dialog HString2Unicode(hString3)textNodePtr = 0IXmlNodeList_Item pNodeList, cnt, varptr(textNodePtr) : hr = statif SUCCEEDED(hr){newcom pTextNode, IXmlNode, -1, textNodePtrif varuse(pTextNode){inputTextPtr = 0IXMLDocument_CreateTextNode _pXml_, hString3, varptr(inputTextPtr) : hr = statif SUCCEEDED(hr){newcom pInputText, IXmlText, -1, inputTextPtrif varuse(pInputText){AppendedChildPtr = 0// varptrじゃなくてlpeekでcomポインタ取得 → やめたIXmlNode_AppendChild pTextNode, inputTextPtr/*lpeek(pInputText, 0)*/, varptr(AppendedChildPtr) : hr = statif SUCCEEDED(hr){newcom pTmp, IXmlNode, -1, AppendedChildPtr;querycom pXns2, pTmp, IXmlNodeSerializer// innerTextで日本語が挿入できない;hString6 = Unicode2HString("test") // ←これはOK;hString6 = Unicode2HString("testだよ!");IXmlNodeSerializer_put_InnerText pXns2, hString6;dialog strf("0x%08x, %d", stat, stat)// 挿入したのを見てみる;hString_test = 0;IXmlNodeSerializer_get_InnerText pXns2, varptr(hString_test);dialog strf("0x%08x, %d", stat, stat);dialog "Debug:"+HString2Unicode(hString_test)SafeRelease pTmp}}}}}SafeRelease pInputTextSafeRelease pTextNodeDeleteHString hString3loop}}}//SafeRelease pNodeListDeleteHString hString2// みてみる?/*querycom pXns, _pXml_, IXmlNodeSerializerhString_test = 0IXmlNodeSerializer_GetXml pXns, varptr(hString_test)dialog strf("0x%08x, %d,\n %s", stat, stat, HString2Unicode(hString_test))*/return hr#deffunc ShowToast array _Text, str _ImagePath, int Template, str AppUserModelID, \local pTnms, \local hString, \local hString4, \local guid, \local toastStaticsPtr, \local hString_APPsID, \local pXml, \local notifierPtr, \local pNotifier, \local factoryPtr, \local pFactory, \local toastPtr, \local pToast, \local hrpTnms = 0pXml = 0pNotifier = 0pFactory = 0pToast = 0// Unicode文字列からHStringに変換するみたいよhString = Unicode2HString("Windows.UI.Notifications.ToastNotificationManager")hString4 = Unicode2HString("Windows.UI.Notifications.ToastNotification")hString_APPsID = Unicode2HString(AppUserModelID)// IToastNotificationManagerStaticsguid = 0x50ac103f, 0x4598d235, 0xfe98efbb, 0xd43a1a4dtoastStaticsPtr = 0RoGetActivationFactory hString, varptr(guid), varptr(toastStaticsPtr) : hr = stat;dialog HString2Unicode(hString)if hr == 0 && toastStaticsPtr != 0{newcom pTnms, IToastNotificationManagerStatics, -1, toastStaticsPtrCreateToastXml pTnms, Template, pXml : hr = statif SUCCEEDED(hr){SetTextValues _Text, pXml : hr = statif SUCCEEDED(hr){// 未実装SetImageSrc _ImagePath, pXml : hr = statif SUCCEEDED(hr){notifierPtr = 0IToastNotificationManagerStatics_CreateToastNotifierWithId pTnms, hString_APPsID, varptr(notifierPtr) : hr = statif SUCCEEDED(hr){newcom pNotifier, IToastNotifier, -1, notifierPtrif varuse(pNotifier){factoryPtr = 0// IToastNotificationFactoryguid = 0x04124B20, 0x422982C6, 0x9EFD09B1, 0x532B66D4RoGetActivationFactory hString4, varptr(guid), varptr(factoryPtr) : hr = statif hr == 0 && factoryPtr != 0{newcom pFactory, IToastNotificationFactory, -1, factoryPtrif varuse(pFactory){toastPtr = 0IToastNotificationFactory_CreateToastNotification pFactory, lpeek(pXml, 0), varptr(toastPtr) : hr = statif SUCCEEDED(hr){newcom pToast, IToastNotification, -1, toastPtrif varuse(pToast){IToastNotifier_Show pNotifier, toastPtrif SUCCEEDED(hr){}}}}}}}}}}}SafeRelease pToastSafeRelease pFactorySafeRelease pNotifierSafeRelease pXmlSafeRelease pTnmsDeleteHString hString_APPsIDDeleteHString hString4DeleteHString hStringreturn hr#global#enum ToastTemplateType_ToastImageAndText01 = 0#enum ToastTemplateType_ToastImageAndText02#enum ToastTemplateType_ToastImageAndText03#enum ToastTemplateType_ToastImageAndText04#enum ToastTemplateType_ToastText01#enum ToastTemplateType_ToastText02#enum ToastTemplateType_ToastText03#enum ToastTemplateType_ToastText04// Win8 のトースト通知を使用するには、アプリ一覧に// AppUserModelIDを設定したショートカットを配置する必要がある// 初期化するのんWinRTAPIInit// 適当なAppUserModelIDを指定する// CompanyName.ProductName.SubProduct.VersionInformation な形式が良い// http://msdn.microsoft.com/ja-jp/library/windows/apps/dd378459.aspxAppUserModelID = "net.hinekure.hsp.test"// 現在の実行ファイルのパス名sdim exepath, 1024 + 1GetModuleFileNameA 0, varptr(exepath), 1024// ショートカット作成先のパス名(?:\Users\xxx\AppData\Roaming\)lnkpath = dirinfo($1001A) + "\\Microsoft\\Windows\\Start Menu\\Programs\\"+"HSP3Test.lnk"// ショートカット作成(アプリ一覧に)CreateShortcut exepath, "", exepath, 0, AppUserModelID, lnkpathmes stat// 現在のウィンドウに 指定したAppUserModelID を設定するSetAppUserModelID hwnd, AppUserModelIDmes stat// なぜか日本語が使えない(理由がよくわからない)text = "HSP3", "Toast", "Sample!!!"// トースト通知してみる// 第1引数は、表示したい文字列を最大3つまでの配列変数で指定// 3つ使えるのは、// ToastTemplateType_ToastImageAndText04// ToastTemplateType_ToastText04// です。// 第2引数は、画像パスを指定(ただし未実装)// 第3引数は、テンプレートIDを指定// 第4引数は、AppUserModelIDを指定ShowToast text, "", ToastTemplateType_ToastText04, AppUserModelIDmes strf("0x%08x, %d", stat, stat)// 終了時にでも実行WinRTAPIUnInit