Aracılığıyla paylaş


TN038: mfc/ole IUnknown uygulaması

[!NOT]

İlk çevrimiçi belgelerinde yer almıştır beri aşağıdaki teknik Not güncelleştirilmedi.Sonuç olarak bazı yordamlar ve konuları eski veya yanlış.En son bilgiler için çevrimiçi belgelere dizini ilgilendiğiniz konu aramak önerilir.

ole 2 at "ole bileşen nesne modeli" veya COM kalbidircom tanımlayan standart nasıl almasına nesneler için birbiriyle iletişim kurması.Bu, ne bir "nesne", yöntem bir nesne üzerinde nasıl gönderilir gibi benzer ayrıntılarını içerir.com, ayrıca tüm com uyumlu Sınıf türetilmiş bir temel sınıf tanımlar.Bu temel sınıfı olan IUnknown.Ancak IUnknown arabirimi C++ sınıf olarak denir, com herhangi bir dile özgü değildir — c, pascal veya bir com nesnesinin ikili Düzen destekleyen herhangi bir dil uygulanabilir.

ole gösterir türetilen tüm sınıflar IUnknown "arabirim" olarak Bu önemli bir ayrım "arabirim" bu yana gibi olan IUnknown birlikte taşıyan uygulaması yok.Basitçe, protokolü olarak nesneleri iletişim, değil, bu uygulamaları ne özellikleri tanımlar.En yüksek esneklik için izin veren bir sistem için makul.MFC'ın işini mfc/C++ programları için varsayılan davranışı uygulamak için var.

MFC'ın uygulaması anlamak için IUnknown bu arabirimi nedir önce anlamanız gerekir.Basitleştirilmiş bir sürümünü IUnknown aşağıda tanımlanmıştır:

class IUnknown
{
public:
    virtual HRESULT QueryInterface(REFIID iid, void** ppvObj) = 0;
    virtual ULONG AddRef() = 0;
    virtual ULONG Release() = 0;
};

[!NOT]

Gibi bazı gerekli çağırma kuralı ayrıntıları __stdcall için bu resimde sol.

AddRef Ve yayın üye işlevleri kontrol nesnenin bellek yönetimi.com nesneleri izlemek için başvuru sayım düzenini kullanır.Bir nesneyi hiçbir zaman başvurulan doğrudan C++'da olduğu gibi.Bunun yerine, com nesneleri, işaretçi her zaman başvurulur.Nesne sahibi bitince serbest bırakmak onun, nesne kullanarak serbest üye olarak adlandırılır (işleç silme için geleneksel bir C++ nesnesi yapılması gibi kullanmanın aksine).Yönetilecek tek bir nesneye birden çok başvuru mekanizması sayım başvuru sağlar.Uygulaması AddRef ve yayın nesneye başvuru sayımı tutar — kendi başvuru sayısı sıfır ulaşıncaya kadar nesne silinmez.

AddRefve yayın uygulama açısından oldukça açık olan.Önemsiz bir uygulama şöyledir:

ULONG CMyObj::AddRef() 
{ 
    return ++m_dwRef; 
}

ULONG CMyObj::Release() 
{ 
    if (--m_dwRef == 0) 
    {
        delete this; 
        return 0;
    }
    return m_dwRef;
}

QueryInterface Üye işlevi biraz daha ilginç.Nesneyi, yalnızca üye işlevleri çok ilginç değil AddRef ve yayın — çok daha fazla şeyler yapmak için nesne bildirmek iyi olur IUnknown sağlar.Burası QueryInterface yararlıdır.Farklı bir "arabirim" aynı nesne üzerinde elde sağlar.Bu arabirimler, genellikle türetilmiştir IUnknown ve yeni üye işlevleri ekleyerek ek işlevsellik ekleyebilirsiniz.com arabirimleri asla arabirimde bildirilen üye değişkenlerine sahiptir ve tüm üye işlevlerini saf sanal olarak bildirilir.Örnek:

class IPrintInterface : public IUnknown
{
public:
    virtual void PrintObject() = 0;
};

