TN038: mfc/ole IUnknown uygulaması

Ole 2 kalbinde "ole bileşen nesne modeli", ya da com. com tanımlayan standart bir başkasına nasıl işbirliği nesneleri için iletişim. Bu yöntem bir nesne üzerinde nasıl gönderilir gibi gibi ne bir "nesne" görünüyor ayrıntılarını içerir. com da tüm com uyumlu sınıfları türetildiği bir temel sınıf tanımlar. IUnknownbu temel sınıftır. com IUnknown arayüzü bir c++ sınıf olarak adlandırılır, ancak herhangi bir dile özgü değildir — c, pascal ya da bir com nesnesinin ikili düzen destekleyebilen başka bir dil uygulanabilir.

Ole "arabirimleri" IUnknown türetilmiş tüm sınıflar gösterir IUnknown ile uygulaması taşıdığı gibi bu bir "arabirim" önemli bir fark olduğunu. Sadece, bu uygulamaları ne değil belirli özelliklerini nesneleri tarafından kurduğu iletişim kuralı tanımlar. Bu makul için maksimum esneklik sağlayan bir sistem. mfc/C++ programları için varsayılan davranışı uygulamak için MFC'ın işi olduğunu.

IUnknown MFC'ın uygulanması anlamak için öncelikle bu arabirimi nedir anlamak gerekir. IUnknown basitleştirilmiş bir sürümünü aşağıda tanımlanan:

 iU&nknown sınıfı
{
public:
 nbsp;  Sanal hresult QueryInterface(REFIID iid, void** ppvObj) = 0;
    Sanal ulong AddRef() = 0;
    Sanal ulong Release() = 0;
}

&Notnbsp;  Bu örnek için __stdcall gibi bazı gerekli arama kuralı ayrıntılarını bırakılır.

Nesnenin bellek yönetimi AddRef ve yayın üye işlevleri kontrol. com nesneleri izlemek için bir başvuru sayma düzeni kullanır. Bir nesneyi hiçbir zaman başvurulan doğrudan C++'da olduğu gibi. Bunun yerine, com nesneleri her zaman bir işaretçi ile başvurulur. Sahibi bitince nesneyi serbest bırakmak için bunu kullanarak, nesnenin üye serbest (operatörü silmek, geleneksel bir c++ nesnesi için yapılması olarak kullanarak farklı olarak) denir. Yönetilecek tek bir nesneye birden çok başvuru mekanizması sayım başvuru sağlar. Nesne bir başvuru sayısı AddRef ve yayın uygulaması korur —, referans sayımı sıfıra kadar nesne silinmez.

AddRef ve serbest bir uygulama açısından oldukça basit. İşte önemsiz bir uygulama:

Ulo&ng CMyObj::AddRef() {nbsp;  dönüş ++ m_dwRef; 
}

ulong CMyObj::Release() {If (--m_dwRef == 0) {}
        Bu silme; 
        return 0;
    }
    return m_dwRef;
}

QueryInterface üye işlevi biraz daha ilginç. Tahmin edebileceğiniz gibi bir nesne olan tek üye işlevleri olan AddRef ve serbest bırakmak çok ilginç değil — IUnknown sağladığından daha fazla şeyler yapmak için nesne anlatmak için güzel olacaktır. Burada QueryInterface yararlı olmasıdır. Aynı nesne üzerinde farklı bir "arabirim" elde sağlar. Bu arabirimlere genellikle IUnknown türetilmiştir ve yeni üye işlevleri ekleyerek ek işlevsellik ekleyebilirsiniz. com arabirimleri hiç üye değişkenleri arabirimde bildirilen ve tüm üye işlevler saf-sanal olarak bildirilir. Örneğin,

iPri&ntInterface sınıfı: ortak IUnknown
{
public:
 nbsp;  Virtual void PrintObject() = 0;
}

Yalnızca bir IUnknownvarsa, bir IPrintInterface almak için IPrintInterface, IID kullanılarak IUnknown::QueryInterface diyoruz. Bir IID arabirimi benzersiz olarak tanımlayan 128-bit bir sayıdır. Siz veya ole tanımlamak her arabirim için bir IID yoktur. PUnk bir IUnknown nesneye bir işaretçi ise, bir IPrintInterface ondan almak için kod olabilir

