COMのネイティブインターフェースメソッドをインデックスで呼び出します。
Result := ComCall(Index, ComObj , Type1, Arg1, Type2, Arg2, ReturnType)
型:整数
仮想関数テーブル内のメソッドのゼロベースインデックス。
インデックスは、元のインターフェース定義内でのメソッドの位置に対応します。マイクロソフトのドキュメントでは、通常、メソッドをアルファベット順に記載していますが、これは関係ありません。正しいインデックスを決定するために、元のインターフェイスの定義を見つけてください。これは、ヘッダーファイルやタイプライブラリの中にあるかもしれません。
親インターフェースから継承されるメソッドを考慮することが重要です。すべてのCOMインタフェースは最終的にIUnknownから派生するため、最初の3つのメソッドは常にQueryInterface(0)、AddRef(1)、Release(2)です。例えば、IShellItem2は IShellItemの拡張で、インデックス3から始まり、5つのメソッドを含むので、IShellItem2の最初のメソッド(GetPropertyStore)はインデックス8にあります。
ヒント:Microsoftによって定義されたCOMインターフェースについては、インターネットまたはWindows SDKで「IInterfaceNameVtbl」-例えば「IUnknownVtbl」を検索してみてください。Microsoft独自のインターフェース定義には、インターフェースの仮想関数テーブルのこのプレーンC定義が付属しており、すべてのメソッドを正しい順序で明示的にリストアップしています。
無効なインデックスを渡すと、プログラムの終了を含む未定義の動作が発生する可能性があります(ただし、これに限定されるものではありません)。
対象となる COM オブジェクト、すなわち COM インタフェースポインタ。ポインタ値は直接渡すか、バリアントタイプVT_UNKNOWNを持つComValueなど、Ptr
プロパティを持つオブジェクト内にカプセル化することができます。
インターフェースポインタは、インターフェースメソッドを実装する仮想関数のアドレスを特定するために使用され、パラメータとしても渡されます。このパラメータは、一般にインターフェースをネイティブにサポートする言語では明示的に存在しないが、Cスタイルの「Vtbl」定義では表示されます。
無効なポインタを渡すと、プログラムの終了を含む未定義の動作を引き起こす可能性があります(ただし、これに限定されるものではありません)。
型:文字列
これらのペアはそれぞれ、メソッドに渡される1つのパラメータを表しています。組数は無制限です。タイプについては、DllCallタイプ表をご覧ください。引数の場合、メソッドに渡す値を指定します。
型:文字列
省略された場合、戻り値の型はデフォルトでHRESULTとなり、これはCOMインターフェイスのメソッドの最も一般的な戻り値の型です。失敗を示す結果は、OSErrorが投げられる。したがって、実際の戻り値の型が HRESULT である場合を除き、戻り値の型を省略してはならない。
メソッドが値を返さない型(Cではvoid
戻り値型)の場合、"Int "または接尾辞のない他の数値型(HRESULTを除く)を指定し、戻り値を無視します。このような場合、戻り値レジスタの内容は任意であるため、ReturnTypeを省略した場合は例外が発生する可能性がある。
それ以外の場合は、DllCall タイプテーブルから引数タイプのいずれかを指定します。接尾辞のアスタリスクにも対応しています。
ComCallはDllCallと同様にCdeclキーワードをサポートしていますが、一般的にCOMインターフェースメソッドでは使用されません。
ReturnTypeがHRESULT(または省略)で、メソッドがエラー値を返した場合(FAILED マクロで定義)、OSErrorがスローされます。
そうでない場合、ComCallは、メソッドによって返された実際の値を返します。メソッドが値を返さない型(Cで定義された戻り値の型がvoid
)の場合、結果は未定義であり、無視されるべきです。
以下のDllCallのトピックは、ComCallにも適用されます:
ComObject、ComObjQuery、ComValue、Bufferオブジェクト、CallbackCreate
アクティブなウィンドウを3秒間、タスクバーから削除します。同等のDllCallの例と比較してみてください。
/* ITaskbarListのVTableにあるメソッドです: IUnknown: 0 QueryInterface -- ComObjQueryの代わりに使用 1 AddRef -- ObjAddRefの代わりに使用 2 Release -- ObjReleaseの代わりに使用 ITaskbarList: 3 HrInit 4 AddTab 5 DeleteTab 6 ActivateTab 7 SetActiveAlt */ IID_ITaskbarList := "{56FDF342-FD6D-11d0-958A-006097C9A090}" CLSID_TaskbarList := "{56FDF344-FD6D-11d0-958A-006097C9A090}" ; TaskbarListオブジェクトを作成します。 tbl := ComObject(CLSID_TaskbarList, IID_ITaskbarList) activeHwnd := WinExist("A") ComCall(3, tbl) ; tbl.HrInit() ComCall(5, tbl, "ptr", activeHwnd) ; tbl.DeleteTab(activeHwnd) Sleep 3000 ComCall(4, tbl, "ptr", activeHwnd) ; tbl.AddTab(activeHwnd) ; When finished with the object, simply replace any references with ; some other value (or if its a local variable, just return): tbl := ""
COMインタフェースをラッピングするいくつかのテクニックを実証します。前例に準ずる。
tbl := TaskbarList() activeHwnd := WinExist("A") tbl.DeleteTab(activeHwnd) Sleep 3000 tbl.AddTab(activeHwnd) tbl := "" class TaskbarList { static IID := "{56FDF342-FD6D-11d0-958A-006097C9A090}" static CLSID := "{56FDF344-FD6D-11d0-958A-006097C9A090}" ; クラスを初期化するために起動時に呼び出されます。 static __new() { ; TaskbarList のすべてのインスタンスのベースオブジェクトを取得します。 proto := this.Prototype ; Bound関数でパラメータを事前に定義することができます。 ; ラッパー関数を必要とせず、より使いやすいメソッドを提供します。 ; HrInit自身はパラメータを持たないので、インデックスだけをバインドします。 ; であり、呼び出し側は暗黙のうちに 'this' を提供することになる。 proto.HrInit := ComCall.Bind(3) ; パラメータを空白にすることで、呼び出し側が値を指定できるようにします。 ; この場合、空白のパラメータは'this'(通常は非表示)です。 proto.AddTab := ComCall.Bind(4,, "ptr") ; オブジェクトやMapを使用することで、繰り返しを減らすことができます。 for name, args in Map( "DeleteTab", [5,,"ptr"], "ActivateTab", [6,,"ptr"], "SetActiveAlt", [7,,"ptr"]) { proto.%name% := ComCall.Bind(args*) } } ; 新しいインスタンスに対して TaskbarList() によって呼び出されます。 __new() { this.comobj := ComObject(TaskbarList.CLSID, TaskbarList.IID) this.ptr := this.comobj.ptr ; ITaskbarList を介してリクエストを初期化します。 this.HrInit() } }