Almak için bir IPrintInterface yalnızca varsa, bir IUnknown, çağrı IUnknown::QueryInterface kullanarak IID , IPrintInterface.Bir IID arabirimi benzersiz olarak tanımlayan bir 128-bit sayısıdır.Var olan bir IID , ya da ole tanımlamak her arabirim için.PUnk bir işaretçi bir IUnknown nesnesi, kodu almak için bir IPrintInterface karşı olabilir:

IPrintInterface* pPrint = NULL;
if (pUnk->QueryInterface(IID_IPrintInterface, 
    (void**)&pPrint) == NOERROR)
{
    pPrint->PrintObject();
    pPrint->Release();   
        // release pointer obtained via QueryInterface
}

Oldukça kolay görünüyor, ama nasıl, çözümü destekleyen iki IPrintInterface bir nesneyi ve IUnknown arabirimi?IPrintInterface doğrudan türetilmiş olduğundan bu durumda basittir IUnknown — IPrintInterface, uygulayarak IUnknown otomatik olarak desteklenir.Örne?in:

class CPrintObj : public CPrintInterface
{
    virtual HRESULT QueryInterface(REFIID iid, void** ppvObj);
    virtual ULONG AddRef();
    virtual ULONG Release();
    virtual void PrintObject();
};

Uygulamaları AddRef ve yayın tam olarak aynı uygulanan bu yukarıdaki olacaktır.CPrintObj::QueryInterface şöyle görünecektir:

HRESULT CPrintObj::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
    if (iid == IID_IUnknown || iid == IID_IPrintInterface)
    {
        *ppvObj = this;
        AddRef();
        return NOERROR;
    }
    return E_NOINTERFACE;
}

Varsa, gördüğünüz gibi arabirim tanımlayıcısı (IID) ise tanınan, nesneniz için; işaretçisi döndürülür Aksi takdirde hata oluşur.Ayrıca, Not başarılı bir QueryInterface sonuçları örtülü bir AddRef.Tabii ki, aynı zamanda uygulamak zorunda CEditObj::Print.Basit olan çünkü IPrintInterface doğrudan türetilen IUnknown arabirimi.İki farklı arabirimlerini destekleyen isteseydiniz, ancak her ikisi de türetilen IUnknown, aşağıdakileri dikkate alın:

class IEditInterface : public IUnkown
{
public:
    virtual void EditObject() = 0;
};

Her ikisi de destekleyen bir sınıf uygulamak için farklı yollarla olsa IEditInterface ve IPrintInterfacedahil olmak üzere birden çok devralma C++ kullanarak, bu notu bu işlevi uygulamak için iç içe geçmiş sınıfları kullanımı üzerinde odaklanacaktır.

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;
};

Tüm uygulama aşağıda yer almaktadır:

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); 
}

Çoğunun fark IUnknown uygulaması içine yerleştirilmiş CEditPrintObj CEditPrintObj::CEditObj ve CEditPrintObj::CPrintObj kodda çoğaltma yerine sınıf.Bu kod miktarını azaltır ve hataları önler.Nokta burada IUnknown arabirimden, çağrı mümkün olmasıdır QueryInterface herhangi bir arabirim almak için nesne destekleyebilir ve her bu arayüzler aynı yapmak mümkündür.Yani tüm QueryInterface her arabiriminden kullanılabilir işlevler aynı şekilde davranır gerekir.Bu katıştırılmış nesnelerin dış içinde "nesne" uygulamasını çağırmak sırayla geri işaretçi kullanılan (m_pParent) ' dir.M_pParent işaretçi sırasında CEditPrintObj yapıcı başlatıldı.Daha sonra CEditPrintObj::CPrintObj::PrintObject ve CEditPrintObj::CEditObj::EditObject de uygulaması geliştirirsiniz.Bir özellik eklemek için oldukça biraz kod eklendi — nesne düzenleme yeteneğini.Neyse ki (durum olsa da) yalnızca tek bir üye işlev arabirimler için oldukça seyrek ve bu durumda, EditObject ve PrintObject genellikle tek bir arabirim içinde birleştirilebilir.

