COM(イベント)

コネクション ポイントは、COM のクライアントとサーバーの間の双方向通信を確立します。この機構を使用すると、何かのイベントが発生したときに、COM のサーバーからクライアントをコールバックできます。たとえば、サーバー (Microsoft Internet Explorer など) は、イベントを発生させて、タイトルの変更のような変更をクライアント プログラムに報告できます。クライアントは、イベント シンクと呼ばれる内部 COM オブジェクトを作成して、通知の受信に備えます。通知を受信すると、クライアントはそのイベントに関連付けられているアクションを実行できます。

イベント シンクは、イベントに関連付けられているメソッドをサーバーに公開するためのインターフェイスを提供します。サーバーは、それらのイベントに関連付けられているメソッドを呼び出して、イベントを発生させます。クライアントは、イベント シンク インターフェイスを通常の COM インターフェイスとして実装します。サーバーは、そのインターフェイスをアウトゴーイング インターフェイスとして宣言します。つまり、COM サーバーの作成者は、COM サーバーのタイプ ライブラリ内のインターフェイスに source 属性を適用します。サーバーは、イベント シンク インターフェイスの定義を使用して、sink メソッドと invoke メソッドを識別します。

イベント シンク インターフェイスを実装する COM クライアントは、しばしばイベント シンク、または単純にシンクと呼ばれます。次の図では、シンクは、ISinkEvents インターフェイスを実装しています。イベントを発生させるサーバーは、ソースと呼ばれます。

FindConnectionPoint()に渡すIDの設定の仕方

登録してあるCOMのイベント関連の情報を取得しなければならない。
  1. OLE/COM オブジェクト ビューアーを起動
  2. Type Libraryからお目当てのものをダブルクリック(ITypeLib Viewerが開く)
  3. CoClasses->ApplicationEventsをオープン(2とか3とかあって、使いどころが不明…)
  4. 右窓に表示されている"uuid"をソース内で定義する
  5. クライアント側でイベントを区別するには更に先の階層のMethodsからそれっぽいイベントを開く
  6. そこに記述されている"id"を使用する

IID定義例
          (Microsoft Word 11.0 Object Library > CoClasses > ApplicationEvents2 の場合)
OLE/COM オブジェクトビューアーでは、
          uuid(000209FE-0000-0000-C000-000000000046)
と記述されている。

ソースでの記述はと言うと…
          const IID IID_IApplicationEvents2 =
                    {0x000209fe,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46};}
となる。
もしくは
          DEFINE_GUIDE(IID_IApplicationEvents2,
                    0x000209fe,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
でもいいのかもしれない。
あとでちゃんと出力の違いを確認しておこう…。

イベントインターフェースの探し方

サーバーオブジェクトがサポートしているイベントを探す方法として以下のやり方が推奨(?)
  1. サーバーオブジェクトの IDispatch->QueryInterface( IID_IConnectionPointContainer, &p )を使って IConnectionPointContainer を取得
  2. この時点で E_NOINTERFACEが返ってきたらこのオブジェクトはイベントインターフェースをサポートしていないという事
  3. IConnectionPointContainerが取得できたら、今度は EnumConnectionPoints()メソッドを使って IEnumConnectionPointsを取得(この時点で取得できないってことはないハズ)
  4. IEnumConnectionPoints->Next()IConnectionPoint配列を取得。
            ・第1引数 : 配列サイズ(in)
            ・第2引数 : IConnectionPoint配列(out)
            ・第3引数 : 実際に取得できた数(out)
  5. IConnectionPoint配列に対し、GetConnectionInterface()メソッドでIIDを取得する。デバッガでIIDを見ればどのイベントがサポートされるかが分かる。

例えば Microsoft Word の場合、以下の4つのインターフェースが取得できる
  • IID_ApplicationEvents
  • IID_ApplicationEvents2
  • IID_ApplicationEvents3
  • IID_ApplicationEvents4
これは OLE/COM オブジェクト ライブラリーの Type LibrariesMicrosoft Word 11.0 Object Library の ITypeLib Viewer を開き、 CoClassesApplication で 確認することができる。
更に展開した先のメソッドのIDがイベントIDとして登録したシンクオブジェクトのInvokeメソッドに渡されると考えていいのかな?

ちなみに Excel の場合は
  • IID_AppEvents
のみサポートしているので、VBAとかでアクセスできるイベントよりは数が減りそうな雰囲気だ…。
最終更新:2008年09月18日 19:48
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。