IPrintInterface * pPrint = null;
Eğer (pUnk-gt;QueryInterface(IID_IPrintInterface, (void**) & pPrint) noerror ==)
{
    pPrint - > PrintObject();
    pPrint - > Release();   
        / / Yayın işaretçi QueryInterface elde edilen
}

Oldukça kolay görünüyor, ama nasıl hem IPrintInterface hem de IUnknown arayüzü destekleyen bir nesne uygulamak? IPrintInterface doğrudan IUnknown türetilmiştir çünkü bu durumda basittir — IPrintInterface uygulayarak, IUnknown otomatik olarak desteklenir. Örneğin:

 cPri&ntObj sınıfı: Genel CPrintInterface
{
 nbsp;  Sanal hresult QueryInterface(REFIID iid, void** ppvObj);
    Sanal ulong AddRef();
    Sanal ulong Release();
    Virtual void PrintObject();
}

AddRef ve sürüm uygulamaları tam olarak aynı olan yukarıdaki uygulamaya olurdu. CPrintObj::QueryInterface bu şöyle

Hresult CPrintObj::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
 nbsp;  Eğer (IID IID_IUnknown == || IID == IID_IPrintInterface)
    {
        * ppvObj = bu;
        AddRef();
        noerror dönmek;
    }
    return ResultFromScode(E_&NOINTERFACE);
}

Arabirim tanımlayıcısı (IID) tanınırsa, gördüğünüz gibi bir işaretçi nesnenize döndürülür; Aksi takdirde hata oluşur. Ayrıca Not başarılı bir QueryInterface bir zımni AddRefiçinde sonuçlanır. Tabii ki, size de CEditObj::Printuygulamaya olurdu. Bu basit çünkü IPrintInterface doğrudan IUnknown arayüzü elde edildi. Eğer iki farklı arabirim IUnknown, türetilmiş her ikisi de destek istedim ancak aşağıdakileri göz önünde bulundurun

iEditI&nterface sınıfı: Genel IUnkown
{
public:
 nbsp;  Virtual void EditObject() = 0;
}

Olmasına rağmen birkaç farklı yolla hem IEditInterface hem de IPrintInterface c++ kullanarak birden çok devralma dahil olmak üzere, destekleyen bir sınıf bu notu bu işlevi uygulamak için iç içe geçmiş sınıflarının kullanımı üzerinde odaklanacaktır.

sı&nıf CEditPrintObj
{
public:
 nbsp;  CEditPrintObj();

hresult QueryInterface(REFIID iid, void**);
    ulong AddRef();
    ulong Release();
    dword m_dwRef;

CPrintObj sınıfı: Genel IPrintInterface
    {
    public:
        CEditPrintObj * m_pParent;
        Sanal hresult QueryInterface(REFIID iid, void** ppvObj);
        Sanal ulong AddRef();
        Sanal ulong Release();
    } m_printObj;

CEditObj sınıfı: Genel IEditInterface
    {
    public:
        CEditPrintObj * m_pParent;
        Sanal ulong QueryInterface(REFIID iid, void** ppvObj);
        Sanal ulong AddRef();
        Sanal ulong Release();
    } m_editObj;
}

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

CEditPrintObj::CEditPrintObj()
{
 nbsp;  m_editObj.m_pParent = bu;
    m_printObj.m_pParent = bu;
}

ulong CEditPrintObj::AddRef() {return ++ m_dwRef;
}

CEditPrintObj::Release()
{
    Eğer (--m_dwRef == 0)
    {
        Bu silme;
        return 0;
    }
    return m_dwRef;
}

hresult CEditPrintObj::QueryInterface(REFIID iid, void** ppvObj)
{
    Eğer (IID IID_IUnknown == || IID == IID_IPrintInterface)
    {
        * ppvObj = & m_printObj;
        AddRef();
        noerror dönmek;
    }
    else if (IID == IID_IEditInterface)
    {
        * ppvObj = & m_editObj;
        AddRef();
        noerror dönmek;
    }
    return ResultFromScode(E_NOINTERFACE);
}

ulong CEditPrintObj::CEditObj::AddRef() {return m_pParent - > AddRef(); 
}