Çok sayıda açıklama ve lot kodu basit bir senaryo için olmasıdır.mfc/ole sınıfı daha kolay bir alternatif sağlar.mfc Uygulaması iletisi haritaları ile benzer şekilde Windows iletilerini kaydırılan bir teknik kullanır.Bu tesis adlı Arabirimi haritalar ve sonraki bölümde ele alınmıştır.

mfc arabirimi eşlemeleri

mfc/ole uygulaması "Arabirim haritaları" MFC'ın "İletisi haritaları" ve "Dağıtma eşlemi" benzer kavramı ve yürütme içerir.MFC's arabirimi eşlemelerin temel özellikleri şunlardır:

  • Standart uygulaması, IUnknown, yerleşik CCmdTarget sınıfı.

  • Başvuru sayısının değiştiren Bakım AddRef ve Release

  • Veri uygulaması kullananQueryInterface

Buna ek olarak, arabirim haritalar aşağıdaki gelişmiş özellikleri destekler:

  • Bir araya toplanabilir com nesneleri oluşturma desteği

  • Bir com nesnesinin uygulamasında toplama nesneleri kullanma desteği

  • Uygulama hookable ve genişletilebilir.

Toplama hakkında daha fazla bilgi için bkz: ole Programmer's Reference.

MFC'ın arabirimi harita desteği de kökü CCmdTarget sınıfı.CCmdTarget"olan bir" başvuru sayısı gibi tüm üye işlevleri ile ilişkili IUnknown uygulaması (örneğin, başvuru sayısı ise CCmdTarget).ole COM'u destekleyen bir sınıf oluşturmak için bir sınıf türetin. CCmdTarget ve çeşitli makroları üye işlevlerin yanı CCmdTarget istenen arabirim uygulamak için.MFC'ın uygulama yuvalanmış sınıfları çok Yukarıdaki örnekte olduğu gibi her arabirim geliþtirmesi tanımlamak için kullanır.IUnknown yanı sıra bazı yinelenen kod ortadan makroları sayısı standart uygulama ile daha kolay yapılır.

MFC'ın arabirimini kullanarak sınıf uygulamak için eşleştirir.

  1. Arasında doğrudan veya dolaylı olarak bir sınıf türetmek CCmdTarget.

  2. Use DECLARE_INTERFACE_MAP türetilmiş sınıf tanımında işlevi.

  3. Desteklemek istediğiniz her arabirim için kullanmak BEGIN_INTERFACE_PART ve END_INTERFACE_PART sınıf tanımında makrolar.

  4. Uygulama dosyasındaki BEGIN_INTERFACE_MAP ve END_INTERFACE_MAP sınıfın arabirim haritası tanımlamak için makrolar.

  5. Desteklenen her IID için kullanmak INTERFACE_PART arasında makro BEGIN_INTERFACE_MAP ve END_INTERFACE_MAP , IID belirli bir "bölümü" sınıfının eşlemek için makrolar.

  6. Her sınıfın desteklediğiniz arabirimleri temsil eden iç içe uygular.

  7. Use METHOD_PROLOGUE üst erişmek için makro CCmdTarget-nesne türetilmiş.

  8. AddRef, Yayın, ve QueryInterface için temsilci CCmdTarget bu işlevlerin uygulanması (ExternalAddRef, ExternalRelease, ve ExternalQueryInterface).

Yukarıdaki CPrintEditObj örnek gibi uygulanabilir:

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)
};

