Aracılığıyla paylaş


TN065: ole otomasyon sunucuları ikili arabirim desteği

[!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.

Bu not, mfc tabanlı ole Otomasyonu sunucu uygulama ikili arabirim desteği ekleme açıklanır.acdual ikili arabirim desteği örnek göstermektedir ve bu notu örnek kodda acdual alınmıştır.Gibi bu notta açıklanan makroları DECLARE_DUAL_ERRORINFO, DUAL_ERRORINFO_PART, ve IMPLEMENT_DUAL_ERRORINFO, acdual örnek bir parçasıdır ve mfcdual içinde bulundu.H.

Çift arabirimleri

ole Otomasyonu çözümü sağlar, ancak bir IDispatch arabirimi, vtbl arabirimi veya (her ikisi de kapsayan) bir çift arabirimi Microsoft tüm ole Otomasyon nesneleri maruz için ikili arabirimleri uygulayan önerir.Çift arabirimleri üzerinden önemli avantajları olan IDispatch-yalnızca veya yalnızca vtbl arabirimler:

  • Bağlama yer alabilir, derleme zamanında vtbl arabirimi üzerinden veya çalışma zamanında IDispatch.

  • Performansı artırmak için vtbl arabirimini kullanan bir ole Otomasyon denetleyicileri yarar sağlayabilir.

  • Kullandığınız varolan ole Otomasyon denetleyicileri IDispatch arabirimi çalışmaya devam edecek.

  • vtbl arabirimi, C++ çağrı kolaydır.

  • Çift arabirimleri Visual Basic nesne desteği özellikleri ile uyumluluk için gereklidir.

CCmdTarget göre bir sınıfa ikili arabirim desteği ekleme

Çift arabirim aslında türetilen özel bir arabirim olduğunu IDispatch.İkili arabirim desteği uygulamak için en basit şekilde bir CCmdTarget-temel sınıftır normal gönderme, arabirim mfc ve ClassWizard kullanarak, sınıf ve daha sonra özel arabirim eklemek için ilk gerçekleştir.Çoðunlukla, özel arabirim uygulamanız yeterlidir geri mfc için temsilci IDispatch uygulaması.

İlk olarak, sunucunuz nesneleriniz için ikili arabirim tanımlamak için odl dosyasını değiştirin.Çift arabirim tanımlamak için bir arabirim deyimi yerine kullanmalısınız DISPINTERFACE Visual C++ sihirbazlar oluşturma deyimi.Varolan kaldırma yerine DISPINTERFACE deyimi, yeni bir arabirim deyimini ekleyin.Koruyarak tarafından DISPINTERFACE formunu devam ClassWizard, nesne özelliklerini ve yöntemlerini eklemek için kullanılacak, ancak arabirim deyiminiz eşdeğer özellikler ve yöntemler ekleyin.

Bir arabirim bildirimi için çift arabirim olmalıdır OLEAUTOMATION ve çift öznitelikleri ve arabirimi türetilmelidir dan IDispatch.Kullanabileceğiniz GUIDGEN oluşturmak için örnek bir IID ikili arabirim için:

[ uuid(0BDD0E81-0DD7-11cf-BBA8-444553540000), // IID_IDualAClick
   oleautomation,
   dual
]
interface IDualAClick : IDispatch
  {
  };

Yerinde arabirim bildirimi olduktan sonra girişleri yöntemleri ve özellikleri ekleme işlemini başlat.Çift arabirimler için yöntem ve özellik erişimcisi işlevleri çift arabirim dönmek için parametre listeleri düzenlemek gereken bir HRESULT ve dönüş değerleri özniteliklere sahip bir parametre olarak geçirmek [retval,out].Özellikler için hem de okuma eklemeniz gerektiğini unutmayın (propget) ve yazma (propput) erişim işlevi aynı kimliğe sahip.Örne?in:

[propput, id(1)] HRESULT text([in] BSTR newText);
[propget, id(1)] HRESULT text([out, retval] BSTR* retval);

Yöntemleri ve özellikleri tanımlanmış sonra coclass deyiminiz arabirim açıklamasına bir başvuru eklemeniz gerekir.Örne?in:

[ uuid(4B115281-32F0-11cf-AC85-444553540000) ]
coclass Document
{
   dispinterface IAClick;
   [default] interface IDualAClick;
};

odl dosyanızı güncelleştirilmiş bir kez nesne sınıfınızda bir çift arabirim uygulama sınıfı tanımlamak ve mfc kullanıcının ilgili girişleri MFC'ın arabirimi haritası mekanizmasını kullanmanız QueryInterface mekanizması.Tek bir giriş gerek INTERFACE_PART odl arabirim bildirimi her girişte ek dağıtma arabirimi girişleri engelleme.Her girişi odl propput adında bir işlev özniteliği gerekiyor put_propertyname.Her girişi propget adında bir işlev özniteliği gerekiyor get_propertyname.

Bir uygulama sınıfı, ikili arabirim tanımlamak için add bir DUAL_INTERFACE_PART bloğu, nesne sınıfı tanımlaması.Örne?in:

BEGIN_DUAL_INTERFACE_PART(DualAClick, IDualAClick)
  STDMETHOD(put_text)(THIS_ BSTR newText);
  STDMETHOD(get_text)(THIS_ BSTR FAR* retval);
  STDMETHOD(put_x)(THIS_ short newX);
  STDMETHOD(get_x)(THIS_ short FAR* retval);
  STDMETHOD(put_y)(THIS_ short newY);
  STDMETHOD(get_y)(THIS_ short FAR* retval);
  STDMETHOD(put_Position)(THIS_ IDualAutoClickPoint FAR* newPosition);
  STDMETHOD(get_Position)(THIS_ IDualAutoClickPoint FAR* FAR* retval);
  STDMETHOD(RefreshWindow)(THIS);
  STDMETHOD(SetAllProps)(THIS_ short x, short y, BSTR text);
  STDMETHOD(ShowWindow)(THIS);
END_DUAL_INTERFACE_PART(DualAClick)

mfc için 's çift arabirim bağlanmak için QueryInterface mekanizması, ekleme bir INTERFACE_PART arabirimi eşleme girdisi:

BEGIN_INTERFACE_MAP(CAutoClickDoc, CDocument)
  INTERFACE_PART(CAutoClickDoc, DIID_IAClick, Dispatch)
  INTERFACE_PART(CAutoClickDoc, IID_IDualAClick, DualAClick)
END_INTERFACE_MAP()

Ardından, arabirimi uygulamasında doldurmanız gerekir.Çoğunlukla, varolan mfc edebileceği olacağınızı IDispatch uygulaması.Örne?in:

STDMETHODIMP_(ULONG) CAutoClickDoc::XDualAClick::AddRef()
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CAutoClickDoc::XDualAClick::Release()
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   return pThis->ExternalRelease();
}
STDMETHODIMP CAutoClickDoc::XDualAClick::QueryInterface(
             REFIID iid, LPVOID* ppvObj)
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP CAutoClickDoc::XDualAClick::GetTypeInfoCount(
            UINT FAR* pctinfo)
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE);
   ASSERT(lpDispatch != NULL);
   return lpDispatch->GetTypeInfoCount(pctinfo);
}
STDMETHODIMP CAutoClickDoc::XDualAClick::GetTypeInfo(
          UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE);
   ASSERT(lpDispatch != NULL);
   return lpDispatch->GetTypeInfo(itinfo, lcid, pptinfo);
}
STDMETHODIMP CAutoClickDoc::XDualAClick::GetIDsOfNames(
       REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames,
       LCID lcid, DISPID FAR* rgdispid) 
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE);
   ASSERT(lpDispatch != NULL);
   return lpDispatch->GetIDsOfNames(riid, rgszNames, cNames, 
                                    lcid, rgdispid);
}
STDMETHODIMP CAutoClickDoc::XDualAClick::Invoke(
    DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
    DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult,
    EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr)
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE);
   ASSERT(lpDispatch != NULL);
   return lpDispatch->Invoke(dispidMember, riid, lcid,
                             wFlags, pdispparams, pvarResult,
                             pexcepinfo, puArgErr);
}

