【HSP3】HSPでWindows8のトースト通知(WinRTAPI使用)をしてみるサンプル(なぜか日本語が使えない)

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.の手順がないと、トースト通知されません。

  • hk1v
  • 2013/12/8 23:37
  • タグ:
  • タグはありません
#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