【HSP3】HSPでWindows8のトースト通知(WinRTAPI使用)をしてみるサンプル(日本語対応版)

fork元:http://codetter.com/?p=1041
日本語通知できるようにしました
cnvstowを使用せず、MultiByteToWideCharでUnicode変換するようにしています

fork元:http://codetter.com/?p=1041
日本語通知できるようにしました
cnvstowを使用せず、MultiByteToWideCharでUnicode変換するようにしています

  • タグ:
  • タグはありません
#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
//*/
	_as=as
	ws=""
	MultiByteToWideChar 0x00,0,varptr(_as),strlen(_as),varptr(ws),0:len=stat
	sdim ws,len*2
	MultiByteToWideChar 0x00,0,varptr(_as),strlen(_as),varptr(ws),len
	hString = 0
	WindowsCreateString varptr(ws), len, 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 = "日本語の", "通知", "試験!!!!"

	// トースト通知してみる

	// 第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