HSPでCOMインタフェース実装の実験ということで…
IEコンポに独自の右クリックメニューを追加してみる。
実行には、hscallbk.dll が必要です。
http://chokuto.ifdef.jp/download/#hscallbk
#include "hscallbk.as"
// HSPで管理されないメモリを作成するモジュール
#module modMemory
#uselib "msvcrt"
#cfunc calloc "calloc" int, int
#func free "free" int
// 【メモリの確保】
// 引数:確保メモリサイズ, HSPの変数の型, HSPの変数
// 戻り値:確保領域の先頭アドレス
#defcfunc CreateMemory int memSize, int memType, var memVar
if memSize < 0 : return 0
ptr = calloc(memSize + 4, 1)
if 0 == ptr : return 0
dupptr ptrSize, ptr, 4, vartype("int")
ptrSize = memSize
dupptr memVar, ptr + 4, memSize, memType
return ptr + 4
// 【確保メモリのサイズ取得】
// 引数:CreateMemoryの戻り値
// 戻り値:確保メモリサイズ
#defcfunc GetMemorySize int memPtr
if 0 == memPtr : return 0
dupptr ptrSize, memPtr - 4, 4, vartype("int")
return ptrSize
// 【確保メモリの解放】
// 引数:CreateMemoryの戻り値
#deffunc DestoryMemory int memPtr
if 0 == memPtr : return 0
free memPtr - 4
return 1
#global
#module modCOMSupport
#uselib "msvcrt"
#cfunc memcmp "memcmp" int, int, int
#uselib "rpcrt4"
#func UuidFromStringA "UuidFromStringA" str, var
#func UuidToStringA "UuidToStringA" int, var
#func RpcStringFreeA "RpcStringFreeA" int
// GUID文字列からバイナリ形式に変換
// "{bd3f23c0-d43e-11cf-893b-00aa00bdce1a}"
#deffunc GetGUID str s, var ret
_s = s
_s = strtrim(_s, 1, '{')
_s = strtrim(_s, 2, '}')
UuidFromStringA _s, ret
return
#defcfunc IsEqualIID_Ptr int pBuf1, int pBuf2
ret = memcmp(pBuf1, pBuf2, 16) ^ -1
return ret
#defcfunc IsEqualIID str pBuf, int pBuf2
dim buf, 4
GetGUID pBuf, buf
ret = IsEqualIID_Ptr(varptr(buf), pBuf2)
return ret
#defcfunc GetGUIDString int guidPtr
guidStrPtr = 0
UuidToStringA guidPtr, guidStrPtr
dupptr s_tmp, guidStrPtr, 64, 2
s = s_tmp
RpcStringFreeA guidStrPtr
return s
#global
#uselib ""
// IUnknown
#define IID_IUnknown "{00000000-0000-0000-C000-000000000046}"
#func QueryInterfaceProc "" int, int, int
#func AddRefProc "" int
#func ReleaseProc "" int
// IDocHostUIHandler
#define IID_IDocHostUIHandler "{bd3f23c0-d43e-11cf-893b-00aa00bdce1a}"
#func ShowContextMenuProc "" int, int, int, int, int
#func GetHostInfoProc "" int, int
#func ShowUIProc "" int, int, int, int, int, int
#func HideUIProc "" int
#func UpdateUIProc "" int
#func EnableModelessProc "" int, int
#func OnDocWindowActivateProc "" int, int
#func OnFrameWindowActivateProc "" int, int
#func ResizeBorderProc "" int, int, int, int
#func TranslateAcceleratorProc "" int, int, int, int
#func GetOptionKeyPathProc "" int, int, int
#func GetDropTargetProc "" int, int, int
#func GetExternalProc "" int, int
#func TranslateUrlProc "" int, int, int, int
#func FilterDataObjectProc "" int, int, int
#define E_INVALIDARG 0x80070057
#define E_NOINTERFACE 0x80004002
#define S_OK 0x00000000
#define E_NOTIMPL 0x80004001
#define S_FALSE 0x00000001
#define CONTEXT_MENU_DEFAULT 0x0
#define CONTEXT_MENU_IMAGE 0x1)
#define CONTEXT_MENU_CONTROL 0x2
#define CONTEXT_MENU_TABLE 0x3
#define CONTEXT_MENU_TEXTSELECT 0x4
#define CONTEXT_MENU_ANCHOR 0x5
#define CONTEXT_MENU_UNKNOWN 0x6
#define CONTEXT_MENU_VSCROLL 0x9
#define CONTEXT_MENU_HSCROLL 0x10
#define CONTEXT_MENU_MEDIA 0x11
#define IID_ICustomDoc "{3050F3F0-98B5-11CF-BB82-00AA00BDCE0B}"
#usecom ICustomDoc IID_ICustomDoc
#comfunc ICustomDoc_SetUIHandler 3 int
#define IID_IOleClientSite "{00000118-0000-0000-C000-000000000046}"
#usecom IOleClientSite IID_IOleClientSite
#comfunc IOleClientSite_GetClientSite 4 var
#define DIID_DWebBrowserEvents2 "{34A715A0-6587-11D0-924A-0020AFC7AC4D}"
#define DISPID_DOCUMENTCOMPLETE 259
#uselib "kernel32"
#func InterlockedIncrement "InterlockedIncrement" int
#func InterlockedDecrement "InterlockedDecrement" int
#uselib "user32"
#func CreatePopupMenu "CreatePopupMenu"
#func AppendMenu "AppendMenuA" int, int, int, str
#func DestroyMenu "DestroyMenu" int
#func TrackPopupMenu "TrackPopupMenu" int, int, int, int, int, int, int
; メニュー項目ID
#enum IDM_ITEM1 = 1
#enum IDM_ITEM2
#enum IDM_ITEM3
#enum IDM_ITEM4
axobj pIeObj, "Shell.Explorer.2", 640, 480
ieObjID = stat
ieObjHWND = objinfo(ieObjID, 2)
comevent pIeEvent, pIeObj, DIID_DWebBrowserEvents2, *LB_IE_Events
// コールバック関数実装
// IUnknown
setcallbk QueryInterface, QueryInterfaceProc, *LB_QueryInterface
setcallbk AddRef, AddRefProc, *LB_AddRef
setcallbk Release, ReleaseProc, *LB_Release
// IDocHostUIHandler
setcallbk ShowContextMenu, ShowContextMenuProc, *LB_ShowContextMenu
setcallbk GetHostInfo, GetHostInfoProc, *LB_GetHostInfo
setcallbk ShowUI, ShowUIProc, *LB_ShowUI
setcallbk HideUI, HideUIProc, *LB_HideUI
setcallbk UpdateUI, UpdateUIProc, *LB_UpdateUI
setcallbk EnableModeless, EnableModelessProc, *LB_EnableModeless
setcallbk OnDocWindowActivate, OnDocWindowActivateProc, *LB_OnDocWindowActivate
setcallbk OnFrameWindowActivate, OnFrameWindowActivateProc, *LB_OnFrameWindowActivate
setcallbk ResizeBorder, ResizeBorderProc, *LB_ResizeBorder
setcallbk TranslateAccelerator, TranslateAcceleratorProc, *LB_TranslateAccelerator
setcallbk GetOptionKeyPath, GetOptionKeyPathProc, *LB_GetOptionKeyPath
setcallbk GetDropTarget, GetDropTargetProc, *LB_GetDropTarget
setcallbk GetExternal, GetExternalProc, *LB_GetExternal
setcallbk TranslateUrl, TranslateUrlProc, *LB_TranslateUrl
setcallbk FilterDataObject, FilterDataObjectProc, *LB_FilterDataObject
// COMのvtableの実装【開始】
IDocHostUIHandlerVtablePtr = CreateMemory(4 * 18, vartype("int"), IDocHostUIHandlerVtable)
// IUnknown
IDocHostUIHandlerVtable.0 = varptr(QueryInterface)
IDocHostUIHandlerVtable.1 = varptr(AddRef)
IDocHostUIHandlerVtable.2 = varptr(Release)
// IDocHostUIHandler
IDocHostUIHandlerVtable.3 = varptr(ShowContextMenu)
IDocHostUIHandlerVtable.4 = varptr(GetHostInfo)
IDocHostUIHandlerVtable.5 = varptr(ShowUI)
IDocHostUIHandlerVtable.6 = varptr(HideUI)
IDocHostUIHandlerVtable.7 = varptr(UpdateUI)
IDocHostUIHandlerVtable.8 = varptr(EnableModeless)
IDocHostUIHandlerVtable.9 = varptr(OnDocWindowActivate)
IDocHostUIHandlerVtable.10 = varptr(OnFrameWindowActivate)
IDocHostUIHandlerVtable.11 = varptr(ResizeBorder)
IDocHostUIHandlerVtable.12 = varptr(TranslateAccelerator)
IDocHostUIHandlerVtable.13 = varptr(GetOptionKeyPath)
IDocHostUIHandlerVtable.14 = varptr(GetDropTarget)
IDocHostUIHandlerVtable.15 = varptr(GetExternal)
IDocHostUIHandlerVtable.16 = varptr(TranslateUrl)
IDocHostUIHandlerVtable.17 = varptr(FilterDataObject)
IDocHostUIHandlerPtr = CreateMemory(4 * 2, vartype("int"), IDocHostUIHandler)
IDocHostUIHandler.0 = IDocHostUIHandlerVtablePtr // Vtable
IDocHostUIHandler.1 = 0 // 参照カウンタ
// COMのvtableの実装【終了】
// メニューの実装【開始】
// http://lhsp.s206.xrea.com/hsp_menu.html#2
; <サブのポップアップメニュー>
; サブメニューを作成し、ハンドルを取得
CreatePopupMenu
hMenu.0 = stat
; 第3パラはメニュー項目ID
AppendMenu hMenu.0, 0, IDM_ITEM3, "サブメニュー項目 3"
AppendMenu hMenu.0, 0, IDM_ITEM4, "サブメニュー項目 4"
; <メインのポップアップメニュー>
; メインのポップアップメニューを作成し、ハンドルを取得
CreatePopupMenu
hMenu.1 = stat
AppendMenu hMenu.1, 0, IDM_ITEM1, "メニュー項目 1"
; 第2パラを$800にするとセパレータ(区切り線)になる。
AppendMenu hMenu.1, $800, 0, ""
AppendMenu hMenu.1, 0, IDM_ITEM2, "メニュー項目 2"
; 第2パラメータを$10にするとサブメニューへ。
; 第3パラにサブメニューのハンドルを入れる。
AppendMenu hMenu.1, $10, hMenu.0, "サブメニュー"
// メニューの実装【終了】
pIeObj->"Navigate" "http://hsp.tv/play/pforum.php"
onexit gosub *exit
stop
*exit
DestroyMenu hMenu.1
end
return
*LB_IE_Events
switch comevdisp(pIeEvent)
case DISPID_DOCUMENTCOMPLETE
gosub *OnDocumentComplete
swbreak
default
swbreak
swend
return
*OnDocumentComplete
pIeDoc = pIeObj("document")
querycom pICustomDoc, pIeDoc, ICustomDoc
ICustomDoc_SetUIHandler pICustomDoc, IDocHostUIHandlerPtr
delcom pICustomDoc
delcom pIeDoc
return
// ↓ IDocHostUIHandlerインターフェースの実装【開始】
*LB_ShowContextMenu
dwID = callbkarg(1)
// 右クリックされたときの種類を判断するには、dwIDを使います。
// https://technet.microsoft.com/ja-jp/library/aa753264
//
// if CONTEXT_MENU_DEFAULT == dwID : ・・・
TrackPopupMenu hMenu.1, $100, ginfo(0), ginfo(1), 0, hwnd, 0
if stat == 0 : return S_OK
if IDM_ITEM1 == stat || IDM_ITEM2 == stat || IDM_ITEM3 == stat || IDM_ITEM4 == stat {
dialog "追加したものだー"
}
// S_FALSE を返すと、標準のメニューが出ます。
return S_OK
*LB_QueryInterface
This = callbkarg(0)
riid = callbkarg(1)
pvObj = callbkarg(2)
if 0 == pvObj : return E_INVALIDARG
dupptr ppvObj, pvObj, 4, vartype("int")
// 初期化
ppvObj = 0
// IIDのチェック(サポートしているもののみ)
if(IsEqualIID(IID_IUnknown, riid)){
ppvObj = This
}else : if(IsEqualIID(IID_IDocHostUIHandler, riid)){
ppvObj = This
}else{
return E_NOINTERFACE
}
// 参照カウンタを加算
dupptr ptrVtable, This, 4, vartype("int")
// VtableのAddRefまでで良いので、8を指定
dupptr ptrAddRef, ptrVtable, 8, vartype("int")
// AddRef()を実行
prms.0 = This
ret = callfunc(prms, ptrAddRef(1), 1)
return S_OK
*LB_AddRef
This = callbkarg(0)
// 参照カウンタをインクリメント
InterlockedIncrement This + 4
return stat
*LB_Release
This = callbkarg(0)
// 参照カウンタをデクリメント
InterlockedDecrement This + 4
ret = stat
if 0 == ret {
// 参照カウンタが0になった場合は、破棄します
DestoryMemory This
}
return ret
// 今回は使用しないので実装しない。
*LB_GetHostInfo
return S_FALSE
*LB_ShowUI
return S_FALSE
*LB_HideUI
return S_FALSE
*LB_UpdateUI
return S_FALSE
*LB_EnableModeless
return S_FALSE
*LB_OnDocWindowActivate
return S_FALSE
*LB_OnFrameWindowActivate
return S_FALSE
*LB_ResizeBorder
return S_FALSE
*LB_TranslateAccelerator
return E_NOTIMPL
*LB_GetOptionKeyPath
return S_FALSE
*LB_GetDropTarget
return S_FALSE
*LB_GetExternal
return E_NOTIMPL
*LB_TranslateUrl
return S_FALSE
*LB_FilterDataObject
return S_FALSE
// ↑ IDocHostUIHandlerインターフェースの実装【終了】