Yukarıdaki bildirimi türetilen bir sınıfı oluşturur CCmdTarget.DECLARE_INTERFACE_MAP makro çerçeve Bu sınıf özel arabirim haritası olduğunu söyler.Buna ek olarak, BEGIN_INTERFACE_PART ve END_INTERFACE_PART makroları tanımlamak yuvalanmış sınıfları, bu durumda adları CEditObj ve CPrintObj (x yalnızca Başlat "I" ile "c" ve arabirim sınıfları ile başlatacak genel sınıflardan yuvalanmış sınıfları ayırt etmek için kullanılır).Bu sınıfların iç içe iki üyesi oluşturulur: m_CEditObj ve m_CPrintObj, sırasıyla.Makrolar otomatik olarak bildirmek AddRef, yayın, ve QueryInterface işlev görür; Bu nedenle, yalnızca işlevleri Bu arabirime özgü bildirin: EditObject ve PrintObject (ole makro stdmethod olduğu gibi kullanılan böylece _stdcall ve sanal anahtar sözcükler hedef platformu için uygun sağlanır).

Bu sınıfın arabirim eşlemesi uygulamak için:

BEGIN_INTERFACE_MAP(CPrintEditObj, CCmdTarget)
    INTERFACE_PART(CPrintEditObj, IID_IPrintInterface, PrintObj)
    INTERFACE_PART(CPrintEditObj, IID_IEditInterface, EditObj)
END_INTERFACE_MAP()

Bu IID_IPrintInterface IID m_CPrintObj ve IID_IEditInterface ile m_CEditObj sırasıyla bağlar.CCmdTarget Uygulaması QueryInterface (CCmdTarget::ExternalQueryInterface) m_CPrintObj ve istendiğinde m_CEditObj işaretçiler döndürmek bu harita kullanır.Bir giriş gerekli değil IID_IUnknown; framework Haritası (Bu durumda m_CPrintObj) ilk arabirim kullandığınızda IID_IUnknown istendi.

Bile BEGIN_INTERFACE_PART otomatik olarak bildirilen makro AddRef, yayın ve QueryInterface işlevleri, yine de bunları uygulamak için gereksinim duyduğunuz:

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, bir uygulama olacak yukarıdaki tanımları CEditPrintObj::CEditObj benzer.Bu işlevler otomatik olarak oluşturmak için kullanılan bir makro oluşturmak mümkün olacaktır (ancak önceki mfc/ole geliştirmede bu durumda olduğu halde) makro kodunun birden çok satırı oluşturduğunda, kesme noktaları ayarlamak zor olur.Bu nedenle, bu kodu el ile genişletildi.

İleti eşlemeleri uygulanışı kullanarak gerekli olmayan şeylerin sayısı vardır:

  • QueryInterface uygulamak

  • Implement AddRef ve yayın

  • Bu yerleşik yöntemlerin hem Arabirimlerinizden bildirmek

Buna ek olarak, çerçeve ileti eşlemeleri dahili olarak kullanır.Bu sayede deyin framework sınıfından türetmek COleServerDoc, zaten belirli arabirimleri destekler ve değişiklik veya eklemeleri çerçevesi tarafından sağlanan arabirimleri sağlar.Bu framework tam olarak destekleyen gerçeğiyle etkin devralarak temel bir sınıf arabirimi eşlemesinden — neden neden olan BEGIN_INTERFACE_MAP temel sınıf adını, ikinci parametre olarak alır.

[!NOT]

Genellikle MFC'ın yerleşik uygulamaları tarafından ole arabirimleri uygulaması yeniden mümkün değildir devralarak mfc sürümünden bu arabirimin katıştırılmış uzmanlığı.Mümkün değil çünkü kullanımı METHOD_PROLOGUE makro içeren erişim elde etmek için CCmdTarget-türetilen nesne anlaşılacağı bir uzaklık sabit , katıştırılmış nesneden CCmdTarget-türetilen nesne.Bunun anlamı, örneğin, katıştırılmış bir XMyAdviseSink MFC'ın uygulamasında gelen türetilemez COleClientItem::XAdviseSink, XAdviseSink üstünden belirli uzaklığında olan edeceğinden, COleClientItem nesnesi.

[!NOT]

