OLE 2의 핵심은 "OLE 구성 요소 개체 모델", 또는 COM. COM 표준 정의 어떻게 협력 개체에 대 한 서로 통신 합니다. "개체" 어떤 모양 메서드 개체에 발송 되는 방법 등의 내용을 포함 합니다. COM 모든 COM 호환 클래스가 파생 되는 기본 클래스를 정의 합니다. 이 기본 클래스는 IUnknown입니다. COM은 어떤 하나의 언어 특정 IUnknown 인터페이스 c + + 클래스 라고도, 비록 ? C, 파스칼, 또는 COM 개체의 이진 레이아웃이 지원할 수 있는 다른 언어에서 구현 될 수 있다。
OLE "인터페이스"으로 IUnknown 에서 파생 된 모든 클래스를 말합니다 IUnknown 그걸로 운반 구현이 같은 "인터페이스" 이후 중요 한 차이입니다. 그것은 단순히는 개체 통신, 아니라 그 구현 할 구체적인 프로토콜을 정의 합니다. 이것은 최대의 유연성을 허용 하는 시스템에 대 한 합리적 이다. 그것은 MFC/c + + 프로그램에 대 한 기본 동작을 구현 하는 MFC의 직업。
MFC의 구현 IUnknown 을 이해 하려면 먼저이 인터페이스는 이해 해야 합니다. Iunknown의 단순화 된 버전 아래에 정의 된:
iUnknown 클래스
{
공개:
nbsp;? 가상 HRESULT QueryInterface(REFIID iid, void** ppvObj) = 0;
?? 가상 ULONG AddRef() = 0;
?? 가상 ULONG Release() = 0;
}(&N)
메모nbsp;??이 그림에 대 한 예: __stdcall 호출 필요한 특정 규칙 세부 밖으로 남아 있다(&N)。
AddRef 및 릴리스 멤버 함수는 개체의 메모리 관리를 제어합니다. COM 참조 카운팅 구성표를 사용 하 여 개체를 계속 추적 해야 합니다. 개체가 참조 하는 절대 c + +에서와 마찬가지로 직접. 대신, COM 개체는 항상 포인터를 통해 참조 됩니다. 소유자 할 때 개체를 해제 하려면 그것을 사용 하 여 개체의 릴리스 멤버 라고 (대조적으로 사용 하는 연산자 삭제, 기존 c + + 개체에 대 한 할 것 이다). 메커니즘을 계산 하는 참조를 관리할 수 단일 개체에 대 한 여러 참조를 허용 합니다. 개체의 참조 횟수를 유지 하는 AddRef 및 Release 구현을 ? 개체의 참조 횟수가 0에 도달 될 때까지 삭제 되지 않습니다。
AddRef 및 릴리스 는 구현 관점에서 매우 간단 합니다. 여기는 사소한 구현:
ULONG CMyObj::AddRef() {nbsp;? 반환 + + m_dwRef;
}
ULONG CMyObj::Release() {경우 (-m_dwRef = = 0) {
?????? 삭제이;
?????? 0; 반환
?? }
?? 반환 m_dwRef;
}(&N)
QueryInterface 멤버 함수는 좀 더 흥미롭습니다. 당신이 상상할 수 있는 매우 흥미로운 AddRef 및 릴리스 누구의 유일한 멤버 함수는 개체가 아닌 ? 개체의 IUnknown 을 제공 하는 보다 더 많은 일을 할 게 좋을 텐데. 이것은 QueryInterface 이다 유용 하다입니다. 동일한 개체에서 다른 "인터페이스"를 얻을 수 있습니다. 이러한 인터페이스는 일반적으로 IUnknown 에서 파생 하 고 새 멤버 함수를 추가 하 여 추가 기능을 추가. COM 인터페이스는 결코 인터페이스에 선언 된 멤버 변수 있고 모든 멤버 함수는 순수 가상으로 선언 됩니다. 예를 들어,
iPrintInterface 클래스: 공용 IUnknown
{
공개:
nbsp;? 가상 void PrintObject() = 0;
}(&N)
단지 당신이 가진다면 IUnknown을 Iprintinterface를 얻으려면, iunknown:: Queryinterface 를 Iprintinterface의 IID 를 사용 하 여 호출 합니다. IID 는 인터페이스를 고유 하 게 식별 하는 128 비트 숫자입니다. 또는 OLE 정의 하는 각 인터페이스에 대해 IID 입니다. 그것 으로부터 Iprintinterface를 검색 하는 코드 있을 펑크 IUnknown 개체에 대 한 포인터 이면
IPrintInterface * pPrint = NULL;
경우 (펑크-gt;QueryInterface(IID_IPrintInterface, (void**) & pPrint) = NOERROR)
{
?? pPrint-> PrintObject();
?? pPrint-> Release();
?????? / / 릴리스 포인터는 Queryinterface를 통해 얻은
}
그 매우 쉬운 것 같이 보이지만 IPrintInterface IUnknown 인터페이스를 지 원하는 개체를 구현할 것 이라고 어떻게? 이 경우에 그것은 간단 합니다 IPrintInterface IUnknown 에서 직접 파생 된 이후 ? Iprintinterface를 구현 하 여 IUnknown 자동으로 지원 됩니다. 예를 들어:
cPrintObj 클래스: 공용 CPrintInterface
{
nbsp;? 가상 HRESULT QueryInterface(REFIID iid, void** ppvObj);
?? 가상 ULONG AddRef();
?? 가상 ULONG Release();
?? 가상 void PrintObject();
}(&N)
AddRef 및 Release 구현이 될 것 이라고 정확히 위에 구현 된 것과 동일 합니다. CPrintObj::QueryInterface 이런식으로 생겼을 것 이다
HRESULT CPrintObj::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
nbsp;? 경우 (iid IID_IUnknown = = | | iid = IID_IPrintInterface)
?? {
?????? * ppvObj =이;
?????? AddRef();
?????? 반환 NOERROR;
?? }
?? 반환 ResultFromScode(E_NOINTERFACE);
}(&N)
포인터가 개체; 반환 됩니다 볼 수 있듯이, 인터페이스 식별자 (IID)를 인식 하는 경우, 그렇지 않으면 오류가 발생합니다. 또한 성공적인 QueryInterface 묵시적된 AddRef에 결과 노트. 물론, 또한 해야 CEditObj::Print를 구현 합니다. 그는 Iprintinterface는 IUnknown 인터페이스에서 직접 파생 된 때문에 간단 합니다. 그러나 모두 IUnknown파생 된 두 개의 서로 다른 인터페이스를 지원 하고자 하는 경우 다음 사항을 고려합니다
iEditInterface 클래스: 공용 IUnkown
{
공개:
nbsp;? 가상 void EditObject() = 0;
}(&N)
이 노트가이 기능을 구현 하는 중첩된 클래스를 사용 하 여에 집중할 것 이다 비록 거기에 IEditInterface 및 c + + 다중 상속을 사용 하 여 포함 하는 IPrintInterface 지원 클래스를 구현 하는 다른 방법의 수。
cEditPrintObj 클래스
{
공개:
nbsp;? CEditPrintObj();
HRESULT QueryInterface(REFIID iid, void**);
?? ULONG AddRef();
?? ULONG Release();
?? DWORD m_dwRef;
CPrintObj 클래스: 공용 IPrintInterface
?? {
?? 공개:
?????? CEditPrintObj * m_pParent;
?????? 가상 HRESULT QueryInterface(REFIID iid, void** ppvObj);
?????? 가상 ULONG AddRef();
?????? 가상 ULONG Release();
?? } m_printObj;
CEditObj 클래스: 공용 IEditInterface
?? {
?? 공개:
?????? CEditPrintObj * m_pParent;
?????? 가상 ULONG QueryInterface(REFIID iid, void** ppvObj);
?????? 가상 ULONG AddRef();
?????? 가상 ULONG Release();
?? } m_editObj;
}(&N)
전체 구현은 아래에 포함 되어있습니다.:
CEditPrintObj::CEditPrintObj()
{
nbsp;? m_editObj.m_pParent =이;
?? m_printObj.m_pParent =이;
}
ULONG CEditPrintObj::AddRef() {반환 + + m_dwRef;
}
CEditPrintObj::Release()
{
?? 경우 (-m_dwRef = = 0)
?? {
?????? 삭제이;
?????? 0; 반환
?? }
?? 반환 m_dwRef;
}
HRESULT CEditPrintObj::QueryInterface(REFIID iid, void** ppvObj)
{
?? 경우 (iid IID_IUnknown = = | | iid = IID_IPrintInterface)
?? {
?????? * ppvObj = & m_printObj;
?????? AddRef();
?????? 반환 NOERROR;
?? }
?? else if (iid = IID_IEditInterface)
?? {
?????? * ppvObj = & m_editObj;
?????? AddRef();
?????? 반환 NOERROR;
?? }
?? 반환 ResultFromScode(E_NOINTERFACE);
}
ULONG CEditPrintObj::CEditObj::AddRef() {반환 m_pParent-> AddRef();
}
ULONG CEditPrintObj::CEditObj::Release() {반환 m_pParent-> Release();
}
HRESULT CEditPrintObj::CEditObj::QueryInterface (
?? REFIID iid, void ** ppvObj) {반환 m_pParent-> QueryInterface (iid, ppvObj);
}
ULONG CEditPrintObj::CPrintObj::AddRef() {반환 m_pParent-> AddRef();
}
ULONG CEditPrintObj::CPrintObj::Release() {반환 m_pParent-> Release();
}
HRESULT CEditPrintObj::CPrintObj::QueryInterface (
?? REFIID iid, void ** ppvObj) {반환 m_pParent-> QueryInterface (iid, ppvObj);
}
대부분의 IUnknown 구현 알 CEditPrintObj::CEditObj 및 CEditPrintObj::CPrintObj 코드를 복제 하는 대신 CEditPrintObj 클래스에 배치 됩니다. 이 코드의 양을 줄이고 버그를 방지 합니다. 핵심 포인트는 여기 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의 인터페이스 지도의 핵심 기능은 다음과 같습니다.:
또한, 인터페이스 맵을 다음과 같은 고급 기능 지원:
집계에 자세한 내용은 다음 웹 사이트를 참조 하십시오. OLE 프로그래머용 참조。
MFC의 인터페이스 맵 지원 CCmdTarget 클래스에 뿌리입니다. CCmdTarget "가는" 수 뿐만 아니라 IUnknown 구현 (참조 횟수가 예는 CCmdTarget)와 관련 된 모든 멤버 함수를 참조 합니다. CCmdTarget 에서 파생 하는 클래스 및 다양 한 매크로 사용 하 여 OLE COM을 지 원하는 클래스를 만들려면 원하는 인터페이스를 구현 하는 CCmdTarget 의 멤버 함수 뿐만 아니라. 중첩된 클래스를 사용 하 여 위의 예제 처럼 각 인터페이스 구현을 정의 하는 MFC의 구현. 이 반복적인 코드 중 일부를 제거 하는 매크로의 숫자 뿐만 아니라 IUnknown 표준 구현과 쉽게 만들어。
지도 기본 인터페이스
지도 MFC의 인터페이스를 사용 하 여 클래스를 구현 하려면 다음이 단계를 따르십시오:
위의 CPrintEditObj 예제에서는 다음과 같은 구현 될 수 있습니다.:
cPrintEditObj 클래스: 공용 CCmdTarget
{
공개:
nbsp;? / / 데이터 멤버 및 멤버 함수 Cprinteditobj에 대 한 간다
/ / 지도 인터페이스
보호 된:
?? 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)
}(&N)
위의 선언은 CCmdTarget에서 파생 된 클래스를 만듭니다. DECLARE_INTERFACE_MAP 매크로이 클래스는 사용자 지정 인터페이스 지도가지고 것입니다 프레임 워크를 알려줍니다. 또한, BEGIN_INTERFACE_PART 및 END_INTERFACE_PART 매크로 정의 중첩된 클래스,이 경우 이름 CEditObj 및 CPrintObj ("C"로 시작 하는 전역 클래스 및 "I"로 시작 하는 인터페이스 클래스에서 중첩 된 클래스를 차별화 하는 데만 사용 되는 X)와 함께. 이러한 클래스의 두 명의 중첩 된 구성원이 만들어집니다: m_CEditObj, 및 m_CPrintObj, 각각. 매크로 자동으로 선언 AddRef, 릴리스및 QueryInterface 함수; 따라서만 선언 함수를이 인터페이스를 특정: EditObject 및 PrintObject ( STDMETHOD 는 OLE 매크로 사용 같은 _stdcall 및 가상 키워드는 대상 플랫폼에 맞게 제공)。
이 클래스에 대 한 인터페이스 맵을 구현:
BEGIN_INTERFACE_MAP (CPrintEditObj, CCmdTarget)
nbsp;? INTERFACE_PART (CPrintEditObj, IID_IPrintInterface, PrintObj)
?? INTERFACE_PART (CPrintEditObj, IID_IEditInterface, EditObj)
END_INTERFACE_MAP()(&N)
이 연결 IID_IPrintInterface IID 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까지 수출 CEditPrintObj::XEditObj::AddRef()
{
nbsp;? METHOD_PROLOGUE (CEditPrintObj, EditObj)
?? 반환 pThis-> ExternalAddRef();
}
ULONG까지 수출 CEditPrintObj::XEditObj::Release()
{
?? METHOD_PROLOGUE (CEditPrintObj, EditObj)
?? 반환 pThis-> ExternalRelease();
}
HRESULT까지 CEditPrintObj::XEditObj::QueryInterface (내보내기
?? REFIID iid, void 멀리 * 훨씬 * ppvObj)
{
?? METHOD_PROLOGUE (CEditPrintObj, EditObj)
?? 반환 (HRESULT) pThis-> ExternalQueryInterface (& iid, ppvObj);
}
void까지 수출 CEditPrintObj::XEditObj::EditObject()
{
?? METHOD_PROLOGUE (CEditPrintObj, EditObj)
?? / / 코드 "편집" 개체를 어떤 의미...
}
CEditPrintObj::CPrintObj에 대 한 구현 Ceditprintobj::ceditobj에 대 한 위의 정의 비슷할 것 이다. (사실, MFC/OLE 개발 앞부분에서이 사건 이었다) 이러한 기능을 자동으로 생성 하는 데 사용 될 수 있는 매크로 만들 수 있을 것 이라고 하지만 매크로 보다 한 줄의 코드를 생성할 때 브레이크 포인트를 설정 하는 것이 어려워집니다. 이런이 이유로 들어,이 코드는 수동으로 확장 됩니다.
메시지의 프레임 워크 구현을 사용 하 여 지도 거기는 다양 한 것 들을 할 필요가 되지 않았다:
또한, 프레임 워크는 내부적으로 메시지 지도 사용합니다. 이 프레임 워크 클래스에서 파생 하면 COleServerDoc, 이미 특정 인터페이스를 지원 하 고 교체 또는 추가 프레임 워크에서 제공 하는 인터페이스를 제공 하는 말. 이 프레임 워크를 완벽 하 게 지원 인터페이스 지도 기본 클래스에서 상속 하는 사실에 의해 사용-그 이유는 왜 BEGIN_INTERFACE_MAP 의 두 번째 매개 변수로 기본 클래스의 이름。
메모nbsp;??그것은 일반적으로 MFC의 OLE 인터페이스의 기본 구현은 구현 상속 MFC 버전에서 해당 인터페이스의 임베디드 전문화 하 여 다시 사용할 수 없습니다. 이 불가능 하기 때문에 포함 CCmdTarget에 접근할 METHOD_PROLOGUE 매크로 사용 하 여-파생된 개체 의미를 고정 오프셋 CCmdTarget에서 포함 된 개체의-개체를 파생 합니다. 즉, 예를 들어, COleClientItem 개체의 위쪽에서 특정 오프셋에 의존 하는 XAdviseSink 때문에 포함 된 Xmyadvisesink에서 COleClientItem::XAdviseSink, MFC의 구현에서 파생 수 없습니다(&N).
그러나, 모든 MFC의 기본 동작을 원하는 함수에 대 한 MFC 구현에 위임할 수 있습니다. (그것은 많은 기능에 대 한 m_xoleinplaceuiwindow에 위임) COleFrameHook 클래스에서 IOleInPlaceFrame (XOleInPlaceFrame)의 MFC 구현에서 이루어집니다. 이 설계; 많은 인터페이스를 구현 하는 개체의 런타임 크기를 줄이기 위해 선택 되었다 (같은 방법으로 m_pParent 이전 섹션에서 사용한) 백 포인터에 대 한 필요성 제거。
집계 및 인터페이스 지도
독립 실행형 COM 개체 지원 외에 MFC 또한 집계를 지원 합니다. 자체 집계는 너무 복잡 한 주제를 논의 여기; 집계에 대 한 자세한 내용은 OLE 프로그래머용 참조 를 참조 하십시오. 이 노트는 단순히 프레임 워크와 인터페이스 지도에 내장 된 집계에 대 한 지원을 설명 합니다.
집계를 사용 하는 방법에 두 가지: (1) 집계를 지 원하는 COM 개체를 사용 하 고 (2) 다른 집계 될 수 있는 개체를 구현 합니다. 이러한 기능은 "집계 개체를 사용 하 여" 및 "만들기 개체를 집계할 수"로 참조할 수 있습니다. MFC 모두 지원。
집계 개체를 사용 하 여
개체를 사용 하는 집계, QueryInterface 메커니즘으로 집계 넥타이 몇 가지 방법이 있을 거기 필요가 있습니다. 다른 말로 하면, 집계 개체는 개체의 일부인 네이티브 처럼 행동 해야 합니다. 그래서 어떻게 MFC의 인터페이스 맵 메커니즘에이 넥타이 합니까? 중첩 된 개체는 IID에 매핑된 어디 INTERFACE_PART 매크로 외에 또한 CCmdTarget 파생 된 클래스의 일부로 집계 개체를 선언할 수 있습니다. 이렇게 하려면 INTERFACE_AGGREGATE 매크로 사용 됩니다. 이 기능을 사용 하면 멤버 변수 (는 IUnknown 에 대 한 포인터 이어야 합니다 또는 파생 클래스), 인터페이스 맵 메커니즘에 통합 하는 지정할 수 있습니다. CCmdTarget::ExternalQueryInterface 가 호출 될 때 포인터를 NULL 없는 경우 프레임 워크 자동으로 집계 개체의 QueryInterface 멤버 함수를 호출 하는 것입니다, 그리고 IID 를 요청 하는 경우이 중 하나가 아닌 네이티브 IID의 CCmdTarget 개체 자체에 의해 지원。
INTERFACE_AGGREGATE 매크로 사용 하려면 다음이 단계를 수행:
예를 들어,
cAggrExample 클래스: 공용 CCmdTarget
{
공개:
nbsp;? CAggrExample();
보호 된:
?? LPUNKNOWN m_lpAggrInner;
?? 가상 BOOL OnCreateAggregates();
DECLARE_INTERFACE_MAP()
?? / / "네이티브" 인터페이스 부분 매크로 여기에서 사용할 수 있습니다
};
CAggrExample::CAggrExample()
{
?? m_lpAggrInner = NULL;
}
BOOL CAggrExample::OnCreateAggregates()
{
?? / / 올바른 제어 알으로 집계 연결
?? m_lpAggrInner (CLSID_Example, Cocreateinstance를 =
?????? GetControllingUnknown(), CLSCTX_INPROC_SERVER,
?????? IID_IUnknown, (LPVOID *) & m_lpAggrInner);
?? 경우 (m_lpAggrInner = = NULL)
?????? FALSE; 반환
?? / / 여기에 다른 집계 개체를 선택적으로 만들
?? TRUE를 반환 합니다.
}
BEGIN_INTERFACE_MAP (CAggrExample, CCmdTarget)
?? / / 여기에 서 네이티브 "INTERFACE_PART" 항목
?? INTERFACE_AGGREGATE (CAggrExample, m_lpAggrInner)
END_INTERFACE_MAP()
m_lpAggrInner를 NULL로 생성자에서 초기화 합니다. 프레임 워크는 QueryInterface의 기본 구현에서 NULL 멤버 변수를 무시 합니다. OnCreateAggregates 는 실제로 집계 개체를 만드는 것이 좋습니다. COleObjectFactory의 MFC 구현 외부의 개체를 만드는 경우에 명시적으로 호출 해야 합니다. CCmdTarget::GetControllingUnknown 의 사용 뿐만 아니라 CCmdTarget::OnCreateAggregates 에서 집계를 만드는 이유는 설명 집계할 수 개체를 만들 때 명백한 될 것입니다.
이 기술은 집계 개체에서 네이티브 인터페이스 플러스 지원 인터페이스의 모든 하는 개체를 줄 것 이다. 집계 지원 인터페이스의 하위 집합만 하려는 경우에 CCmdTarget::GetInterfaceHook를 재정의할 수 있습니다. 이렇게 하면 매우 낮은 수준의 hookability, QueryInterface비슷합니다. 일반적으로, 원하는 집계를 지 원하는 모든 인터페이스。
개체 구현 집계할 수 만들기
"제어 알." 위임 AddRef, 릴리스및 QueryInterface 구현을 해야 합니다 개체를 집계할 수 수에 대 한 다른 말로 하면, 개체의 일부가 될 것, 그것은 위임 해야 합니다 AddRef, 릴리스및 QueryInterface 또한 IUnknown에서 파생 된 다른 개체를. 이 "제어 알 수"는 개체를 만들 때, 즉 제공 됩니다 COleObjectFactory의 구현에 제공 합니다. 이 구현 오버 헤드의 작은 금액을 수행 하 고 경우에 따라 바람직하지 않다, 그래서 MFC 선택적이 게. 개체의 생성자에서 CCmdTarget::EnableAggregation 을 호출 개체를 집계할 수 있을 수 있도록,。
개체는 또한 집계를 사용 하는 경우 올바른 통과 해야 해야 합니다 또한 집계 개체를 "제어 알". 일반적으로이 IUnknown 포인터는 집계 만들어질 때 개체에 전달 됩니다. 예를 들어, pUnkOuter 매개 변수는 CoCreateInstance를 사용 하 여 만든 개체에 대 한 "제어 알"입니다. 올바른 "알 수 없는 제어" 포인터 CCmdTarget::GetControllingUnknown를 호출 하 여 검색할 수 있습니다. 그러나 해당 함수에서 반환 되는 값 유효 하지 생성자 중. 이런 이유로 그것은 제안 CCmdTarget::OnCreateAggregates, 어디 GetControllingUnknown 의 반환 값은 COleObjectFactory 구현에서 생성 하는 경우에 신뢰할 수 있는 재정의에 귀하의 집계를 만드는。
그것도 중요 개체 추가 또는 인공 참조 횟수를 해제 하는 경우 올바른 참조 횟수를 조작 합니다. 이 경우 위해 항상 ExternalAddRef 및 InternalRelease 및 InternalAddRef대신 ExternalRelease 를 호출 합니다. 집계를 지 원하는 클래스에 InternalRelease 또는 InternalAddRef 를 호출 하는 것 두 일 이다。
참조 자료
OLE 고유의 인터페이스를 정의 하거나 OLE 인터페이스 프레임 워크의 구현을 재정의 등의 고급 사용 기본 인터페이스 맵 메커니즘을 사용 해야。
이 섹션에서는 각 매크로 및 이러한 고급 기능을 구현 하는 데 사용 되는 Api를 설명 합니다.
CCmdTarget::EnableAggregation-함수 설명
void EnableAggregation();
메모nbsp;??이 유형의 개체에 대 한 OLE 집계를 지원 하고자 하는 경우에 파생된 클래스의 생성자에서이 함수를 호출 합니다. 이 집계할 수 개체에 필요한 특별 한 IUnknown 구현 준비(&N)。
CCmdTarget::ExternalQueryInterface-함수 설명
DWORD ExternalQueryInterface (const void 멀리 * lpIID, LPVOID 멀리 * ppvObj);
lpIID
IID (QueryInterface 첫 번째 인수)를 멀리 포인터
ppvObj
에 IUnknown * 포인터 (두 번째 인수 QueryInterface)
메모nbsp;??이 함수 호출의 IUnknown 구현에서 각 인터페이스에 대 한 클래스를 구현 합니다. 이 함수는 개체의 인터페이스 맵을 기반으로 Queryinterface의 표준 데이터 기반 구현을 제공 합니다. 그것은 HRESULT 반환 값을 캐스팅 하는 데 필요한입니다. 이 기능은 로컬 인터페이스 맵을 사용 하는 대신 "제어 IUnknown" 호출 개체를 집계 하는 경우(&N)。
CCmdTarget::ExternalAddRef-함수 설명
DWORD ExternalAddRef();
메모nbsp;??이 함수를 호출 Iunknown::addref의 구현에서 각 인터페이스에 대 한 클래스를 구현 합니다. 반환 값은 CCmdTarget 개체에 대해 새 참조 횟수입니다. 이 기능은 로컬 참조 횟수를 조작 하는 대신 "제어 IUnknown" 호출 개체를 집계 하는 경우(&N)。
CCmdTarget::ExternalRelease-함수 설명
DWORD ExternalRelease();
메모nbsp;??이 함수를 호출 Iunknown::release의 구현에서 각 인터페이스에 대 한 클래스를 구현 합니다. 반환 값은 개체에 대해 새 참조 횟수를 나타냅니다. 이 기능은 로컬 참조 횟수를 조작 하는 대신 "제어 IUnknown" 호출 개체를 집계 하는 경우(&N)。
DECLARE_INTERFACE_MAP-매크로 설명
DECLARE_INTERFACE_MAP
메모nbsp;??이 매크로 사용 하 여 인터페이스 지도는 CCmdTarget 에서 파생 된 모든 클래스의. DECLARE_MESSAGE_MAP와 같은 방식으로 많이 사용. 클래스 정의 헤더에 일반적으로에이 매크로 호출을 배치 합니다 (.H) 파일입니다. DECLARE_INTERFACE_MAP 를 사용 하 여 클래스 구현 파일에 인터페이스 지도 정의 해야 합니다 (.CPP) BEGIN_INTERFACE_MAP 및 END_INTERFACE_MAP 매크로(&N)。
BEGIN_INTERFACE_PART 및 END_INTERFACE_PART-매크로 설명
BEGIN_INTERFACE_PART (localClass, iface);
END_INTERFACE_PART (localClass)
localClass
인터페이스를 구현 하는 클래스의 이름
iface
이 클래스를 구현 하는 인터페이스의 이름
메모nbsp;??클래스는 구현 하는 각 인터페이스에 대 한 BEGIN_INTERFACE_PART 및 END_INTERFACE_PART 쌍을가지고 해야 합니다. 이러한 매크로 뿐만 아니라 해당 클래스의 포함 된 멤버 변수를 정의 하는 OLE 인터페이스에서 파생 되는 로컬 클래스를 정의 합니다. AddRef, 릴리스및 QueryInterface 멤버는 자동으로 선언 됩니다. 구현 되는 인터페이스의 일부인 다른 멤버 함수에 대 한 선언을 포함 해야 합니다 (해당 선언 BEGIN_INTERFACE_PART 및 END_INTERFACE_PART 매크로 사이 배치 됩니다)(&N)。
Iface 인수가 IAdviseSink또는 IPersistStorage (또는 당신의 자신의 사용자 정의 인터페이스)와 같은 구현 하고자 하는 OLE 인터페이스。
LocalClass 인수는 정의 됩니다 로컬 클래스의 이름입니다. ' X' 앞 자동으로 이름에 추가 됩니다. 이 명명 규칙은 동일한 이름의 전역 클래스와 충돌을 피하기 위해 사용 됩니다. 또한, 그것을 제외 하 고 localClass 이름와 같은 포함 된 멤버의 이름은 'm_x'에 의해 접두사가。
예를 들어:
BEGIN_INTERFACE_PART (MyAdviseSink, IAdviseSink)
nbsp; STDMETHOD_(void,OnDataChange) (LPFORMATETC, LPSTGMEDIUM);
? STDMETHOD_(void,OnViewChange) (DWORD, 긴);
? STDMETHOD_(void,OnRename)(LPMONIKER);
? STDMETHOD_(void,OnSave)();
? STDMETHOD_(void,OnClose)();
END_INTERFACE_PART(MyAdviseSink)(&N)
iAdviseSink에서 파생 된 XMyAdviseSink 라는 로컬 클래스를 정의 하 고 선언 하는 클래스의 멤버가 호출 m_xMyAdviseSink.Note:
메모nbsp;STDMETHOD_ 와 함께 시작 하는 줄에서 OLE2 본질적으로 복사 됩니다.H와 약간 수정 합니다. Ole2에서 그들을 복사 합니다.H는 해결 하기 어려운 오류를 줄일 수 있습니다(&N).
BEGIN_INTERFACE_MAP 및 END_INTERFACE_MAP-매크로 설명
BEGIN_INTERFACE_MAP (클래스, baseClass)
END_INTERFACE_MAP
클래스
인터페이스 맵을 정의 하는 클래스
baseClass
클래스 에서 파생 되는 클래스。
설명: BEGIN_INTERFACE_MAP 및 END_INTERFACE_MAP 매크로 실제로 인터페이스 맵을 정의 구현 파일에 사용 됩니다. 구현 되는 각 인터페이스에 대 한 하나 이상의 INTERFACE_PART 매크로 호출입니다. 클래스를 사용 하 여 각 집계에 대 한 거기에 하나의 INTERFACE_AGGREGATE 매크로 호출。
INTERFACE_PART-매크로 설명
INTERFACE_PART (클래스, iid, localClass)
클래스
인터페이스 지도 포함 하는 클래스의 이름。
iid
IID 포함된 하는 클래스에 매핑할 수 있는。
localClass
('X')이 로컬 클래스의 이름
메모nbsp;??이 매크로 BEGIN_INTERFACE_MAP 매크로 END_INTERFACE_MAP 매크로 사이 개체 지 각 인터페이스에 대해 사용 됩니다. 있는 IID 클래스 및 localClass에서 지정 된 클래스의 멤버에 매핑할 수 있습니다. 'M_x' localClass 에 자동으로 추가 됩니다. 참고 하나 이상의 IID 단일 멤버와 연결 될 수 있습니다. 만 "가장 파생 된" 인터페이스를 구현 하는 모든 중간 인터페이스 뿐만 아니라 제공 하고자 하는 경우에 매우 유용 합니다. 이것의 좋은 예로 IOleInPlaceFrameWindow 인터페이스입니다. 계층 구조는 다음과 같이(&N):
IUnknown
nbsp;? IOleWindow
?????? IOleUIWindow
?????????? IOleInPlaceFrameWindow(&N)
클라이언트 개체 IOleInPlaceFrameWindow를 구현 하는 경우 이러한 인터페이스에서 QueryInterface 될 수 있습니다: IOleUIWindow, IOleWindow또는 IUnknown"가장 파생된" 인터페이스 IOleInPlaceFrameWindow (실제로 구현 하는 하나) 외. 이 처리 하려면 IOleInPlaceFrameWindow 인터페이스를 각각의 모든 기본 인터페이스를 매핑할 하나 이상의 INTERFACE_PART 매크로 사용할 수 있습니다.
클래스 정의 파일:
BEGIN_INTERFACE_PART (CMyFrameWindow, IOleInPlaceFrameWindow)
클래스 구현 파일에:
BEGIN_INTERFACE_MAP (CMyWnd, CFrameWnd)
nbsp;? INTERFACE_PART (CMyWnd, IID_IOleWindow, MyFrameWindow)
?? INTERFACE_PART (CMyWnd, IID_IOleUIWindow, MyFrameWindow)
?? INTERFACE_PART (CMyWnd, IID_IOleInPlaceFrameWindow, MyFrameWindow)
END_INTERFACE_MAP(&N)
그것은 항상 필요 이후 프레임 워크 Iunknown의 돌。
INTERFACE_PART-매크로 설명
INTERFACE_AGGREGATE (클래스, theAggr)
클래스
인터페이스 지도 포함 하는 클래스의 이름,
theAggr
집계 하는 멤버 변수의 이름。
메모nbsp;??이 매크로 게 프레임 워크 클래스는 집계 개체를 사용 하는 데 사용 됩니다. 그것은 BEGIN_INTERFACE_PART 및 END_INTERFACE_PART 매크로 사이 나타나야 합니다. 집계 개체는 IUnknown에서 파생 된 별도 개체가입니다. 집계와 INTERFACE_AGGREGATE 매크로 사용 하 여 집계 지원 나타나는 개체에서 직접 지원 되는 모든 인터페이스를 만들 수 있습니다. TheAggr 인수는 단순히 (직접 또는 간접적으로) IUnknown 에서 파생 된 클래스의 멤버 변수 이름입니다. 모든 INTERFACE_AGGREGATE 매크로 INTERFACE_PART 매크로 인터페이스 지도에 배치 하는 경우 따라야 합니다(&N).
기술 노트 번호로 |nbsp; 카테고리별 기술 노트(&N)