Sizin nesnesinin yöntem ve özellik erişimcisi işlevleri için uygulamasında doldurmanız gerekir.Yöntem ve özellik işlevleri geri ClassWizard kullanılarak oluşturulan yöntemler genellikle temsilci seçebilirsiniz.Ancak, değişkenleri doğrudan erişmek için özelliklerini ayarlama, get/değeri değişkene yerine kod yazmak gerekir.Örne?in:

STDMETHODIMP CAutoClickDoc::XDualAClick::put_text(BSTR newText)
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   // MFC automatically converts from Unicode BSTR to 
   // Ansi CString, if necessary...
   pThis->m_str = newText;
   return NOERROR;
}
STDMETHODIMP CAutoClickDoc::XDualAClick::get_text(BSTR* retval)
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   // MFC automatically converts from Ansi CString to 
   // Unicode BSTR, if necessary...
   pThis->m_str.SetSysString(retval);
   return NOERROR;
}

Geçirme ikili arabirim işaretçisi

İkili arabirim işaretçiyi geçirerek değil özellikle çağırmanız gerekiyorsa basit CCmdTarget::FromIDispatch.FromIDispatchmfc kullanıcının yalnızca çalışır IDispatch işaretçiler.Bu sorunu gidermek için tek yönlü olduğu özgün sorgu IDispatch işaretçiyi yukarı tarafından mfc ve gerekli işlevleri için işaretçiyi geçirmek.Örne?in:

STDMETHODIMP CAutoClickDoc::XDualAClick::put_Position(
      IDualAutoClickPoint FAR* newPosition)
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   LPDISPATCH lpDisp = NULL;
   newPosition->QueryInterface(IID_IDispatch, (LPVOID*)&lpDisp);
   pThis->SetPosition(lpDisp);
   lpDisp->Release();
   return NOERROR;
}

Geri ikili arabirim yöntemi aracılığıyla bir işaretçi geçirmeden önce mfc dönüştürmek gereksinim duyabileceğiniz IDispatch , çift arabirim işaretçisi için işaretçi.Örne?in:

STDMETHODIMP CAutoClickDoc::XDualAClick::get_Position(
      IDualAutoClickPoint FAR* FAR* retval)
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   LPDISPATCH lpDisp;
   lpDisp = pThis->GetPosition();
   lpDisp->QueryInterface(IID_IDualAutoClickPoint, (LPVOID*)retval);
   return NOERROR;
}

Uygulamanın tür kitaplığı kaydı

AppWizard kod sistemi ile bir ole Otomasyonu sunucu uygulamasının tür kitaplığı kaydı oluşturmaz.Diğer yolları tür kitaplığı kaydı sırasında her uygulama tek başına çalıştırdığınızda, ole türü bilgilerini, yani keserseniz tür kitaplığı kaydı uygulama uygundur.

Kaydetmek için her uygulamayı çalıştırdığınızda uygulamanın tür kitaplığı Standı tek başına:

  • afxctl içerir.H kendi standart üstbilgi dosyası stdafx içerir.Tanımına erişmek için h, AfxOleRegisterTypeLib işlevi.

  • Uygulamanızın, InitInstance işlev, bulmak için arama COleObjectFactory::UpdateRegistryAll.Bu çağrı ekleyin çağrısı AfxOleRegisterTypeLib, belirten Kitaplık Kimliği karşılık gelen türü kitaplığınızın adıyla birlikte, tür kitaplığı:

    // When a server application is launched stand-alone, it is a good idea
    // to update the system registry in case it has been damaged.
    m_server.UpdateRegistry(OAT_DISPATCH_OBJECT);
    COleObjectFactory::UpdateRegistryAll();
    // DUAL_SUPPORT_START
    // Make sure the type library is registered or dual interface won't work.
    AfxOleRegisterTypeLib(AfxGetInstanceHandle(), LIBID_ACDual, _T("AutoClik.TLB"));
    // DUAL_SUPPORT_END
    