Ancak, tüm MFC'ın varsayılan davranışı istediğiniz işlevlerin mfc uygulaması için atayabilirler.Bu mfc uygulaması yapılır IOleInPlaceFrame (XOleInPlaceFrame), COleFrameHook sınıfı (onu temsilci için birçok işlevi için m_xOleInPlaceUIWindow).Bu tasarım, çalışma zamanı birçok arabirimleri uygulayan nesnelerinin boyutunu küçültmek için seçildi; (önceki bölümde yol m_pParent kullanılmış gibi) geri işaretçi gereksinimini ortadan kaldırır.

5hhehwba.collapse_all(tr-tr,VS.110).gifToplama ve arabirim eşlemeleri

Tek başına com nesnelerini destekleyen ek olarak mfc toplama de destekler.Toplama kendisini burada tartışmak için çok karmaşık bir konu olduğunu; bakın ole Programmer's Reference toplama hakkında daha fazla bilgi için.Bu not sadece toplama çerçevesi ve arabirim haritalar yerleşik desteği anlatılacaktır.

Toplama kullanmanın iki yolu vardır: (1) kullanarak toplama destekleyen bir com nesnesi ve (2) uygulama başka tarafından toplanan bir nesne.Bu yetenekleri için "toplama nesne kullanma" ve "bir nesneyi bir araya toplanabilir yapma" olarak da görülebilir.mfc her ikisini de destekler.

5hhehwba.collapse_all(tr-tr,VS.110).gifToplama nesne kullanma

Bir toplama nesne var. bazı yolu QueryInterface mekanizması içine toplama bağlamanız gerekiyor kullanmak için.Diğer bir deyişle, nesneniz doğal bir parçası olarak rağmen toplama nesne davranır olmalıdır.Peki bu bağ MFC'ın arabirimi eşleme mekanizması mi?Ek olarak INTERFACE_PART makro iç içe nesne eşlenen bir IID için burada, de bildirdiğiniz toplama nesnenin bir parçası olarak, CCmdTarget türetilmiş sınıf.Bunu yapmak için INTERFACE_AGGREGATE makro kullanılır.Bu sayede üye değişkeni belirtmek (bir işaretçi olması, bir IUnknown veya türetilmiş sınıf), olduğu arabirimi eşleme mekanizması entegre için.İşaretçi null olduğunda değil, CCmdTarget::ExternalQueryInterface olan adlı çerçeve otomatik olarak toplama nesnenin çağıracaktır QueryInterface , üye işlev IID istenen yerel biri değil IIDtarafından desteklenen s CCmdTarget nesnesinin kendisi.

INTERFACE_AGGREGATE makro kullanma

  1. Üye değişkeni bildirmek (bir IUnknown *), toplama nesne işaretçisini yuvarlanmışsa.

  2. İçeren bir INTERFACE_AGGREGATE adıyla üye değişkene göndermede arabirimi haritanızda makro.

  3. Belirli bir noktada (genellikle sırasında CCmdTarget::OnCreateAggregates), üye değişkeni null dışında bir şey için başlatılamıyor.

Örne?in:

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 yapıcısına başlatıldı.Framework varsayılan uygulamasında null üye değişkeni yok sayacak QueryInterface.OnCreateAggregates , aslında toplama nesneleri oluşturmak için uygun bir yerdir.mfc uygulaması dışında nesne oluşturuyorsanız, açıkça çağırmak sahip COleObjectFactory.İçinde aggregates oluşturma nedenini CCmdTarget::OnCreateAggregates yanı sıra kullanımı CCmdTarget::GetControllingUnknown bir araya toplanabilir nesneleri oluşturma ele belirgin haline gelir.

Bu teknik nesneniz toplama nesne yerel arabirimleri destekleyen arabirimlerinin tümünü sunar.Yalnızca bir alt kümesini destekleyen toplama arabirimleri istiyorsanız, geçersiz CCmdTarget::GetInterfaceHook.Böylece çok düşük düzeyli hookability benzer QueryInterface.Genellikle, toplama destekleyen tüm arabirimler için istediğiniz.

5hhehwba.collapse_all(tr-tr,VS.110).gifNesne uygulaması bir araya toplanabilir hale getirme

