TN038: OLE MFC/IUnknown 구현
[!참고]
온라인 설명서의을 처음 포함 되었습니다 때문 다음 기술 참고 업데이트 되지 않았습니다.따라서 일부 절차 및 항목 오래 되었거나 잘못 된 수 있습니다.최신 정보는 온라인 설명서 색인에서 관심 있는 주제에 대해 검색 하는 것이 좋습니다.
OLE 2의 핵심은 "OLE 구성 요소 개체 모델", 또는 COM입니다.COM 표준 정의 협동 방법 개체에 대 한 서로 통신 합니다.여기에 어떤 "object" 메서드 개체에서 발송 방법을 비롯 하 여 형태를 자세히.또한 COM 모든 COM 호환 클래스에서 파생 되는 기본 클래스를 정의 합니다.이 기본 클래스는 IUnknown.하지만 IUnknown 인터페이스 라고 하는 C++ 클래스로, COM에는 하나의 언어에만 수 없습니다-C, 파스칼, 또는 COM 개체의 이진 레이아웃이 지원할 수 있는 언어로 구현할 수 있습니다.
OLE에서 파생 된 모든 클래스를 말합니다 IUnknown 로 "인터페이스"입니다. 이 중요 한 차이점은 "이후" 같은 인터페이스인 IUnknown 함께 구현이 전달 되.단순히 여 개체의 통신, 이러한 구현을 수행할 않는 구체적인 프로토콜을 정의 합니다.이것은 최대의 유연성을 제공 하는 시스템에 대 한 적절 한입니다.이 MFC/C++ 프로그램에 대 한 기본 동작을 구현 하는 MFC의 작업입니다.
MFC의 구현을 이해할 수 IUnknown 이란이 인터페이스를 먼저 이해 해야 합니다.단순화 된 버전의 IUnknown 아래에 정의 됩니다.
class IUnknown
{
public:
virtual HRESULT QueryInterface(REFIID iid, void** ppvObj) = 0;
virtual ULONG AddRef() = 0;
virtual ULONG Release() = 0;
};
[!참고]
일부 필요한 호출 규칙 세부 사항, 같은 __stdcall 이 그림에 그대로 남아 있습니다.
AddRef 및 릴리스 멤버 함수는 개체의 메모리 관리를 제어 합니다.COM 참조 카운팅 구성표를 사용 하 여 개체를 추적 합니다.개체는 참조 되지 않는 C++에서와 마찬가지로 직접.대신, COM 개체는 항상 포인터를 통해 참조 됩니다.소유자가 완료 되 면 해당 개체를 해제 합니다 개체의 사용 릴리스 (대조적으로 기존 C++ 개체에 대해 실행 하는 delete 연산자 사용) 멤버를 호출할.참조 카운팅 메커니즘은 단일 개체에 대 한 여러 참조를 관리할 수 있습니다.구현 하는 AddRef 및 릴리스 개체의 참조 횟수를 유지-참조 계수가 0에 도달할 때까지 개체는 삭제 되지 않습니다.
AddRef및 릴리스 는 구현 관점에서 보면 매우 간단 합니다.Trivial 구현 다음과 같습니다.
ULONG CMyObj::AddRef()
{
return ++m_dwRef;
}
ULONG CMyObj::Release()
{
if (--m_dwRef == 0)
{
delete this;
return 0;
}
return m_dwRef;
}
QueryInterface 멤버 함수는 조금 더 흥미로운입니다.가진 유일한 멤버 함수 개체에는 매우 흥미로운 수 없습니다 AddRef 및 릴리스 -보다 더 많은 작업을 수행할 개체를 구별 하는 것이 더 좋을 것 IUnknown 제공 합니다.여기서 QueryInterface 사용할 수 있습니다.동일한 개체에서 다른 "인터페이스"를 가져올 수 있습니다.일반적으로 이러한 인터페이스가 파생 됩니다 IUnknown 와 새 멤버 함수를 추가 하 여 추가 기능을 추가 합니다.COM 인터페이스를 인터페이스에 선언 된 멤버 변수가 없는 및 모든 멤버 함수는 순수 가상으로 선언 됩니다.다음 예제를 참조하십시오.
class IPrintInterface : public IUnknown
{
public:
virtual void PrintObject() = 0;
};
얻을 수는 IPrintInterface 만 있으면는 IUnknown, 호출 IUnknown::QueryInterface 를 사용 하는 IID 의 IPrintInterface.IID 의 인터페이스를 고유 하 게 식별 하는 128 비트 숫자입니다.되는 IID 또는 OLE 정의 하는 각 인터페이스에 대 한.경우 펑크 에 대 한 포인터입니다를 IUnknown 개체를 검색 하는 코드는 IPrintInterface 에서 때문일 수 있습니다.
IPrintInterface* pPrint = NULL;
if (pUnk->QueryInterface(IID_IPrintInterface,
(void**)&pPrint) == NOERROR)
{
pPrint->PrintObject();
pPrint->Release();
// release pointer obtained via QueryInterface
}
아주 쉽게 보이지만 것 구현 하는 방법을 모두의 Iprintinterface을 지 원하는 개체 및 IUnknown 인터페이스?Iprintinterface에서 직접 파생 되지 않으므로 경우 간단한 것 IUnknown -Iprintinterface을 구현 하 여 IUnknown 자동으로 지원 됩니다.예를 들면 다음과 같습니다.
class CPrintObj : public CPrintInterface
{
virtual HRESULT QueryInterface(REFIID iid, void** ppvObj);
virtual ULONG AddRef();
virtual ULONG Release();
virtual void PrintObject();
};
구현은 AddRef 및 릴리스 정확 하 게 이러한 구현 된 위의 같을 것입니다.CPrintObj::QueryInterface 다음과 비슷하게 됩니다:
HRESULT CPrintObj::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
if (iid == IID_IUnknown || iid == IID_IPrintInterface)
{
*ppvObj = this;
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
경우 볼 수 있듯이 인터페이스 식별자 (IID)는 인식, 사용자 개체에; 포인터 반환 됩니다 그렇지 않으면 오류가 발생합니다.또한 성공적으로 QueryInterface 결과 묵시적으로 AddRef.물론 구현 할 수도 있습니다 CEditObj::Print.방법은 간단 하기 때문에 IPrintInterface 에서 간접적으로 파생 된는 IUnknown 인터페이스.하지만 두 가지 인터페이스를 지 원하는 원한다 면, 둘 다에서 파생 IUnknown, 다음 사항을 고려 하십시오.
class IEditInterface : public IUnkown
{
public:
virtual void EditObject() = 0;
};
모두를 지 원하는 클래스를 구현 하는 다양 한 방법으로 숫자 이지만 IEditInterface 및 IPrintInterface를 비롯 하 여 C++ 다중 상속을 사용 하 여,이 글에서는이 기능을 구현 하는 중첩된 클래스의 중점적으로 다룹니다.
class CEditPrintObj
{
public:
CEditPrintObj();
HRESULT QueryInterface(REFIID iid, void**);
ULONG AddRef();
ULONG Release();
DWORD m_dwRef;
class CPrintObj : public IPrintInterface
{
public:
CEditPrintObj* m_pParent;
virtual HRESULT QueryInterface(REFIID iid, void** ppvObj);
virtual ULONG AddRef();
virtual ULONG Release();
} m_printObj;
class CEditObj : public IEditInterface
{
public:
CEditPrintObj* m_pParent;
virtual ULONG QueryInterface(REFIID iid, void** ppvObj);
virtual ULONG AddRef();
virtual ULONG Release();
} m_editObj;
};
전체 구현은 아래에 포함 되어 있습니다.
CEditPrintObj::CEditPrintObj()
{
m_editObj.m_pParent = this;
m_printObj.m_pParent = this;
}
ULONG CEditPrintObj::AddRef()
{
return ++m_dwRef;
}
CEditPrintObj::Release()
{
if (--m_dwRef == 0)
{
delete this;
return 0;
}
return m_dwRef;
}
HRESULT CEditPrintObj::QueryInterface(REFIID iid, void** ppvObj)
{
if (iid == IID_IUnknown || iid == IID_IPrintInterface)
{
*ppvObj = &m_printObj;
AddRef();
return NOERROR;
}
else if (iid == IID_IEditInterface)
{
*ppvObj = &m_editObj;
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
ULONG CEditPrintObj::CEditObj::AddRef()
{
return m_pParent->AddRef();
}
ULONG CEditPrintObj::CEditObj::Release()
{
return m_pParent->Release();
}
HRESULT CEditPrintObj::CEditObj::QueryInterface(
REFIID iid, void** ppvObj)
{
return m_pParent->QueryInterface(iid, ppvObj);
}
ULONG CEditPrintObj::CPrintObj::AddRef()
{
return m_pParent->AddRef();
}
ULONG CEditPrintObj::CPrintObj::Release()
{
return m_pParent->Release();
}
HRESULT CEditPrintObj::CPrintObj::QueryInterface(
REFIID iid, void** ppvObj)
{
return m_pParent->QueryInterface(iid, ppvObj);
}
대부분의 IUnknown 구현에 배치는 CEditPrintObj CEditPrintObj::CEditObj 및 CEditPrintObj::CPrintObj 코드를 복제 하는 것이 아니라 클래스입니다.이 코드의 양을 줄일 수 및 버그를 피할 수 있습니다.중요 한 점은 IUnknown 인터페이스에서 호출할 수 것입니다 QueryInterface 개체를 모든 인터페이스를 검색할 수 있습니다를 지원 하 고 각 인터페이스에서 동일한 작업을 수행할 수 있습니다.즉, 모든 QueryInterface 각 인터페이스에서 사용 가능한 함수 같은 방식으로 작동 해야 합니다.포함 된 개체의 외부에 "개체" 구현을 호출 되려면 백 포인터 사용된 (m_pParent)입니다.M_pParent 포인터 중 CEditPrintObj 생성자 초기화 됩니다.그런 다음 CEditPrintObj::CPrintObj::PrintObject 및 Ceditprintobj::ceditobj::editobject도 구현할 수 있습니다.코드의 많은 부분이 추가 기능 중 하나에 추가 되었습니다-개체를 편집할 수 있는 기능입니다.다행 스럽게도 (발생 하지 않지만)는 단일 멤버 함수를 인터페이스에 대 한 매우 일반적인 수 없습니다 및이 경우 EditObject 및 PrintObject 일반적으로 단일 인터페이스로 결합할 수 있는.
많은 설명 및 많은 간단한 시나리오에 대 한 코드입니다.MFC/OLE 클래스는 간단한 대안을 제공합니다.MFC 구현 메시지 맵을 사용 하 여 Windows 메시지가 줄 바꿈 하는 방식으로 유사한 기법을 사용 합니다.이 시설 이라고 인터페이스 맵 을 및 다음 섹션에서 설명 합니다.
MFC 인터페이스 맵
MFC/OLE 구현을 하는 MFC의 "메시지 맵" 및 "디스패치 맵"와 유사한 "인터페이스 맵" 개념과 실행에 포함 되어 있습니다.핵심 기능으로 MFC 인터페이스 맵을 다음과 같습니다.
표준 구현인 IUnknown에 내장 된의 CCmdTarget 클래스입니다.
수정 하 여 참조 횟수를 유지 관리 AddRef 및 출시
데이터 기반 구현QueryInterface
또한 인터페이스 맵은 다음 고급 기능을 지원 합니다.
집계 가능한 COM 개체를 만드는 작업에 대 한 지원
집계 개체를 사용 하 여 COM 개체의 구현에 대 한 지원
Hookable 및 확장할 수 있는 구현을입니다.
집계에 대 한 자세한 내용은 OLE 프로그래머용 참조.
MFC 인터페이스 맵을 지원 루트에 있는 CCmdTarget 클래스입니다.CCmdTarget"가는" 개수는 물론 멤버 함수 관련 된 모든 참조는 IUnknown 구현 (참조 횟수가 예입니다 CCmdTarget).OLE COM을 지 원하는 클래스를 만들려면 클래스에서 파생 CCmdTarget 및 다양 한 매크로 사용 뿐만 아니라 멤버 함수를 CCmdTarget 원하는 인터페이스를 구현 합니다.MFC의 구현은 중첩된 클래스를 사용 하 여 위의 예제와 마찬가지로 각 인터페이스 구현을 정의 합니다.이 표준 구현과 많은 반복적인 코드의 일부를 제거 하는 매크로 뿐만 아니라 IUnknown 쉬워집니다.
MFC의 인터페이스를 사용 하 여 클래스 구현에 매핑합니다.
직접 또는 간접적으로 파생 하는 클래스는 CCmdTarget.
사용은 DECLARE_INTERFACE_MAP 파생된 클래스 정의에 함수.
지원 하려는 각 인터페이스에 대해 사용 하는 BEGIN_INTERFACE_PART 및 END_INTERFACE_PART 클래스 정의에서 매크로.
구현 파일에서 사용 하는 BEGIN_INTERFACE_MAP 및 END_INTERFACE_MAP 클래스의 인터페이스 구조를 정의 하는 매크로.
지원 되는 각 IID를 사용 하는 INTERFACE_PART 매크로 사이 BEGIN_INTERFACE_MAP 및 END_INTERFACE_MAP 매크로 IID는 특정 "부분" 클래스에 매핑할.
각각의 지원 되는 인터페이스를 나타내는 중첩된 클래스를 구현 합니다.
사용은 METHOD_PROLOGUE 부모에 액세스 하려면 매크로 CCmdTarget-파생 개체입니다.
AddRef릴리스, 및 QueryInterface 위임할 수는 CCmdTarget 이러한 함수 구현 (ExternalAddRef, ExternalRelease, 및 ExternalQueryInterface).
위의 CPrintEditObj 예제는 다음과 같이 구현할 수 있습니다.
class CPrintEditObj : public CCmdTarget
{
public:
// member data and member functions for CPrintEditObj go here
// Interface Maps
protected:
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(EditObj, IEditInterface)
STDMETHOD_(void, EditObject)();
END_INTERFACE_PART(EditObj)
BEGIN_INTERFACE_PART(PrintObj, IPrintInterface)
STDMETHOD_(void, PrintObject)();
END_INTERFACE_PART(PrintObj)
};
위의 선언에서 파생 된 클래스를 만들고 CCmdTarget.DECLARE_INTERFACE_MAP 매크로 프레임 워크가이 클래스는 사용자 지정 인터페이스 맵 있는지 알려줍니다.또한는 BEGIN_INTERFACE_PART 및 END_INTERFACE_PART 매크로 정의 중첩된 클래스가 경우 CEditObj 및 CPrintObj (X 데만 중첩된 클래스를 구별 하는 "I"로 시작 하는 "C" 및 인터페이스 클래스를 사용 하 여 시작 하는 전역 클래스에서) 이름.이러한 클래스의 중첩 된 두 명의 구성원을 만들어집니다: m_CEditObj, 및 m_CPrintObj, 각각.매크로 자동으로 선언에서 AddRef, 릴리스, 및 QueryInterface 기능을 수행 합니다. 따라서만 함수는이 인터페이스에 선언: EditObject 및 PrintObject (매크로 OLE STDMETHOD 입니다 등 사용 하도록 _stdcall 및 가상 키워드는 대상 플랫폼에 맞게 제공 됩니다).
이 클래스의 인터페이스 맵을 구현 하려면:
BEGIN_INTERFACE_MAP(CPrintEditObj, CCmdTarget)
INTERFACE_PART(CPrintEditObj, IID_IPrintInterface, PrintObj)
INTERFACE_PART(CPrintEditObj, IID_IEditInterface, EditObj)
END_INTERFACE_MAP()
이 IID는 IID_IPrintInterface m_CPrintObj 및 iid_ieditinterface와 m_ceditobj와 각각 연결 됩니다.CCmdTarget 의 구현을 QueryInterface (CCmdTarget::ExternalQueryInterface)이이 지도 사용 하 여 m_CPrintObj 및 m_CEditObj 요청 시에 포인터를 반환 합니다.항목을 포함 하는 것이 필요 하지 않습니다 IID_IUnknown. 프레임 워크 때 첫 번째 인터페이스 맵에서 (이 경우 m_CPrintObj)에 사용할 IID_IUnknown 요청 합니다.
도 BEGIN_INTERFACE_PART 자동으로 선언 되는 매크로 AddRef, 릴리스 및 QueryInterface 함수를 여전히 필요한 구현:
ULONG FAR EXPORT CEditPrintObj::XEditObj::AddRef()
{
METHOD_PROLOGUE(CEditPrintObj, EditObj)
return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CEditPrintObj::XEditObj::Release()
{
METHOD_PROLOGUE(CEditPrintObj, EditObj)
return pThis->ExternalRelease();
}
HRESULT FAR EXPORT CEditPrintObj::XEditObj::QueryInterface(
REFIID iid, void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(CEditPrintObj, EditObj)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
void FAR EXPORT CEditPrintObj::XEditObj::EditObject()
{
METHOD_PROLOGUE(CEditPrintObj, EditObj)
// code to "Edit" the object, whatever that means...
}
구현을 위한 CEditPrintObj::CPrintObj, 수 위의 정의를 Ceditprintobj::ceditobj과 비슷합니다.이러한 기능을 자동으로 생성 하는 데 사용할 수 있는 매크로 만들 수 있습니다 (했지만 OLE MFC/개발에 앞서이 경우 있지만) 매크로 두 줄 이상의 코드를 생성할 때 중단점을 설정 하려면 어려워집니다.이 따라서,이 코드는 수동으로 확장 됩니다.
메시지 맵 구현 프레임 워크를 사용 하 여 여러 가지 필요 없습니다 있습니다.
Queryinterface를 구현 합니다.
구현 AddRef 및 릴리스
이러한 기본 제공 메서드 중 하나를 모두 사용자 인터페이스에서 선언
또한 프레임 워크는 메시지 맵을 내부적으로 사용합니다.이 말은 프레임 워크 클래스에서 파생 하면 COleServerDoc에 이미 특정 인터페이스를 지원 하 고 교체 하거나 추가 하는 프레임 워크에서 제공 하는 인터페이스를 제공 합니다.이 프레임 워크를 완벽 하 게 지 원하는 사실로 가능 상속 기본 클래스는 인터페이스 맵에서-이유는 이유는 무엇입니까 BEGIN_INTERFACE_MAP 기본 클래스 이름을 두 번째 매개 변수로 사용 합니다.
[!참고]
일반적으로 MFC의 기본 제공 구현으로 OLE 인터페이스의 구현을 다시 사용할 수 없습니다 상속 포함 된 특수화의 인터페이스에서 MFC 버전입니다.이것이 불가능 때문에 사용의 METHOD_PROLOGUE 매크로에 포함 된 액세스 CCmdTarget-파생된 개체를 의미는 고정 오프셋 에서 포함된 된 개체의는 CCmdTarget-파생 개체입니다.이 즉, 예를 들어, 포함 된 Xmyadvisesink는 MFC의 구현에서 파생 수 없습니다 COleClientItem::XAdviseSinkXAdviseSink 위에서 특정 오프셋에서 중인에 의존 하기 때문에, 해당 COleClientItem 개체입니다.
[!참고]
그러나 MFC 구현의 모든 기능을 원하는 MFC의 기본 동작에 대 한 위임 수 있습니다.MFC 구현에 이렇게 IOleInPlaceFrame (XOleInPlaceFrame)에 있는 COleFrameHook 클래스 (위임에 다양 한 기능에 대 한 m_xOleInPlaceUIWindow).이 디자인 많은 인터페이스를 구현 하는 개체의 런타임 크기를 줄이기 위해 선택 되었습니다. (방법이 m_pParent 이전 섹션에서 사용한 것과 같은) 백 포인터 필요를 하지 않습니다.
집계 및 인터페이스 맵
독립 실행형 COM 개체를 지 원하는 것 외에 MFC 집계도 지원 합니다.집계 자체는 문서에서 설명 하는 너무 복잡 한 주제입니다. 참조는 OLE 프로그래머용 참조 집계에 대 한 자세한 내용은.이 참고는 단순히 집계 구축 프레임 워크와 인터페이스 지도에 대 한 지원을 설명 합니다.
집계를 사용 하는 방법은 두 가지: (1) 집계를 지 원하는 COM 개체를 사용 하 고 (2) 집계할 수가 다른 개체를 구현 합니다.이러한 기능을 "사용 하 여 집계 개체" 및 "집계 가능한 개체 만들기"로 참조할 수 있습니다.MFC를 모두 지원합니다.
집계 개체를 사용합니다.
집계 개체를 집계 QueryInterface 메커니즘에 빨리 연결할 수 있는 방법이 있을 필요를 사용.즉, 네이티브 개체의 일부인 것 처럼 집계 개체 동작 해야 합니다.그렇다면이 타이 MFC 인터페이스 매핑 메커니즘으로 합니까?이외에 INTERFACE_PART 매크로 중첩된 개체에서 IID에 매핑된 위치 또한 선언할 수 집계 개체의 일부로 사용자 CCmdTarget 클래스를 파생 합니다.이렇게 하려면 해당 INTERFACE_AGGREGATE 매크로 사용 합니다.이 멤버 변수를 지정할 수 있습니다 (에 대 한 포인터 여야는 IUnknown 또는 파생 클래스)를 인터페이스 매핑 메커니즘에 통합 될 수 있는.포인터를 경우 NULL이 아닌 경우 CCmdTarget::ExternalQueryInterface 입니다 라고 하는 프레임 워크가 자동으로 집계 개체 호출 합니다 QueryInterface 경우 멤버 함수는 IID 요청 중 네이티브 아닌 IIDs 지원의 CCmdTarget 개체 자체.
INTERFACE_AGGREGATE 매크로 사용 하려면
멤버 변수를 선언 (에 IUnknown *)는 집계 개체에 대 한 포인터 포함 됩니다.
포함 된 INTERFACE_AGGREGATE 멤버 변수 이름으로 참조 사용자 인터페이스 맵에서 매크로.
특정 시점 (대개 동안 CCmdTarget::OnCreateAggregates), NULL 이외의 다른 멤버 변수를 초기화 합니다.
예를 들면 다음과 같습니다.
class CAggrExample : public CCmdTarget
{
public:
CAggrExample();
protected:
LPUNKNOWN m_lpAggrInner;
virtual BOOL OnCreateAggregates();
DECLARE_INTERFACE_MAP()
// "native" interface part macros may be used here
};
CAggrExample::CAggrExample()
{
m_lpAggrInner = NULL;
}
BOOL CAggrExample::OnCreateAggregates()
{
// wire up aggregate with correct controlling unknown
m_lpAggrInner = CoCreateInstance(CLSID_Example,
GetControllingUnknown(), CLSCTX_INPROC_SERVER,
IID_IUnknown, (LPVOID*)&m_lpAggrInner);
if (m_lpAggrInner == NULL)
return FALSE;
// optionally, create other aggregate objects here
return TRUE;
}
BEGIN_INTERFACE_MAP(CAggrExample, CCmdTarget)
// native "INTERFACE_PART" entries go here
INTERFACE_AGGREGATE(CAggrExample, m_lpAggrInner)
END_INTERFACE_MAP()
m_lpAggrInner 의 생성자에 NULL로 초기화 됩니다.프레임 워크의 기본 구현에서 NULL 멤버 변수를 무시 합니다 QueryInterface.OnCreateAggregates 실제로 집계 개체를 만드는 데는 것이 좋습니다.MFC 구현의 외부에서 개체를 만들 경우 명시적으로 호출 해야 COleObjectFactory.집계를 만드는 이유 CCmdTarget::OnCreateAggregates 의 사용과 CCmdTarget::GetControllingUnknown 집계 가능한 개체 만들기를 설명 하는 경우 드러납니다.
이 기술은 개체 모든 더하기 네이티브 인터페이스는 집계 개체를 지 원하는 인터페이스를 제공 합니다.집계를 지 원하는 인터페이스의 하위 집합만 원할 경우 무시할 수 있습니다 CCmdTarget::GetInterfaceHook.매우 낮은 수준의 hookability 비슷한 있습니다 QueryInterface.일반적으로 집계를 지 원하는 모든 인터페이스를 합니다.
개체 구현 집계 가능한 만들기
집계 가능한 경우 개체의 구현에 대 한 AddRef, 릴리스, 및 QueryInterface 는 "제어 모르지." 위임 해야 즉, 위임 해야 해당 개체에 AddRef, 릴리스, 및 QueryInterface 는 다른 개체에도 파생에서 IUnknown.이 "제어 알" 만들어질 때 개체에는 구현에 제공 됩니다 제공 하지 않습니다 COleObjectFactory.이 구현 약간의 오버 헤드를 지니며 MFC이 선택적 적용 되므로 경우에 따라서는, 바람직하지 않습니다.호출할 집계 가능한 개체를 사용 하려면 CCmdTarget::EnableAggregation 에서 개체의 생성자입니다.
개체 또한 집계를 사용 하는 경우 또한 올바른 전달 되도록 해야 "제어 unknown" 개체를 집계 합니다.일반적으로이 IUnknown 포인터가 집계 만들어질 때 개체에 전달 됩니다.예를 들어 pUnkOuter 매개 변수를 사용 하 여 만든 개체에 대 한 "제어 알"입니다 CoCreateInstance."알 수 없는 제어" 올바른 포인터를 호출 하 여 검색할 수 있는 CCmdTarget::GetControllingUnknown.하지만 그 함수 로부터 값을 반환 생성자 중 올바르지 않습니다.이러한 이유로 재정의 된 집계를 만드는 것이 좋습니다 CCmdTarget::OnCreateAggregates, 반환 값에서 GetControllingUnknown 에서 만들어진 경우에 안정적으로 운영 될는 COleObjectFactory 구현 합니다.
개체 추가 또는 인공 참조 횟수를 해제 하는 경우 올바른 참조 횟수를 조작 지 중요 합니다.경우, 항상 call ExternalAddRef 및 ExternalRelease 대신 InternalRelease 및 InternalAddRef.호출 하는 것이 어렵습니다 InternalRelease 또는 InternalAddRef 에서 집계를 지 원하는 클래스입니다.
참조 자료
고유의 인터페이스를 정의 하거나 재정의 OLE 인터페이스 프레임 워크의 구현 OLE의 고급 사용법 내부 인터페이스 매핑 메커니즘을 사용을 해야 합니다.
이 섹션에서는 각 매크로 및 이러한 고급 기능을 구현 하는 데 사용 되는 Api에 설명 합니다.
CCmdTarget::EnableAggregation-함수에 대 한 설명
void EnableAggregation();
설명
이 형식의 개체에 대 한 OLE 집계를 지원 하려는 경우 파생된 클래스의 생성자에서이 함수를 호출 합니다.이 집계 가능한 개체에 대 한 필요는 특별 한 IUnknown 구현을 준비 합니다.
CCmdTarget::ExternalQueryInterface-함수에 대 한 설명
DWORD ExternalQueryInterface(
const void FAR* lpIID,
LPVOID FAR* ppvObj
);
설명
매개 변수
lpIID
멀리 포인터는 IID (QueryInterface 첫 번째 인수)ppvObj
에 대 한 포인터는 IUnknown * (두 번째 인수에 QueryInterface)
설명
클래스를 각각의 인터페이스에 대 한 IUnknown 구현에서이 함수를 호출을 구현 합니다.이 함수는 QueryInterface 개체 인터페이스 맵을 기반 표준 데이터 기반 구현을 제공 합니다.HRESULT 반환 값을 캐스팅 하는 것이 필요 합니다.개체가 집계 되지 않으면 로컬 인터페이스 맵을 사용 하는 대신 "제어 IUnknown"이이 함수를 호출 합니다.
CCmdTarget::ExternalAddRef-함수에 대 한 설명
DWORD ExternalAddRef();
설명
클래스는 각 인터페이스에 대 한 Iunknown::addref의 구현에이 함수를 호출을 구현 합니다.반환 값의 새 참조 횟수 CCmdTarget 개체입니다.개체가 집계 되지 않으면 로컬 참조 횟수를 조작 하는 대신 "제어 IUnknown"이이 함수를 호출 합니다.
CCmdTarget::ExternalRelease-함수에 대 한 설명
DWORD ExternalRelease();
설명
클래스는 각 인터페이스에 대 한 Iunknown::release의 구현에이 함수를 호출을 구현 합니다.반환 값은 개체의 새 참조 횟수를 나타냅니다.개체가 집계 되지 않으면 로컬 참조 횟수를 조작 하는 대신 "제어 IUnknown"이이 함수를 호출 합니다.
DECLARE_INTERFACE_MAP-매크로 설명
DECLARE_INTERFACE_MAP
설명
이 매크로 사용 하 여 파생 된 클래스에서 CCmdTarget 는 인터페이스 맵이 있어야 합니다.거의 같은 방법으로 사용 되는 DECLARE_MESSAGE_MAP.이 매크로 호출 헤더는 일반적으로 클래스 정의에 넣어야 합니다 (.H) 파일입니다.클래스와 DECLARE_INTERFACE_MAP 인터페이스 맵을 구현 파일에 정의 해야 (.CPP)에 있는 BEGIN_INTERFACE_MAP 및 END_INTERFACE_MAP 매크로.
BEGIN_INTERFACE_PART 및 END_INTERFACE_PART-매크로 설명
BEGIN_INTERFACE_PART(
localClass,
iface
);
END_INTERFACE_PART(
localClass
)
설명
매개 변수
localClass
인터페이스를 구현 하는 클래스의 이름iface
이 클래스를 구현 하는 인터페이스의 이름
설명
필요가 클래스를 구현 하는 각 인터페이스에는 BEGIN_INTERFACE_PART 및 END_INTERFACE_PART 쌍.이러한 매크로 물론 해당 클래스의 포함 된 멤버 변수를 정의 하는 OLE 인터페이스 로부터 파생 되는 로컬 클래스를 정의 합니다.AddRef, 릴리스, 및 QueryInterface 멤버를 자동으로 선언 합니다.구현 되는 인터페이스의 일부가 다른 멤버 함수에 대 한 선언을 포함 합니다 (이러한 선언 사이 배치 되는 BEGIN_INTERFACE_PART 및 END_INTERFACE_PART 매크로).
Iface 인수는 같은 구현 하고자 하는 OLE 인터페이스 IAdviseSink, 또는 IPersistStorage (또는 직접 사용자 지정 인터페이스).
LocalClass 인수에 정의 되는 로컬 클래스의 이름입니다.' X'는 이름에 자동으로 추가 될.이 명명 규칙을 사용 하 여 같은 이름의 전역 클래스와의 충돌을 피할 수 있습니다.또한 같은 포함 된 멤버의 이름에 localClass 'm_x가 '를 접두사로 사용 하지 제외 이름.
예를 들면 다음과 같습니다.
BEGIN_INTERFACE_PART(MyAdviseSink, IAdviseSink)
STDMETHOD_(void,OnDataChange)(LPFORMATETC, LPSTGMEDIUM);
STDMETHOD_(void,OnViewChange)(DWORD, LONG);
STDMETHOD_(void,OnRename)(LPMONIKER);
STDMETHOD_(void,OnSave)();
STDMETHOD_(void,OnClose)();
END_INTERFACE_PART(MyAdviseSink)
IAdviseSink에서 파생 된 XMyAdviseSink 라는 로컬 클래스를 정의할 수 및 m_xmyadvisesink.note는 선언 된 클래스의 멤버를 호출:
[!참고]
줄 다음으로 시작 STDMETHOD_ 에서 OLE2 기본적으로 복사 됩니다.H와 약간 수정 된.Ole2에서 복사 합니다.H는 해결 하기 어려운 오류를 줄일 수 있습니다.
BEGIN_INTERFACE_MAP 및 END_INTERFACE_MAP-매크로 설명
BEGIN_INTERFACE_MAP(
theClass,
baseClass
)
END_INTERFACE_MAP
설명
매개 변수
theClass
인터페이스 맵을 정의 해야 하는 클래스baseClass
클래스 theClass 에서 파생 됩니다.
설명
BEGIN_INTERFACE_MAP 및 END_INTERFACE_MAP 매크로 구현 파일에 실제로 인터페이스 맵을 정의할 때 사용 합니다.각 인터페이스에 대해 구현 되는 하나 이상의 INTERFACE_PART 매크로 호출 합니다.클래스를 사용 하 여 각 집계에는 하나 INTERFACE_AGGREGATE 매크로 호출 합니다.
INTERFACE_PART-매크로 설명
INTERFACE_PART(
theClass,
iid,
localClass
)
설명
매개 변수
theClass
인터페이스 맵이 들어 있는 클래스의 이름입니다.iid
IID 가 포함 된 클래스에 매핑할 수 있습니다.localClass
('X') 덜 로컬 클래스의 이름입니다.
설명
이 매크로 사이 사용 되는 BEGIN_INTERFACE_MAP 매크로 END_INTERFACE_MAP 매크로 각 인터페이스에 대 한 개체를 지원할.IID는 지정 된 클래스의 멤버에 매핑할 수 있습니다 theClass 및 localClass.'M_x 가' 추가할 수 있는 localClass 자동으로.참고 하나에 두 개 이상의 IID 단일 멤버와 연관 될 수 있습니다."가장 파생" 인터페이스만 구현 하는 모든 중간 인터페이스를 제공 하려는 경우에 매우 유용 합니다.이것의 좋은 예입니다 있는 IOleInPlaceFrameWindow 인터페이스입니다.해당 계층 구조는 다음과 같습니다.
IUnknown
IOleWindow
IOleUIWindow
IOleInPlaceFrameWindow
개체를 구현 하는 경우 IOleInPlaceFrameWindow, 클라이언트 수 있습니다 QueryInterface 이러한 인터페이스 중 하나에: IOleUIWindow, IOleWindow, 또는 IUnknown, "가장 많이 파생 된" 인터페이스 외에도 IOleInPlaceFrameWindow (실제로 구현 하나).이 처리를 두 개 이상 사용할 수 있습니다 INTERFACE_PART 매크로 각 기본 인터페이스에 매핑하는 IOleInPlaceFrameWindow 인터페이스:
클래스 정의 파일:
BEGIN_INTERFACE_PART(CMyFrameWindow, IOleInPlaceFrameWindow)
클래스 구현 파일:
BEGIN_INTERFACE_MAP(CMyWnd, CFrameWnd)
INTERFACE_PART(CMyWnd, IID_IOleWindow, MyFrameWindow)
INTERFACE_PART(CMyWnd, IID_IOleUIWindow, MyFrameWindow)
INTERFACE_PART(CMyWnd, IID_IOleInPlaceFrameWindow, MyFrameWindow)
END_INTERFACE_MAP
프레임 워크의 IUnknown 필수 이기 때문에 수행 됩니다.
INTERFACE_PART-매크로 설명
INTERFACE_AGGREGATE(
theClass,
theAggr
)
설명
매개 변수
theClass
인터페이스 맵에 포함 된 클래스의 이름을,theAggr
집계 된 멤버 변수의 이름입니다.
설명
이 매크로 집계 개체 클래스를 사용 하는 프레임 워크를 알리는 데 사용 됩니다.사이 나타나야는 BEGIN_INTERFACE_PART 및 END_INTERFACE_PART 매크로.집계 개체에서 파생 된 별도 개체입니다 IUnknown.집계를 사용 하 여, INTERFACE_AGGREGATE 매크로 집계 지원 표시 개체에서 직접 지원 되는 모든 인터페이스 만들 수 있습니다.TheAggr 인수는 단순히 이름에서 파생 된 클래스의 멤버 변수 IUnknown (직접 또는 간접적으로).모든 INTERFACE_AGGREGATE 매크로 수행 해야는 INTERFACE_PART 는 인터페이스 맵에서 놓으면 매크로.