コネクション ポイント
この記事では、MFC の CCmdTarget
クラスと CConnectionPoint
クラスを使用して、コネクション ポイント (旧称 OLE コネクション ポイント) を実装する方法について説明します。
従来、コンポーネント オブジェクト モデル (COM) には、オブジェクトがインターフイスに機能を実装して公開するための全般的なメカニズム (IUnknown::QueryInterface
*) が定義されています。 しかし、対応するメカニズム、つまりオブジェクトが特定のインターフェイスを呼び出す機能を公開するためのメカニズムは定義されていません。 つまり、オブジェクトに対する入力ポインター (そのオブジェクトのインターフェイスへのポインター) の処理方法は COM に定義されていましたが、出力インターフェイス (オブジェクトが他のオブジェクトのインターフェイスに対して保持するポインター) については、明示的なモデルが COM には存在していなかったのです。 この機能をサポートするモデルが、コネクション ポイントという名称で新しく COM に追加されました。
コネクションには、インターフェイスを呼び出す側のオブジェクト (ソース) とインターフェイスを実装する側のオブジェクト (シンク) という 2 つの要素があります。 コネクション ポイントは、ソース側が公開するインターフェイスです。 ソースがコネクション ポイントを公開することで、シンクは、ソースへの接続を確立できるようになります。 ソース オブジェクトには、コネクション ポイントのメカニズム (IConnectionPoint
インターフェイス) を介してシンク インターフェイスへのポインターが渡されます。 ソースは、このポインターを通じて、シンクに実装された一連のメンバー関数にアクセスできます。 たとえばシンクに実装されたイベントを発生させたければ、ソースは、シンクに実装されている適切なメソッドを呼び出すことができます。 次の図は、ここで説明したコネクション ポイントを示しています。
コネクション ポイントの実装
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
インターフェイス用のコネクション ポイントを公開するようになります。 この例を次の図に示します。
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
を呼び出しています。