Bir araya toplanabilir, olacak bir nesne uygulaması için AddRef, yayın, ve QueryInterface bir "denetleme bilinmeyen için" temsilci gerekir Diğer bir deyişle, bu nesnenin bir parçası olarak, temsilci gerekir AddRef, yayın, ve QueryInterface farklı bir nesneye aynı zamanda türetilen IUnknown.Sağlanan oluşturulduğunda, nesne, bu uygulaması, sağlanan bu "denetleme" Bilinmiyor COleObjectFactory.Bu uygulama, az miktarda bir ek yük taşıyan ve mfc bu isteğe bağlı hale getirir, böylece bazı durumlarda arzu, değildir.Bir araya toplanabilir olması nesneyi etkinleştirmek için arama CCmdTarget::EnableAggregation nesnenin yapıcısını dan.

Nesne aggregates de kullanıyorsa, ayrıca doğru aktardığınızdan emin olmanız gerekir "denetleme Bilinmeyen" olarak toplama nesneleri.Genellikle bu IUnknown toplama oluşturulduğunda, işaretçiyi nesnesine iletilir.Örneğin, pUnkOuter parametresi "denetleme" ile oluşturulan nesneler için bilinmiyor CoCreateInstance.Doğru "Bilinmeyen denetleme" işaretçi çağırarak alınabilir CCmdTarget::GetControllingUnknown.Bu işlev döndürülen değer ancak kurucu sırasında geçerli değil.Bu nedenle, yalnızca geçersiz sizin aggregates oluşturma önerilir CCmdTarget::OnCreateAggregates, dönüş değeri arasında burada GetControllingUnknown oluşturulan bile güvenilir olduğunu COleObjectFactory uygulaması.

Nesneyi eklerken veya yapay başvuru sayıları serbest doğru başvuru sayısı denetlemek önemlidir.Bu durumda olduğundan emin olmak için her zaman arama ExternalAddRef ve ExternalRelease yerine InternalRelease ve InternalAddRef.Çağrı nadir InternalRelease veya InternalAddRef destekleyen toplama sınıfı.

5hhehwba.collapse_all(tr-tr,VS.110).gifBaşvuru malzemeleri

ole, ole arabirimlerinin framework'ün uygulama geçersiz kılma ya da kendi arabirimleri tanımlama gibi gelişmiş kullanımı temel arabirim eşleme mekanizması kullanımını gerektirir.

Her makro ve bu gelişmiş özellikleri uygulamak için kullanılan API'ları bu bölümde anlatılmaktadır.

5hhehwba.collapse_all(tr-tr,VS.110).gifCCmdTarget::EnableAggregation — İşlev açıklama

void EnableAggregation();

Notlar

Nesne türü için ole toplama desteklemek isterseniz, türetilmiş sınıf kurucusu içinde bu işlevini çağırın.Bu, bir araya toplanabilir nesneler için gerekli olan özel bir IUnknown uygulaması hazırlar.

5hhehwba.collapse_all(tr-tr,VS.110).gifCCmdTarget::ExternalQueryInterface — İşlev açıklama

DWORD ExternalQueryInterface( 
   const void FAR* lpIID, 
   LPVOID FAR* ppvObj 
);

Notlar

5hhehwba.collapse_all(tr-tr,VS.110).gifParametreler

  • lpIID
    İşaretçi bir IID (ilk bağımsız değişken için QueryInterface) far

  • ppvObj
    Bir işaretçi bir IUnknown * (ikinci bağımsız değişkeni için QueryInterface)

Notlar

Bu işlev her arabirim için sınıfınızın IUnknown uygulamanızda çağrı uygular.Bu işlev, nesnenin arabirimi haritanın QueryInterface standart verilere uygulaması sağlar.Dönüş değeri için hresult artığını gereklidir.Nesne toplanan, yerel arabirim eşleme kullanmak yerine "IUnknown" Bu işlevi çağıracaktır.

5hhehwba.collapse_all(tr-tr,VS.110).gifCCmdTarget::ExternalAddRef — İşlev açıklama

