コネクション ポイント

この記事では、MFC の CCmdTarget クラスと CConnectionPoint クラスを使用して、コネクション ポイント (旧称 OLE コネクション ポイント) を実装する方法について説明します。

従来、コンポーネント オブジェクト モデル (COM) には、オブジェクトがインターフイスに機能を実装して公開するための全般的なメカニズム (IUnknown::QueryInterface*) が定義されています。 しかし、対応するメカニズム、つまりオブジェクトが特定のインターフェイスを呼び出す機能を公開するためのメカニズムは定義されていません。 つまり、オブジェクトに対する入力ポインター (そのオブジェクトのインターフェイスへのポインター) の処理方法は COM に定義されていましたが、出力インターフェイス (オブジェクトが他のオブジェクトのインターフェイスに対して保持するポインター) については、明示的なモデルが COM には存在していなかったのです。 この機能をサポートするモデルが、コネクション ポイントという名称で新しく COM に追加されました。

コネクションには、インターフェイスを呼び出す側のオブジェクト (ソース) とインターフェイスを実装する側のオブジェクト (シンク) という 2 つの要素があります。 コネクション ポイントは、ソース側が公開するインターフェイスです。 ソースがコネクション ポイントを公開することで、シンクは、ソースへの接続を確立できるようになります。 ソース オブジェクトには、コネクション ポイントのメカニズム (IConnectionPoint インターフェイス) を介してシンク インターフェイスへのポインターが渡されます。 ソースは、このポインターを通じて、シンクに実装された一連のメンバー関数にアクセスできます。 たとえばシンクに実装されたイベントを発生させたければ、ソースは、シンクに実装されている適切なメソッドを呼び出すことができます。 次の図は、ここで説明したコネクション ポイントを示しています。

Diagram showing an implemented connection point.
コネクション ポイントの実装

MFC には、このモデルが CConnectionPoint クラスと CCmdTarget クラスに実装されています。 CConnectionPoint から派生したクラスには、他のオブジェクトにコネクション ポイントを公開するための IConnectionPoint インターフェイスが実装されています。 CCmdTarget から派生したクラスには、IConnectionPointContainer インターフェイスが実装されていて、オブジェクトが提供しているすべてのコネクション ポイントを列挙したり、特定のコネクション ポイントを見つけたりすることができます。

クラスに実装した各コネクション ポイントについて、コネクション ポイントを実装する接続部分を宣言する必要があります。 コネクション ポイントを 1 つでも実装した場合は、コネクション マップを 1 つクラス内で宣言する必要があります。 コネクション マップは、ActiveX コントロールでサポートされるコネクション ポイントの表です。

次の例は、単純なコネクション マップと 1 つのコネクション ポイントを示しています。 1 つ目の例では、コネクション マップとコネクション ポイントを宣言し、2 つ目の例では、そのマップとポイントを実装しています。 CMyClass は、CCmdTarget の派生クラスでなければならないことに注意してください。 1 つ目の例では、クラス宣言の protected セクションにコードが挿入されています。

class CMyClass : public CCmdTarget
{
protected:
   // Connection point for ISample interface
   BEGIN_CONNECTION_PART(CMyClass, SampleConnPt)
      CONNECTION_IID(IID_ISampleSink)
   END_CONNECTION_PART(SampleConnPt)

   DECLARE_CONNECTION_MAP()

BEGIN_CONNECTION_PART マクロと END_CONNECTION_PART マクロで、この特定のコネクション ポイントを実装する埋め込みクラス XSampleConnPt (CConnectionPoint から派生) が宣言されています。 CConnectionPoint のいずれかのメンバー関数をオーバーライドしたり、独自のメンバー関数を追加したりする必要がある場合は、この 2 つのマクロの間にそれらを宣言します。 たとえば、この 2 つのマクロの間に記述した CONNECTION_IID マクロは、CConnectionPoint::GetIID メンバー関数をオーバーライドします。

2 つ目の例では、コントロールの実装ファイル (.cpp ファイル) にコードが挿入されています。 このコードは、SampleConnPt というコネクション ポイントを含んだコネクション マップを実装しています。

BEGIN_CONNECTION_MAP(CMyClass, CCmdTarget)
    CONNECTION_PART(CMyClass, IID_ISampleSink, SampleConnPt)
END_CONNECTION_MAP()

複数のコネクション ポイントがクラスに存在する場合は、BEGIN_CONNECTION_MAP マクロと END_CONNECTION_MAP マクロの間に追加する形で CONNECTION_PART マクロを挿入します。

最後に、クラスのコンストラクターに EnableConnections の呼び出しを追加します。 次に例を示します。

CMyClass::CMyClass()
{
   EnableConnections();
}

このコードを挿入すると、CCmdTarget から派生したクラスが、ISampleSink インターフェイス用のコネクション ポイントを公開するようになります。 この例を次の図に示します。

Diagram showing a Connection point implemented by using MFC.
MFC で実装されたコネクション ポイント

通常、コネクション ポイントは "マルチキャスト"、つまり同じインターフェイスに接続された複数のシンクに対してブロードキャストする機能をサポートします。 次のコード フラグメントは、コネクション ポイント上の各シンクを反復処理することによってマルチキャストを実行する例です。

void CMyClass::CallSinkFunc()
{
   POSITION pos = m_xSampleConnPt.GetStartPosition();
   ISampleSink* pSampleSink;
   while (pos != NULL)
   {
      pSampleSink = (ISampleSink*)(m_xSampleConnPt.GetNextConnection(pos));
      if (pSampleSink != NULL)
         pSampleSink->SinkFunc();
   }
}

この例では、CConnectionPoint::GetConnections を呼び出して、SampleConnPt コネクション ポイントから最新の接続のセットを取得します。 次に、それらの接続を反復処理しながら、アクティブな各接続の ISampleSink::SinkFunc を呼び出しています。

関連項目

MFC COM