MFC를 이용한 COM Connection Point 구현
커넥션은 아래 두 부분으로 구성되어 있다.
소스 (Source)
인터페이스를 호출하는 객체
싱크 (Sink)
인터페이스를 구현하는 객체
커넥션 포인트는 소스에 의해 노출되는 인터페이스이다. 커넥션 포인트 매커니즘(IConnectionPoint 인터페이스)을 통해서, 싱크 인터페이스 포인터가 소스 객체에 전달된다. 이 싱크 인터페이스 포인터를 이용하여 싱크 객체의 멤버 함수를 호출할 수 있다.
MFC 는 CConnectionPoint 와 CCmdTarget 클래스 내에 이 모델을 구현하였다. 다른 객체에 커넥션 포인트를 노출하기 위해 CConnectionPoint 를 상속한 클래스가 IConnectionPoint 인터페이스를 구현한다. CCmdTarget을 상속한 클래스는 IConnectionPointContainer를 구현하고, 그리고 이 클래스는 모든 이용 가능한 커넥션 포인터를 열거하거나 특정 커넥션 포인트를 찾을 수 있다.
각각의 커넥션 포인트마다 커넥션 포인트를 구현하는 connection part를 선언해야 한다. 하나 이상의 커넥션 포인트를 구현한다면, 클래스 내에 single connection map 을 선언해야 한다. Connection Map은 ActiveX 컨트롤에 의해 지원되는 커넥션 포인트 테이블이다.
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 매크로는 내장 클래스(embedded class) XSampleConnPt (ConnectionPoint를 상속한)를 선언한다. CConnectinPoint 멤버함수를 재정의 하거나 멤버 함수를 추가하길 원한다면, 이 매크로 사이에 선언하면 된다. 예를 들면, CONNECTION_IID 매크로는 위 매크로 사이에 선언될 때 CConnectionPoint::GetIID 멤버함수를 재정의한다.
두번째 예제에서는, 구현 파일에 코드가 추가된다. 이 코드는 connection map을 구현한다.
BEGIN_CONNECTION_MAP(CMyClass, CMyBaseClass) CONNECTION_PART(CMyClass, IID_ISampleSink, SampleConnPt) END_CONNECTION_MAP() |
하나 이상의 커넥션 포인트를 가지고 있다면, BEGIN_CONNECTION_MAP 과 END_CONNECTION_MAP 매크로 사이에 CONNECTION_PART 매크로를 추가하면 된다.
마지막으로, 클래스의 생성자에 EnableConnection 을 호출하는 코드를 추가한다.
CMyClass::CMyClass() { EnableConnections(); ... } |
Dl 코드가 추가되면, CCmdTarget을 상속한 클래스는 ISampleSink 인터페이스에 대한 커넥션 포인트를 노출시킨다.
보통, 커넥션 포인트는 “multicasting” 을 지원한다 – 동일한 인터페이스에 연결된 다수의 싱크에게 브로드캐스팅. 아래 예는 한 커넥션 포인트에 대한 각각의 싱크를 반복하면 멀티캐스트하는 방법을 보여준다.
void CMyClass::CallSinkFunc() { const CPtrArray* pConnections = m_xSampleConnPt.GetConnections(); ASSERT(pConnections != NULL); int cConnections = pConnections->GetSize(); ISampleSink* pSampleSink; for (int i = 0; i < cConnections; i++) { pSampleSink = (ISampleSink*)(pConnections->GetAt(i)); if(pSampleSink != NULL) pSampleSink->SinkFunc(); } } |
이 예제는 CConnectionPoint::GetConnections 를 호출하여 SampleConnPtr 커넥션 포인트에 대한 현재 커넥션들을 가져온다. 그러고 나서 커넥션을 탐색하면서 모든 커넥션에 대해 ISampleSink::SinkFunc 를 호출한다.
추가 (2009-06-08) : 연결 지점 (Connection point) 이 제대로 동작하려면 소스 파일의 BEGIN_INTERFACE_MAP 에 IID_IConnectionPointContainer 를 선언해 주어야 한다.
BEGIN_INTERFACE_MAP(CMyClass, CDocument) INTERFACE_PART(CMyClass, IID_ITestExeuction, Dispatch) INTERFACE_PART(CMyClass, IID_IConnectionPointContainer,
ConnPtContainer) END_INTERFACE_MAP() |
관련글 : http://codemuri.tistory.com/entry/%EB%B2%88%EC%97%AD-ActiveX-script-hosting
From : MSDN (ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vclib/html/bc9fd7c7-8df6-4752-ac8c-0b177442c88d.htm)