Tür kitaplığı değişiklikler yapabilmek için proje oluşturma ayarlarını değiştirme

Projenin build ayarlarını değiştirmek için üstbilgi içeren dosyayı UUID tanımları, MkTypLib tarafından üretilir, her tür kitaplığı yeniden:

  1. Üzerinde Yapı menüsünde'ı ayarlarıve sonra odl her yapılandırma dosya listesinden seçin.

  2. Tıklatın ole türleri sekmesini ve dosya adını belirtmek Çıkış üstbilgisi dosyaadı alanı.Varolan dosyanın üzerine MkTypLib çünkü zaten projeniz tarafından kullanılmayan bir dosya adı kullanın.Tıklatın Tamam kapatmak için Build Settings iletişim kutusu.

Eklemek için UUID MkTypLib oluşturulan üstbilgi dosyasından projenize tanımları:

  1. MkTypLib üretilen dahil bilgisayarınızın standart üstbilgi dosyasında üstbilgi dosyası stdafx içerir.H.

  2. INITIIDS yeni bir dosya oluşturun.cpp ve projenize ekleyin.Bu dosyada, MkTypLib oluşturulan üstbilgi dosyası OLE2 sonra dahil.H ve INITGUID.Y:

    // initIIDs.c: defines IIDs for dual interfaces
    // This must not be built with precompiled header.
      #include <ole2.h>
      #include <initguid.h>
      #include "acdual.h"
    
  3. Üzerinde Yapı menüsünde'ı ayarlarıve INITIIDS'ı seçin.Her yapılandırma dosya listesinden cpp.

  4. Tıklatın C++ sekmesinde, kategori Derlemesi üstbilgilerive önceden derlenmiş üstbilgileri kullanmayan radyo düğmesi.Kapatmak için Tamam'ı Build Settings iletişim kutusu.

Tip Kitaplığı'nda doğru nesne sınıfı adı belirtme

Visual C++ ile yanlış sevk sihirbazlar uygulaması sınıf adı ole creatable sınıfları için sunucunun odl dosyasında coclass belirtmek için kullanın.Bu çalışma sırasında uygulama sınıf adı büyük olasılıkla kullanıcıların nesnenizin istediğiniz sınıf adı değil.Doğru adı belirtmek için odl dosyasını açın, her coclass ifadesini bulun ve uygulama sınıf adı doğru dış adla değiştirin.

Coclass deyimi değiştirildiğinde, değişken adları, Not CLSIDs MkTypLib oluşturulan üstbilgi dosyasında buna göre değiştirir.Yeni değişken adları kodunuzun güncelleştirmeniz gerekir.

Özel durumlar ve Otomasyon hatası arabirimleri

Özel durumlar, Otomasyon nesnesinin yöntem ve özellik erişimcisi işlevleri atabilir.Bu nedenle, ikili arabirim uygulamanızda onları işlemek ve denetleyici ole Otomasyonu hata işleme arabirimi aracılığıyla geri özel durum hakkında bilgi aktarmak IErrorInfo.Bu arabirim üzerinden hem de ayrıntılı, bağlamsal hata bilgilerini sağlar IDispatch ve vtbl arabirimleri.Hata işleyicisi, uygulamanız belirtmek için ISupportErrorInfo arabirimi.

Hata işleme mekanizmasını göstermek için ClassWizard üretilen standart gönderme desteği uygulamak için kullanılan işlevler istisna atar varsayalım.MFC'ın uygulaması IDispatch::Invoke genellikle bu özel durumlarý yakalar ve üzerinden dönen bir EXCEPTINFO yapısı dönüştürür Invoke çağırın.vtbl arabirimi kullanıldığında, ancak, size özel durumlarý kendinizi yakalamak için sorumludur.İkili arabirim yöntemleriniz koruma örnek:

STDMETHODIMP CAutoClickDoc::XDualAClick::put_text(BSTR newText)
{
   METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
   TRY_DUAL(IID_IDualAClick)
   {
      // MFC automatically converts from Unicode BSTR to 
      // Ansi CString, if necessary...
      pThis->m_str = newText;
      return NOERROR;
   }
   CATCH_ALL_DUAL
}

CATCH_ALL_DUALbir özel durum oluþtuðunda doğru hata kodunu döndürerek dikkate alır.CATCH_ALL_DUALole Otomasyonu hata işleme bilgileri kullanarak içine mfc istisna dönüştürür ICreateErrorInfo arabirimi.(Örnek CATCH_ALL_DUAL makro dosyası mfcdual olur.H acdual örnek.Onu çağıran işlev özel durumları işlemek için DualHandleException, mfcdual dosyasındadır.CPP.) CATCH_ALL_DUAL hata kodu oluştu özel durum türüne göre belirler:

  • COleDispatchException – bu durumda, HRESULT aşağıdaki kodu kullanarak oluşturulur:

    hr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 
                               (e->m_wCode + 0x200));
    

    Bu oluşturur bir HRESULT belirli bir özel duruma neden arabirimi.Hata kodu sistem tanımlı tüm çakışmaları önlemek için 0x200 tarafından Ofset HRESULTs standart ole arabirimler için.

  • CMemoryException – bu durumda, E_OUTOFMEMORY döndürülür.

  • Herhangi bir diğer durum – bu durumda E_UNEXPECTED döndürülür.

ole Otomasyon hatası tanıtıcısı kullanılır, ayrıca uygulamak belirtmek için ISupportErrorInfo arabirimi.

İlk olarak, kod desteklediği göstermek için Otomasyon sınıf tanımı eklemek ISupportErrorInfo.

İkinci kod ilişkilendirmek için Otomasyon sınıfının arabirimi harita ekleme ISupportErrorInfo MFC'ın uygulama sınıfla QueryInterface mekanizması.INTERFACE_PART Deyimi eşleşen için tanımlanan sınıf ISupportErrorInfo.

Son olarak desteklemek için tanımlanmış sınıf uygulamak ISupportErrorInfo.

( acdual örnek üç adımları yapmak yardımcı olacak üç makro içeriyor DECLARE_DUAL_ERRORINFO, DUAL_ERRORINFO_PART, ve IMPLEMENT_DUAL_ERRORINFO, mfcdual içerdiği tüm.H.)

Aşağıdaki örnek desteklemek için tanımlanmış bir sınıf uygulayan ISupportErrorInfo.CAutoClickDocOtomasyon sınıfınızın adını ve IID_IDualAClick olan IID ole Otomasyon hatası nesnesi bildirilen hataların kaynağını arabirim:

STDMETHODIMP_(ULONG) CAutoClickDoc::XSupportErrorInfo::AddRef() 
{
   METHOD_PROLOGUE(CAutoClickDoc, SupportErrorInfo) 
   return pThis->ExternalAddRef(); 
} 
STDMETHODIMP_(ULONG) CAutoClickDoc::XSupportErrorInfo::Release() 
{ 
   METHOD_PROLOGUE(CAutoClickDoc, SupportErrorInfo) 
   return pThis->ExternalRelease(); 
} 
STDMETHODIMP CAutoClickDoc::XSupportErrorInfo::QueryInterface( 
   REFIID iid, LPVOID* ppvObj) 
{ 
   METHOD_PROLOGUE(CAutoClickDoc, SupportErrorInfo) 
   return pThis->ExternalQueryInterface(&iid, ppvObj); 
} 
STDMETHODIMP CAutoClickDoc::XSupportErrorInfo::InterfaceSupportsErrorInfo( 
   REFIID iid) 
{ 
   METHOD_PROLOGUE(CAutoClickDoc, SupportErrorInfo) 
   return (iid == IID_IDualAClick) ? S_OK : S_FALSE; 
}

Ayrıca bkz.

Diğer Kaynaklar

Teknik notlar numarasına göre

Kategoriye göre teknik notlar