DWORD ExternalAddRef();

Notlar

Bu işlev IUnknown::AddRef uygulamanızda her arabirim için sınıfınızın çağrısı uygular.Yeni başvuru sayısı CCmdTarget nesnesinde dönüş değeridir.Nesne toplanır, bu işlevi yerine yerel başvuru sayısı işleme "IUnknown" çağıracaktır.

5hhehwba.collapse_all(tr-tr,VS.110).gifCCmdTarget::ExternalRelease — İşlev açıklama

DWORD ExternalRelease();

Notlar

Bu işlev IUnknown::Release uygulamanızda her arabirim için sınıfınızın çağrısı uygular.Dönüş değeri, nesne üzerinde yeni başvuru sayısı gösterir.Nesne toplanır, bu işlevi yerine yerel başvuru sayısı işleme "IUnknown" çağıracaktır.

5hhehwba.collapse_all(tr-tr,VS.110).gifDECLARE_INTERFACE_MAP — Makro tanımı

DECLARE_INTERFACE_MAP

Notlar

Türetilen herhangi bir sınıfında Bu makroyu kullanmak CCmdTarget arabirimi haritası sahip.Aynı şekilde çok kullanılan DECLARE_MESSAGE_MAP.Bu makroyu çağırma sınıf tanımında, genellikle bir başlık olarak yerleştirilmesi (.h) dosyası.Bir sınıf DECLARE_INTERFACE_MAP uygulama dosyasında arabirimi eşleme tanımlamalısınız (.cpp) ile BEGIN_INTERFACE_MAP ve END_INTERFACE_MAP makrolar.

5hhehwba.collapse_all(tr-tr,VS.110).gifBEGIN_INTERFACE_PART ve END_INTERFACE_PART — makro tanımları

BEGIN_INTERFACE_PART( 
   localClass,
   iface 
);
END_INTERFACE_PART( 
   localClass 
)

Notlar

5hhehwba.collapse_all(tr-tr,VS.110).gifParametreler

  • localClass
    Arabirim uygulayan sınıf adı

  • iface
    Bu sınıf uygulayan arabirimin adı

Notlar

Sınıfınızın uygulayan her arabirim için olması gereken bir BEGIN_INTERFACE_PART ve END_INTERFACE_PART çifti.Bu makrolar, o sınıfın katıştırılmış üye değişkeni olarak tanımlayan ole arabirimi türetilen yerel bir sınıf tanımlayın.AddRef, Yayın, ve QueryInterface üyesi bildirilen otomatik olarak.Uygulanan arabiriminin bir parçası olan üye işlevler için bildirimleri eklemeniz gerekir (Bu bildirimleri intranetiniz arasında BEGIN_INTERFACE_PART ve END_INTERFACE_PART makrolar).

İface gibi uygulamak istediğiniz ole arabirim olmayan bağımsız değişken IAdviseSink, veya IPersistStorage (veya kendi özel arabirim).

LocalClass bağımsız değişkeni tanımlı yerel sınıf adıdır.' x' adı e otomatik olarak.Bu adlandırma genel sınıflarıyla aynı adı çakışmaları önlemek için kullanılır.Buna ek olarak, gömülü, üyenin aynı adı localClass 'm_x' konduğundan dışında bir ad.

Örne?in:

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 türetilmiş XMyAdviseSink adlı yerel bir sınıf tanımlamak ve m_xMyAdviseSink.Note bildirilmiş sınıfının üyesi olarak adlandırılır:

[!NOT]

İle başlayan satırları stdmethod_ aslında OLE2 kopyalanır.H ve biraz değiştirilmiş.OLE2 kopyalayarak.H gidermek zor hataları azaltabilirsiniz.

5hhehwba.collapse_all(tr-tr,VS.110).gifBEGIN_INTERFACE_MAP ve END_INTERFACE_MAP — makro tanımları

BEGIN_INTERFACE_MAP( 
   theClass,
   baseClass 
)
END_INTERFACE_MAP

Notlar

