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 as sdim ws, strlen(as)*2 + 2 cnvstow ws, as hString = 0 WindowsCreateString varptr(ws), strlen(as), varptr(hString) return hString // 未使用のため #defcfunc Unicode2HStringEx str as, var HSTRING_HEADER sdim ws, strlen(as)*2 + 2 cnvstow ws, as hString = 0 dim HSTRING_HEADER, 6 WindowsCreateStringReference varptr(ws), strlen(as), varptr(HSTRING_HEADER), varptr(hString) return hString #deffunc DeleteHString int _hString WindowsDeleteString _hString return stat #defcfunc GetHStringLength int _hString WindowsGetStringLen _hString return stat #defcfunc HString2Unicode int _hString if _hString == 0 : return "" size = GetHStringLength(_hString) * 2 if size <= 0 : return "" WindowsGetStringRawBuffer _hString, varptr(size) dupptr buf, stat, GetHStringLength(_hString) * 2, 2 return 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 hr hr = 0 pShellLink = 0 pPropStore = 0 newcom pShellLink, IShellLink if varuse(pShellLink) == 0 : return -1 IShellLink_SetPath pShellLink, file_path : hr = stat if SUCCEEDED(hr){ IShellLink_SetArguments pShellLink, arg : hr = stat if SUCCEEDED(hr){ IShellLink_SetIconLocation pShellLink, icon_path, icon_idx : hr = stat if SUCCEEDED(hr){ querycom pPropStore, pShellLink, IPropertyStore if varuse(pPropStore){ // Unicodeに変換 sdim wstring, strlen(AppUserModelID) * 2 + 2 cnvstow wstring, AppUserModelID // 配列なので(今回は1つしかないけど) wstrings = varptr(wstring) // PROPVARIANT 構造体 dim ppropvar, 4 // Unicode文字列→PROPVARIANT に変換 InitPropVariantFromStringVector varptr(wstrings), 1/*今回は1つだけなので*/, varptr(ppropvar) : hr = stat if SUCCEEDED(hr){ PKEY_AppUserModel_ID = 0x9F4C2855, 0x4B399F79, 0xD4E1D0A8, 0xF3D5E12D, 5 IPropertyStore_SetValue pPropStore, varptr(PKEY_AppUserModel_ID), varptr(ppropvar) : hr = stat if SUCCEEDED(hr){ IPropertyStore_Commit pPropStore : hr = stat if SUCCEEDED(hr){ IPersistFile_Save pShellLink, out_path, 1 : hr = stat } } PropVariantClear varptr(ppropvar) } } } } } // SafeRelease SafeRelease pPropStore SafeRelease pShellLink return 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 hr hr = 0 pPropStore = 0 propStorePtr = 0 IID_IPropertyStore_Array = 0x886d8eeb, 0x44468cf2, 0xbacd028d, 0x99cfbd1d PKEY_AppUserModel_ID = 0x9F4C2855, 0x4B399F79, 0xD4E1D0A8, 0xF3D5E12D, 5 SHGetPropertyStoreForWindow _hwnd, varptr(IID_IPropertyStore_Array), varptr(propStorePtr) if stat == 0 && propStorePtr != 0{ newcom pPropStore, IPropertyStore, -1, propStorePtr if varuse(pPropStore){ // Win7 では廃止されているらしい // propsys.dll 7.0 /* mes varptr(InitPropVariantFromString) InitPropVariantFromString "net.hinekure.test.hsp3", varptr(ppropvar) */ // Unicodeに変換 sdim wstring, strlen(AppUserModelID) * 2 + 2 cnvstow wstring, AppUserModelID // 配列なので(今回は1つしかないけど) wstrings = varptr(wstring) // PROPVARIANT 構造体 dim ppropvar, 4 // Unicode文字列→PROPVARIANT に変換 InitPropVariantFromStringVector varptr(wstrings), 1, varptr(ppropvar) : hr = stat if SUCCEEDED(hr){ IPropertyStore_SetValue pPropStore, varptr(PKEY_AppUserModel_ID), varptr(ppropvar) : hr = stat if SUCCEEDED(hr){ IPropertyStore_Commit pPropStore : hr = stat } PropVariantClear varptr(ppropvar) } } } // SafeRelease SafeRelease pPropStore return 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 WinRTAPIInit RoInitialize 1 return stat #deffunc WinRTAPIUnInit RoUninitialize return stat #deffunc CreateToastXml var _pTnms_, int _Template, var _pXml_, \ local inputXmlPtr, \ local _pTnms, \ local hr _pXml = _pXml_ _pTnms = _pTnms_ inputXmlPtr = 0 // ToastTemplateType_ToastText01 = 4 IToastNotificationManagerStatics_GetTemplateContent _pTnms, _Template/*4*/, varptr(inputXmlPtr) : hr = stat if SUCCEEDED(hr){ newcom _pXml, IXMLDocument, -1, inputXmlPtr if varuse(_pXml){ hr = 0 }else{ hr = -1 } _pXml_ = _pXml } /* querycom pXns, _pXml_, IXmlNodeSerializer hString_test = 0 IXmlNodeSerializer_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 0 return #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 hr pNodeList = 0 nodeListPtr = 0 hString2 = Unicode2HString("text") IXMLDocument_GetElementsByTagName _pXml_, hString2, varptr(nodeListPtr) : hr = stat if SUCCEEDED(hr){ newcom pNodeList, IXmlNodeList, -1, nodeListPtr if varuse(pNodeList){ nodeListLength = 0 IXmlNodeList_get_Length pNodeList, varptr(nodeListLength) : hr = stat if 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 = 0 IXmlNodeList_Item pNodeList, cnt, varptr(textNodePtr) : hr = stat if SUCCEEDED(hr){ newcom pTextNode, IXmlNode, -1, textNodePtr if varuse(pTextNode){ inputTextPtr = 0 IXMLDocument_CreateTextNode _pXml_, hString3, varptr(inputTextPtr) : hr = stat if SUCCEEDED(hr){ newcom pInputText, IXmlText, -1, inputTextPtr if varuse(pInputText){ AppendedChildPtr = 0 // varptrじゃなくてlpeekでcomポインタ取得 → やめた IXmlNode_AppendChild pTextNode, inputTextPtr/*lpeek(pInputText, 0)*/, varptr(AppendedChildPtr) : hr = stat if 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 pInputText SafeRelease pTextNode DeleteHString hString3 loop } } } // SafeRelease pNodeList DeleteHString hString2 // みてみる? /* querycom pXns, _pXml_, IXmlNodeSerializer hString_test = 0 IXmlNodeSerializer_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 hr pTnms = 0 pXml = 0 pNotifier = 0 pFactory = 0 pToast = 0 // Unicode文字列からHStringに変換するみたいよ hString = Unicode2HString("Windows.UI.Notifications.ToastNotificationManager") hString4 = Unicode2HString("Windows.UI.Notifications.ToastNotification") hString_APPsID = Unicode2HString(AppUserModelID) // IToastNotificationManagerStatics guid = 0x50ac103f, 0x4598d235, 0xfe98efbb, 0xd43a1a4d toastStaticsPtr = 0 RoGetActivationFactory hString, varptr(guid), varptr(toastStaticsPtr) : hr = stat ;dialog HString2Unicode(hString) if hr == 0 && toastStaticsPtr != 0{ newcom pTnms, IToastNotificationManagerStatics, -1, toastStaticsPtr CreateToastXml pTnms, Template, pXml : hr = stat if SUCCEEDED(hr){ SetTextValues _Text, pXml : hr = stat if SUCCEEDED(hr){ // 未実装 SetImageSrc _ImagePath, pXml : hr = stat if SUCCEEDED(hr){ notifierPtr = 0 IToastNotificationManagerStatics_CreateToastNotifierWithId pTnms, hString_APPsID, varptr(notifierPtr) : hr = stat if SUCCEEDED(hr){ newcom pNotifier, IToastNotifier, -1, notifierPtr if varuse(pNotifier){ factoryPtr = 0 // IToastNotificationFactory guid = 0x04124B20, 0x422982C6, 0x9EFD09B1, 0x532B66D4 RoGetActivationFactory hString4, varptr(guid), varptr(factoryPtr) : hr = stat if hr == 0 && factoryPtr != 0{ newcom pFactory, IToastNotificationFactory, -1, factoryPtr if varuse(pFactory){ toastPtr = 0 IToastNotificationFactory_CreateToastNotification pFactory, lpeek(pXml, 0), varptr(toastPtr) : hr = stat if SUCCEEDED(hr){ newcom pToast, IToastNotification, -1, toastPtr if varuse(pToast){ IToastNotifier_Show pNotifier, toastPtr if SUCCEEDED(hr){ } } } } } } } } } } } SafeRelease pToast SafeRelease pFactory SafeRelease pNotifier SafeRelease pXml SafeRelease pTnms DeleteHString hString_APPsID DeleteHString hString4 DeleteHString hString return 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.aspx AppUserModelID = "net.hinekure.hsp.test" // 現在の実行ファイルのパス名 sdim exepath, 1024 + 1 GetModuleFileNameA 0, varptr(exepath), 1024 // ショートカット作成先のパス名(?:\Users\xxx\AppData\Roaming\) lnkpath = dirinfo($1001A) + "\\Microsoft\\Windows\\Start Menu\\Programs\\"+"HSP3Test.lnk" // ショートカット作成(アプリ一覧に) CreateShortcut exepath, "", exepath, 0, AppUserModelID, lnkpath mes stat // 現在のウィンドウに 指定したAppUserModelID を設定する SetAppUserModelID hwnd, AppUserModelID mes stat // なぜか日本語が使えない(理由がよくわからない) text = "HSP3", "Toast", "Sample!!!" // トースト通知してみる // 第1引数は、表示したい文字列を最大3つまでの配列変数で指定 // 3つ使えるのは、 // ToastTemplateType_ToastImageAndText04 // ToastTemplateType_ToastText04 // です。 // 第2引数は、画像パスを指定(ただし未実装) // 第3引数は、テンプレートIDを指定 // 第4引数は、AppUserModelIDを指定 ShowToast text, "", ToastTemplateType_ToastText04, AppUserModelID mes strf("0x%08x, %d", stat, stat) // 終了時にでも実行 WinRTAPIUnInit