ulong CEditPrintObj::CEditObj::Release() {m_pParent - dön > 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() {m_pParent - dön > Release(); 
}

hresult CEditPrintObj::CPrintObj::QueryInterface)
    REFIID IID, void ** ppvObj) {return m_pParent - > QueryInterface (IID, ppvObj); 
}

IUnknown uygulanması en dikkat CEditPrintObj::CEditObj ve CEditPrintObj::CPrintObj kod çoğaltmak yerine, CEditPrintObj sınıfa yerleştirilir. Bu kod miktarını azaltır ve hataları önler. Burada önemli nokta IUnknown arayüzü herhangi bir arabirim nesnesinin desteklemiyor olabilir almak için QueryInterface çağrısı mümkün olduğunu ve bu arabirimlerin her birinden aynı yapmak mümkündür. Bu, tüm QueryInterface işlevleri kullanılabilir her arayüzü aynı şekilde davranmak gerekir anlamına gelir. Sırayla uygulanması "dış nesne" aramak bu katıştırılmış nesneler, arka-işaretçi kullanılan (m_pParent) ' dir. M_pParent işaretçi CEditPrintObj kurucu sırasında başlatıldı. Ardından CEditPrintObj::CPrintObj::PrintObject ve CEditPrintObj::CEditObj::EditObject de uygulamak. Bir şekil eklemek için kodu biraz eklendi — nesne düzenleme yeteneğini. Neyse ki, (olmasına rağmen) yalnızca tek bir üye işlev arabirimler için oldukça nadir görülür ve bu durumda, EditObject ve PrintObject genellikle tek bir arabirim kombine.

Bir açıklama ve bir çok basit bir senaryo için kod olmasıdır. mfc/ole sınıflar, basit bir alternatif sunar. mfc uygulaması bir benzer şekilde Windows iletilerini sarılmış ileti haritalar kullanmaktadır. Bu tesis Arabirimi haritalar denir ve bir sonraki bölümde açıklanan.

Mfc arabirimi Maps

Mfc/ole kavramı ve yürütme "Arabirimi Haritalar" MFC'ın "Mesajı Haritalar" ve "Gönderme Haritalar" benzer bir uygulama içerir. MFC's arayüz haritaların temel özellikleri şunlardır:

Ayrıca, aşağıdaki gelişmiş özellikleri arabirimi haritalar destek:

Toplama hakkında daha fazla bilgi için bkz: ole Programcı Başvurusu.

MFC'ın arabirimi harita desteği CCmdTarget sınıfında yatmaktadır. CCmdTarget "olan bir" başvuru (referans sayımı örneğin ise CCmdTargetiçinde) IUnknown uygulanması ile ilişkili tüm üye işlevleri yanı sıra sayısı. ole com destekleyen bir sınıf oluşturmak için CCmdTarget bir sınıf türetmek ve çeşitli makroları kullanmak yanı sıra üye fonksiyonları istenen arabirimlerini CCmdTarget . MFC'ın uygulanması Yuvalanmış sınıfları her arabirim uygulaması gibi yukarıdaki örnek tanımlamak için kullanır. Bu IUnknown yanı sıra bazı yinelenen kodun ortadan makroları bir dizi standart bir uygulama ile daha kolay yapılır.

Arabirim göster temelleri

MFC'ın arabirimini kullanarak bir sınıf haritalar şu adımları izleyin.:

  1. Bir sınıf doğrudan veya dolaylı olarak elde CCmdTarget.

  2. Türetilmiş sınıf tanımında DECLARE_INTERFACE_MAP işlevini kullanın.

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

  4. Uygulama dosyasında sınıfın arabirim göster tanımlamak için BEGIN_INTERFACE_MAP ve END_INTERFACE_MAP makroları kullanın.

  5. Desteklenen her IID için belirli bir sınıf "parçası" Bu IID eşlemek için BEGIN_INTERFACE_MAP ve END_INTERFACE_MAP makroları arasındaki INTERFACE_PART makro kullanma.

  6. Size destek arabirimleri temsil Yuvalanmış sınıfları uygulamak.

  7. Üst CCmdTargeterişmek için method_prologue makroyu kullanmak-nesne elde.

  8. AddRef, yayınve QueryInterface bu işlevler (ExternalAddRef, ExternalReleaseve ExternalQueryInterface) CCmdTarget uygulanması için temsilci seçebilirsiniz.