5hhehwba.collapse_all(tr-tr,VS.110).gifParametreler

  • theClass
    Arabirim eşleme tanımlanmış olduğu sınıf

  • baseClass
    Hangi sınıftan theClass türetildiği.

Notlar

BEGIN_INTERFACE_MAP Ve END_INTERFACE_MAP makrolar uygulama dosyasında gerçekte eşleme arabirimi tanımlamak için kullanılır.Her arabirim için uygulanan var. bir veya daha fazla INTERFACE_PART makro çağırmaları.Sınıf kullanan her toplama var. biri INTERFACE_AGGREGATE makroyu çağırma.

5hhehwba.collapse_all(tr-tr,VS.110).gifINTERFACE_PART — Makro tanımı

INTERFACE_PART( 
   theClass,
   iid, 
   localClass 
)

Notlar

5hhehwba.collapse_all(tr-tr,VS.110).gifParametreler

  • theClass
    Arabirim eşlemeyi içeren sınıf adı.

  • iid
    IID olan katıştırılmış sınıfına eşlendi.

  • localClass
    (Daha az 'x') yerel sınıf adı.

Notlar

Bu makro arasında kullanılan BEGIN_INTERFACE_MAP makro ve END_INTERFACE_MAP her arabirim için makro nesneniz destekler.Belirtilen sınıf üyesi bir IID eşlemek verir theClass ve localClass.'m_x' için eklenen localClass otomatik olarak.Not birden fazla IID tek bir üye ile ilişkili olabilir.Sadece bir "en türetilen" arabirimini uygulayan ve aynı zamanda tüm ara arabirimleri sağlamak istiyorsanız, bu seçenek çok kullanışlıdır.Bunun iyi bir örneği IOleInPlaceFrameWindow arabirimi.Kendi hiyerarşisi şöyle görünür:

IUnknown
    IOleWindow
        IOleUIWindow
            IOleInPlaceFrameWindow

Uygulayan bir nesne, IOleInPlaceFrameWindow, istemci bir olabilir QueryInterface bu arabirimlerin hiçbirinde: IOleUIWindow, IOleWindow, veya IUnknown, "en türetilen" arabirimi yanı sıra IOleInPlaceFrameWindow , aslında uygulama (bir).İşlemek için birden fazla kullanabilirsiniz INTERFACE_PART için her temel arabirim eşlemek için makro IOleInPlaceFrameWindow arabirimi:

sınıf tanımı dosyası:

BEGIN_INTERFACE_PART(CMyFrameWindow, IOleInPlaceFrameWindow)

sınıf uygulama dosyası:

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

Framework alır IUnknown her zaman gerekli olduğundan dikkate.

5hhehwba.collapse_all(tr-tr,VS.110).gifINTERFACE_PART — Makro tanımı

INTERFACE_AGGREGATE( 
   theClass,
   theAggr 
)

Notlar

5hhehwba.collapse_all(tr-tr,VS.110).gifParametreler

  • theClass
    Arabirim eşlemeyi içeren sınıf adı

  • theAggr
    Toplanmasını üye değişkeninin adı.

Notlar

Bu makro, toplama nesne sınıfı kullanıyor framework bildirmek için kullanılır.Arasında yer almalıdır BEGIN_INTERFACE_PART ve END_INTERFACE_PART makrolar.Türetilen ayrı bir nesne toplama bir nesnesidir IUnknown.Kullanarak toplama ve INTERFACE_AGGREGATE makro görünen toplam destekler nesne tarafından doğrudan desteklenen tüm arabirimler yapabilirsiniz.TheAggr bağımsız değişken ise sadece üye değişkeni türetilir sınıfınızın adını IUnknown (doğrudan veya dolaylı olarak).Tüm INTERFACE_AGGREGATE makrolar gerekir izleyin INTERFACE_PART arabirimi haritada yerleştirildiğinde makrolar.

Ayrıca bkz.

Diğer Kaynaklar

Teknik notlar numarasına göre

Kategoriye göre teknik notlar