Yukarıdaki CPrintEditObj örnek aşağıdaki gibi uygulanabilir:

cPrintEditObj sınıfı: Genel CCmdTarget
{
public:
 nbsp;  / / buraya üye veri ve üye işlevleri için CPrintEditObj gitmek

/ / Arabirim Maps
Korumalı:
    DECLARE_I&NTERFACE_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 beyanı CCmdTargettüretilmiş bir sınıf oluşturur. DECLARE_INTERFACE_MAP makro çerçeve, bu sınıf özel arabirim göster olacak söyler. Ayrıca, BEGIN_INTERFACE_PART ve END_INTERFACE_PART makroları Yuvalanmış sınıfları, bu durumda adları CEditObj ve CPrintObj (x yalnızca Yuvalanmış sınıfları "c" ile başlamak küresel sınıfları ve "Ben" başlangıç arabirimi sınıfları ayırt etmek için kullanılır) tanımlayın. İç içe iki üyesi bu sınıflar oluşturulur: m_CEditObj ve m_CPrintObj, sırasıyla. Makrolar otomatik olarak AddRef, yayınve QueryInterface işlevlerini bildirmek; Bu nedenle sadece işlevleri bu arabirime özgü bildirdiğiniz: EditObject ve PrintObject ( STDMETHOD's ole makro kullanılır gibi _stdcall ve sanal anahtar kelimeler hedef platformuna uygun olarak sağlanır böylece).

Bu sınıf için arabirim göster uygulamak için:

BEGI&N_INTERFACE_MAP (CPrintEditObj, CCmdTarget)
 nbsp;  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 ile sırasıyla bağlar. QueryInterface (CCmdTarget::ExternalQueryInterface) CCmdTarget uygulanması bu harita m_CPrintObj ve istendiğinde m_CEditObj işaretçiler dönmek için kullanır. IID_IUnknowniçin bir girdi eklemek gerekli değildir; Çerçeve (Bu durumda m_CPrintObj) harita ilk arabirimin kullanacağı zaman IID_IUnknown istenen.

BEGIN_INTERFACE_PART makro otomatik olarak AddRef, yayın ve QueryInterface işlevleri için bildirilmiş olsa da, hala onları uygulamak için gerekir:

Ulong kadar ihracat CEditPrintObj::XEditObj::AddRef()
{
 nbsp;  method_prologue (CEditPrintObj, EditObj)
    dönüş pThis - > ExternalAddRef();
}

ulong kadar ihracat CEditPrintObj::XEditObj::Release()
{
    method_prologue (CEditPrintObj, EditObj)
    dönüş pThis - > ExternalRelease();
}

hresult kadar ihracat CEditPrintObj::XEditObj::QueryInterface ((İngilizce)
    REFIID IID, void far far ** ppvObj)
{
    method_prologue (CEditPrintObj, EditObj)
    dönmek (hresult) pThis - > ExternalQueryInterface (& IID, ppvObj);
}

void far verme CEditPrintObj::XEditObj::EditObject()
{
    method_prologue (CEditPrintObj, EditObj)
    / / "Düzenle" kodu nesne, ne demektir...
}

Uygulanması için CEditPrintObj::CPrintObj, CEditPrintObj::CEditObj yukarıdaki tanımları benzer olacaktır. (Gerçek şu ki, daha önce mfc/ole gelişiminde bu durumda idi), bu işlevleri otomatik olarak oluşturmak için kullanılabilecek bir makro oluşturmak mümkün olacaktır, ancak makro kodu birden fazla satırı oluşturduğunda, kesme noktaları ayarlamak için zor olur. Bu nedenle, bu kodu elle genişletilir.

İleti çerçeve uygulaması kullanarak haritalar orada bir şeyler yapmak için gerekli değildi vardır:

Ayrıca çerçeve ileti haritalar dahili olarak kullanır. Bir çerçeve sınıfından türetmek böylece COleServerDoczaten belirli arabirimleri destekleyen ve değişiklik veya eklemeleri çerçevesi tarafından sağlanan arabirimleri sağlar, söylüyorlar. Bu çerçeve tamamen arabirim göster temel sınıftan devralınmasını destekler aslında etkin — yani neden BEGIN_INTERFACE_MAP , temel sınıf adı için ikinci parametresi olarak alır nedeni.

&Notnbsp;  Genellikle devralan mfc sürümünden bu arabirimin katıştırılmış uzmanlık tarafından MFC'ın yerleşik uygulamaları ole arabirimleri uygulaması yeniden kullanmak mümkün değildir. Bu mümkün değil çünkü içeren CCmdTargeterişmek için method_prologue makro kullanımı-türetilen nesne anlamına gelir bir uzaklık sabit CCmdTargetkatıştırılmış nesne-nesne türetilmiş. Bu, örneğin, XAdviseSink belirli bir uzaklık COleClientItem nesnesinin üst varlık üzerinde olduğundan gelen COleClientItem::XAdviseSink, MFC'ın uygulanmasında bir katıştırılmış XMyAdviseSink türetilemez demektir.

Ancak, mfc uygulanması için tüm MFC'ın varsayılan davranışı istediğiniz işlevleri için verebilirsiniz. Bu IOleInPlaceFrame (XOleInPlaceFrame) mfc uygulaması (o temsilci m_xOleInPlaceUIWindow birçok işlevleri için) COleFrameHook sınıfındaki yapılır. Bu tasarım, birçok arabirimleri uygulayan nesneler çalışma boyutunu azaltmak için seçildi; (önceki bölümde yol m_pParent kullanıldığı gibi) geri işaretçi gereksinimini ortadan kaldırır.

Toplama ve arabirim haritalar

Mfc, tek başına com nesnelerini destekleyen ek olarak, toplama'i de destekler. Toplama kendisi burada tartışmak için çok karmaşık bir konudur; toplama hakkında daha fazla bilgi için ole Programcı Başvurusu bakın. Bu notu sadece destek için toplama çerçevesi ve arabirim haritalar inşa anlatacağız.

Toplama kullanmanın iki yolu vardır: (1) kullanarak bir com nesnesinin Toplama destekleyen ve (2) uygulama başka bir tarafından toplanan nesne. Bu yetenekler "toplama nesne kullanma" ve "nesne araya toplanabilir yapma" olarak için belirtilebilir. mfc her ikisini de destekler.

Toplama nesne kullanma

Toplama nesne toplama QueryInterface mekanizması içine kravat için bir yol var gerekir kullanmak için. Diğer bir deyişle, nesne doğal bir parçası sanki toplama nesne davranması gerekir. Peki MFC'ın arabirim göster mekanizması bu kravat nedir? Burada bir iç içe nesneyi bir IID için eşleştirilir, INTERFACE_PART makro yanı sıra, toplama nesne CCmdTarget türetilmiş sınıfınızda bir parçası olarak bildirebilirsiniz. Bunu yapmak için INTERFACE_AGGREGATE makro kullanılır. Bu sayede hangi arabirim göster mekanizması entegre olması için (bir IUnknown işaretçisi olmalı veya türetilmiş sınıf) bir üye değişkeni belirtin. CCmdTarget::ExternalQueryInterface çağrıldığında işaretçi null değilse, çerçeve otomatik olarak toplama nesnenin QueryInterface üye işlevi çağırır, IID istenirse, bir CCmdTarget nesnesi tarafından desteklenen yerel IIDs değil.

INTERFACE_AGGREGATE makro kullanmak için aşağıdaki adımları izleyin.:

  1. Toplama nesne işaretçisi içeren bir üye değişken (bir IUnknown *).

  2. Üye değişken adıyla başvuran arabirimi harita, bir INTERFACE_AGGREGATE makrosu ekleyin.

  3. (Genellikle CCmdTarget::OnCreateAggregatessırasında) bazı noktada, üye değişkeni null dışında bir şey başlatmak.

Örneğin,

cAggrExample sınıfı: Genel CCmdTarget
{
public:
 nbsp;  CAggrExample();

Korumalı:
    lpunknown m_lpAggrInner;
    Virtual bool OnCreateAggregates();

DECLARE_INTERFACE_MAP()
    / / "doğal" arabirimi bölümü makrolar buraya kullanılabilir
};

CAggrExample::CAggrExample()
{
    m_lpAggrInner = null;
}

bool CAggrExample::OnCreateAggregates()
{
    / / Tel toplama doğru kontrol bilinmeyen ile
    m_lpAggrInner (CLSID_Example, CoCreateInstance =
        GetControllingUnknown(), CLSCTX_INPROC_SERVER,
        IID_IUnknown, (LPVOID *) & m_lpAggrInner);
    Eğer (m_lpAggrInner == null)
        return false;
    / / İsteğe bağlı olarak diğer toplama nesneleri oluşturma
    true döndürür;
}

BEGIN_INTERFACE_MAP (CAggrExample, CCmdTarget)
    / / yerli "INTERFACE_PART" girdileri buraya gitmek
    INTERFACE_AGGREGATE (CAggrExample, m_lpAggrInner)
END_INTERFACE_MAP()

m_lpAggrInnerNULL Oluşturucu başlatılır. Çerçeve QueryInterfacevarsayılan uygulanması bir null üye değişkeni göz ardı eder. OnCreateAggregates , aslında senin toplama nesneleri oluşturmak için iyi bir yerdir. COleObjectFactorymfc uygulaması dışında bir nesne oluşturuyorsanız açıkça aramak gerekecek. Bir araya toplanabilir nesneleri oluşturma ele CCmdTarget::OnCreateAggregates yanı sıra CCmdTarget::GetControllingUnknown kullanımını toplamları oluşturma nedenini belirgin olacaktır.

Bu teknik, nesne toplama nesne Yerel arabirimleri destekler arabirimlerinin tümünü verecektir. Yalnızca bir alt toplam destekleyen arabirimlerinin istiyorsanız, CCmdTarget::GetInterfaceHookgeçersiz kılabilirsiniz. Bu sayede çok düşük düzeyde hookability, için QueryInterfacebenzer. Genellikle, istediğiniz toplam destekleyen tüm arabirimleri.

Nesne uygulaması araya toplanabilir hale

Bir nesne araya toplanabilir olması için bir "kontrol bilinmeyen." AddRef, yayınve QueryInterface uygulanması temsilci gerekir Diğer bir deyişle, o nesnenin bir parçası olmak, o AddRef, yayınve QueryInterface da IUnknowntüretilen farklı bir nesneye temsilci gerekir. Bu "kontrol bilinmeyen" oluşturulduğunda, nesne için o COleObjectFactoryuygulanması için sağlanan sağlanmıştır. Bu uygulama küçük bir miktar yük taşır ve mfc bu isteğe bağlı kılan bazı durumlarda arzu, değildir. CCmdTarget::EnableAggregation nesnenin Oluşturucu--dan aramak araya toplanabilir olması bir nesneyi etkinleştirmek için.

Nesne toplamları da kullanıyorsa, da doğru aktardığınızdan emin olmanız gerekir "kontrol bilinmeyen" toplama nesneleri. Genellikle toplam oluşturulduğunda bu IUnknown işaretçisi nesnesine aktarylyr. Örneğin, CoCreateInstanceile oluşturulan nesneler için "kontrol bilinmeyen" pUnkOuter parametresidir. CCmdTarget::GetControllingUnknownarayarak doğru "Bilinmeyen kontrol" işaretçi alınabilir. Bu işlevden döndürülen değer ancak kurucunun sırasında geçerli değil. Bu nedenle, bu CCmdTarget::OnCreateAggregates GetControllingUnknown gelen bir dönüş değeri COleObjectFactory uygulanması oluşturmuş bile güvenilir olduğu, geçersiz kılma olarak sadece sizin toplamları oluşturun önerilmektedir.

Nesneyi eklerken veya yapay başvuru sayıları bırakmadan doğru başvuru sayısı yönetmek önemlidir. Bu durumda emin olmak için her zaman ExternalAddRef ve ExternalRelease InternalRelease ve InternalAddRefyerine diyoruz. Toplama destekleyen bir sınıf InternalRelease veya InternalAddRef çağrısı nadir.

Başvuru malzemeleri

Kendi arabirimleri tanımlama veya çerçeve'nın uygulama ole arabirimleri geçersiz kılma gibi ole, Gelişmiş kullanımı temel arabirim göster mekanizması gerektirmesi.

Bu bölümde, her makro ve bu gelişmiş özellikleri uygulamak için kullanılan API'leri açıklanmaktadır.

CCmdTarget::EnableAggregation — İşlev tanımlama

void EnableAggregation();

&Notnbsp;  Bu tür nesneleri için ole toplama desteklemek isterseniz bu işlevi türetilmiş sınıf kurucusu içinde arayın. Bu bir araya toplanabilir nesneleri için gereken özel bir IUnknown uygulama hazırlar.

CCmdTarget::ExternalQueryInterface — İşlev tanımlama

dword ExternalQueryInterface (const void far * lpIID, LPVOID far * ppvObj);

lpIID

Bir IID (ilk bağımsız değişkeni için QueryInterface) uzak bir işaretçi

ppvObj

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

&Notnbsp;  Bu işlev, IUnknown uygulanmasında her arabirim için sınıf çağrısı uygular. Bu işlev, nesnenin arabirimi haritada dayalı QueryInterface standart veri güdümlü uygulanması sağlar. Dönüş değeri için bir hresult oyuncular gereklidir. Nesne birikir, bu işlev "IUnknown" Yerel arabirim Haritayı kullanarak yerine arayacak.

CCmdTarget::ExternalAddRef — İşlev tanımlama

dword ExternalAddRef();

&Notnbsp;  Bu işlev, IUnknown::AddRef uygulanmasında her arabirim için sınıf çağrısı uygular. Dönüş değeri yeni başvuru CCmdTarget nesne sayısıdır. Nesne birikir, bu işlev "IUnknown" Yerel başvuru sayısı işleme yerine arayacak.

CCmdTarget::ExternalRelease — İşlev tanımlama

Dword ExternalRelease();

&Notnbsp;  Bu işlev, IUnknown::Release uygulanmasında her arabirim için sınıf çağrısı uygular. Dönüş değeri, nesne üzerinde yeni başvuru sayısını gösterir. Nesne birikir, bu işlev "IUnknown" Yerel başvuru sayısı işleme yerine arayacak.

DECLARE_INTERFACE_MAP — Makronun açıklama

DECLARE_INTERFACE_MAP

&Notnbsp;  Bu makro bir arabirim göster olacak CCmdTarget türetilmiş herhangi bir sınıf kullanın. Çok da declare_message_mapaynı şekilde kullanılır. Bu makroyu çağırma sınıf tanımında, genellikle bir başlık olarak yerleştirilmesi (.h) dosyası. DECLARE_INTERFACE_MAP bir sınıf arabirimi harita uygulaması dosyayı tanımlamanız gerekir (.cpp) BEGIN_INTERFACE_MAP ve END_INTERFACE_MAP makrolar.

BEGIN_INTERFACE_PART ve END_INTERFACE_PART — makro tanımları

BEGIN_INTERFACE_PART (localClass, iface);

END_INTERFACE_PART (localClass)

localClass

Arabirim uygulayan sınıf adı

iface

Bu sınıf uygulayan arabirimin adı

&Notnbsp;  Sınıf uygulayan her arabirim için bir BEGIN_INTERFACE_PART ve END_INTERFACE_PART çifti olması gerekir. Bu makrolar, o sınıfın bir 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ınve QueryInterface üyeleri otomatik olarak bildirilir. Uygulanmakta olan arabiriminin bir parçası olan diğer üye işlevleri için bildirimleri eklemeniz gerekir (Bu tanımlamalar arasında BEGIN_INTERFACE_PART ve END_INTERFACE_PART makrolar yerleştirilir).

İface bağımsız, IAdviseSink, veya IPersistStorage (veya kendi özel arabirimi gibi) uygulamak istediğiniz ole arabirimidir.

LocalClass bağımsız değişkeni tanımlanacaktır Yerel Sınıf adıdır. ' x' otomatik olarak adının önüne. Bu isimlendirme, küresel sınıfları aynı adı ile çakışmaları önlemek için kullanılır. Ayrıca gömülü üye, bunun dışında localClass adıyla aynı adı 'm_x tarafından' öneki.

Örneğin:

BEGI&N_INTERFACE_PART (MyAdviseSink, IAdviseSink)
 nbsp; STDMETHOD_(void,OnDataChange) (lpformatetc, LPSTGMEDIUM);
   STDMETHOD_(void,OnViewChange) (dword, uzun);
   STDMETHOD_(void,OnRename)(LPMONIKER);
   STDMETHOD_(void,OnSave)();
   STDMETHOD_(void,OnClose)();
END_INTERFACE_PART(MyAdviseSink)

iAdviseSink elde edilen XMyAdviseSink adlı bir yerel sınıf tanımlamak istiyorsunuz ve m_xMyAdviseSink.Note içinde bildirildi?i sınıfının bir üyesi olarak:

&Notnbsp;stdmethod_ ile başlayan satırlar, esasen OLE2 kopyalanır.S ve biraz değiştirilmiş. OLE2 kopyalayarak.H çözmek zor hataları azaltabilir.

BEGIN_INTERFACE_MAP ve END_INTERFACE_MAP — makro tanımları

BEGIN_INTERFACE_MAP (ardından, AnaSınıf)

END_INTERFACE_MAP

ardından

Arabirim göster tanımlanması olduğu sınıf

anaSınıf

Ardından gelen türetir içinden sınıf.

Sözleri: BEGIN_INTERFACE_MAP ve END_INTERFACE_MAP makrolar uygulama dosyasında aslında arabirimi harita tanımlamak için kullanılır. Uygulanan her arabirim için bir veya daha fazla INTERFACE_PART makro çağırmaları yoktur. Sınıfın kullandığı her toplama için orada bir INTERFACE_AGGREGATE Makroyu çağırma.

INTERFACE_PART — Makronun açıklama

INTERFACE_PART (ardından, IID, localClass)

ardından

Arabirim göster içeren sınıfın adı.

iid

Katıştırılmış sınıfına eşlenecek olan IID.

localClass

(Daha az ' x') Yerel Sınıf adı

&Notnbsp;  Bu makro END_INTERFACE_MAP makro arasında BEGIN_INTERFACE_MAP makro nesneniz destekleyecek her arabirim için kullanılır. Ardından ve localClasstarafından belirtilen sınıf üyesi bir IID eşleştirmenize olanak verir. 'M_x' localClass için otomatik olarak eklenir. Not Birden fazla IID tek bir üye ile ilişkili olabilir. Sadece bir "en türetilen" arabirimini uygulayan ve tüm ara arabirimleri de sağlamak istiyorsanız bu seçenek çok kullanışlıdır. Bu iyi bir örnek IOleInPlaceFrameWindow arabirimdir. Onun hiyerarşisi şuna:

IU&nknown
 nbsp;  IOleWindow
        IOleUIWindow
            IOleInPlaceFrameWindow

IOleInPlaceFrameWindowbir nesneyi uygular, bir istemci bu arabirimlerin hiçbirinde QueryInterface olabilir: IOleUIWindow, IOleWindowya da IUnknown, yanı sıra "en türetilen" arabirim IOleInPlaceFrameWindow (bir uygulama aslında). Ele almak birden fazla INTERFACE_PART makro her temel arabirim göster IOleInPlaceFrameWindow arabirimini kullanarak

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

BEGIN_INTERFACE_PART (CMyFrameWindow, IOleInPlaceFrameWindow)

sınıf uygulama dosya:

BEGI&N_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

Çerçeve IUnknown çünkü her zaman gerekli ilgilenir.

INTERFACE_PART — Makronun açıklama

INTERFACE_AGGREGATE (ardından, theAggr)

ardından

Arabirim göster içeren sınıfın adı,

theAggr

Toplanması için üye değişkeni adı.

&Notnbsp;  Bu makro çerçeve sınıf toplama nesne kullandığını anlatmak için kullanılır. BEGIN_INTERFACE_PART ve END_INTERFACE_PART makrolar arasında yer almalıdır. IUnknowntüretilmiş, ayrı bir nesne toplama bir nesnedir. Toplama ve INTERFACE_AGGREGATE makrosunu kullanarak, nesne tarafından doğrudan desteklenen toplam destekler görünen tüm arabirimleri yapabilirsiniz. TheAggr bağımsız değişkeni sadece IUnknown (doğrudan ya da dolaylı olarak) elde edilen sınıf üye değişken adıdır. Tüm INTERFACE_AGGREGATE makroları bir arabirim göster yerleştirildiğinde INTERFACE_PART makroları izlemelisiniz.

Teknik notlar numarasına göre |nbsp; Teknik notlar kategorisine göre

Index