Bu Not, ole Otomasyonu mfc tabanlı sunucu uygulama ikili arabirim desteği ekleme anlatılmaktadır. acdual örneği göstermektedir ikili arabirim desteği ve bu notu örnek kodda acdual alınmıştır. Bu notta açıklandığı gibi makro DECLARE_DUAL_ERRORINFO , DUAL_ERRORINFO_PART , ve IMPLEMENT_DUAL_ERRORINFO , acdual örnek bir parçasıdır ve mfcdual bulunabilir.H.
Çift arabirimleri
Ole Otomasyonu bir IDispatch arabirimi, bir vtbl arabirimi ya da (ki ikisi de kapsayan) bir çift arabirim uygulamak sağlar ancak Microsoft tüm maruz Otomasyonu nesneler için ikili arabirim uygulamak önerir. İkili Arabirim IDispatchgöre önemli avantajlar var.-sadece veya salt vtbl arabirimleri:
CCmdTarget tabanlı bir sınıfa ikili arabirim desteği ekleme
Gerçekten sadece bir özel arabirim IDispatchtüretilmiş bir çift arabirimidir. Bir CCmdTargetiçinde ikili arabirim desteği uygulamanın en basit yolu-temel sınıftır normal gönderme arayüzü mfc ve ClassWizard kullanarak, sınıf, ardından özel arabirim sonradan ekleme ilk uygulamak için. Çoğunlukla, özel arabirim uygulamanız sadece geri mfc IDispatch uygulaması için temsilci.
İlk olarak, çift arabirimler, nesneler için tanımlamak sunucunuzun odl dosyasını değiştirin. Bir ç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 açıklamada, yeni bir arabirim deyimi ekleyin. İstinat tarafından DISPINTERFACE formu, sen devam edebilir ClassWizard özellikleri ve yöntemleri, nesneye eklemek için kullanın, ancak eşdeğer özellikleri ve yöntemleri, arayüz açıklamaya eklemelisiniz.
İkili arabirim için bir arabirim deyimi OLEAUTOMATION ve çift öznitelikleri olmalı ve arabirim IDispatchelde edilebilir. Sen-ebilmek kullanma GUIDGEN örnek bir IID ikili arabirim oluşturmak için
[uuid(0BDD0E81-0DD7-11cf-BBA8-444553540000), / / IID_IDualAClick
OleAutomation,
çift
]
IDualAClick arabirim: IDispatch
{
}
Bir kez yerinde arabirim bildirimi varsa, yöntemlerini ve özelliklerini girişlerini eklemeye başlayın. Çift arabirimler için yöntem ve özellik erişimcisi işlevleri çift arabirim bir hresult dönmek ve dönüş değerleri parametre özniteliklere sahip olarak geçmek parametre listeleri düzenlemek gerek [retval,out] . Özellikler, hem de bir okuma eklemeniz gerekir unutmayın ( propget ) ve yazma ( propput ) erişmek işlevi aynı kimliğe sahip. Örneğin:
[propput, id(1)] hresult metin ([gelen] bstr newText);
[propget, id(1)] hresult metin ([dışarı retval] bstr * retval)
Yöntemleri ve özellikleri tanımlandıktan sonra coclass deyiminizde arabirim bildirimi bir başvuru eklemeniz gerekir. Örneğin:
[uuid(4B115281-32F0-11cf-AC85-444553540000)]
coclass belge
{
görüntüleme arabirimi IAClick;
[varsayılan] arabirim IDualAClick;
}
Bir kez odl dosyanızı güncellendi, MFC'ın arabirimi göster mekanizması bir uygulama sınıfı için çift arabirim nesnesi sınıf tanımlamak ve MFC'ın QueryInterface düzeneği ilgili girişleri yapmak için kullanın. Bir girişi ihtiyacınız INTERFACE_PART odl arabirimi beyanı her giriş, artı bir dağıtma arabirimi girişleri engelleme. Her odl giriş propput özniteliğine sahip adlı bir işlev ihtiyacı put_propertyname . Her girdi propget özniteliği adında bir işlev ihtiyacı vardır.get_propertyname.
Bir uygulama sınıfı, ikili arabirim tanımlamak için bir DUAL_INTERFACE_PART engellemek için 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_ kısa newX);
STDMETHOD(get_x) (THIS_ kısa far * retval);
STDMETHOD(put_y) (THIS_ kısa newY);
STDMETHOD(get_y) (THIS_ kısa far * retval);
STDMETHOD(put_Position) (THIS_ IDualAutoClickPoint far * newPosition);
STDMETHOD(get_Position) (THIS_ IDualAutoClickPoint far far ** retval);
STDMETHOD(RefreshWindow)(THIS);
STDMETHOD(SetAllProps) (THIS_ kısa x, kısa y, bstr metin);
STDMETHOD(ShowWindow)(THIS);
END_DUAL_INTERFACE_PART(DualAClick)
MFC's çift arabirim bağlanmak için QueryInterface mekanizması, eklemek bir INTERFACE_PART giriş arabirimi Haritası
BEGIN_INTERFACE_MAP (CAutoClickDoc, CDocument)
INTERFACE_PART (CAutoClickDoc, DIID_IAClick, gönderim)
INTERFACE_PART (CAutoClickDoc, IID_IDualAClick, DualAClick)
END_INTERFACE_MAP()
Ardından, arabirimin uygulanmasında doldurmanız gerekmektedir. Çoğunlukla, sen-ecek muktedir için varolan mfc IDispatch uygulaması temsilci. Ö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);
}
Senin nesnenin yöntem ve özellik erişimcisi işlevleri için uygulamasında doldurmak gerekiyor. Yöntem ve özellik işlevler genellikle geri ClassWizard kullanılarak oluşturulan yöntemleri için temsilci seçebilirsiniz. Ancak, değişkenleri doğrudan erişim özelliklerini ayarlarsanız, get/değeri değişkenin koymak için kod yazmak gerekir. Örneğin:
STDMETHODIMP CAutoClickDoc::XDualAClick::put_text(BSTR newText)
{
nbsp; method_prologue (CAutoClickDoc, DualAClick)
/ / mfc otomatik olarak dönüştürür gelen Unicode bstr / / ANSI CString, gerekirse...
pThis - > m_str = newText;
noerror dönmek;
}
STDMETHODIMP CAutoClickDoc::XDualAClick::get_text(BSTR* retval)
{
method_prologue (CAutoClickDoc, DualAClick)
/ / mfc otomatik olarak dönüştürür dan ANSI CString için / / Unicode bstr, gerekirse...
pThis - > m_str.SetSysString(retval);
noerror dönmek;
}
Geçen ikili arabirim işaretçisi
İkili arabirim işaretçiyi geçen özellikle CCmdTarget::FromIDispatcharamak gerekir basit değildir. FromIDispatch , yalnızca MFC'ın IDispatch işaretçisi üzerinde çalışır. Bu sorunu gidermek için bir yolu orijinal IDispatch işaretçisi set vazgeçmek mfc tarafından ve bu işaretçi gerek işlevlerine geçmek sorgulamak. Örneğin
STDMETHODIMP CAutoClickDoc::XDualAClick::put_Position)
nbsp; IDualAutoClickPoint far * newPosition)
{
method_prologue (CAutoClickDoc, DualAClick)
LPDISPATCH lpDisp = null;
newPosition - > QueryInterface (IID_IDispatch, (LPVOID *) & lpDisp);
pThis - > SetPosition(lpDisp);
lpDisp - > Release();
noerror dönmek;
}
İşaretçi geri ikili arabirim yöntemi aracılığıyla geçirmeden önce o ikili arabirim işaretçinizi mfc IDispatch işaretçiyi değiştirmek gerekebilir. Örneğin:
STDMETHODIMP CAutoClickDoc::XDualAClick::get_Position)
nbsp; IDualAutoClickPoint far far ** retval)
{
method_prologue (CAutoClickDoc, DualAClick)
LPDISPATCH lpDisp;
lpDisp = pThis - > GetPosition();
lpDisp - > QueryInterface (IID_IDualAutoClickPoint, (LPVOID *) retval);
noerror dönmek;
}
Uygulama türü kitaplığı kaydettiriliyor
AppWizard kod sistemiyle Otomasyonu sunucu uygulama tür kitaplığı kaydı oluşturmaz. Tür kitaplığı kaydı için başka yollar varken, uygulaması tek başına çalıştırıldığı zaman o, kendi ole türü bilgileri güncelleştiriliyor tür kitaplığı kayıt uygulaması olması daha uygundur.
Uygulama başına çalıştırılan her uygulamanın tür kitaplığını kaydetmek için:
InitInstance işlevi, COleObjectFactory::UpdateRegistryAllçağrısı bulun. Bu çağrı, AfxOleRegisterTypeLibtür kitaplığı adı, tür kitaplığı için karşılık gelen LIBID belirterek, bir çağrı ekleyin/ / Sunucu uygulaması tek başına başlatıldığında, bu iyi bir fikir
/ / hasar görmüş durumda sistem kayıt defterini güncelleştirmek için.
m_server.UpdateRegistry(OAT_DISPATCH_OBJECT);
COleObjectFactory::UpdateRegistryAll();
/ / DUAL_SUPPORT_START
/ / Tür kitaplığı kayıtlı veya çift arabirim alışkanlık iş emin olun.
AfxOleRegisterTypeLib(AfxGetInstanceHandle(), LIBID_ACDual, _T("AutoClik.TLB"));
/ / DUAL_SUPPORT_END
Tür kitaplığı değişiklikleri karşılamak için proje oluşturma ayarlarını değiştirme
Böylece UUID tanımlarını içeren üstbilgi dosyası tarafından oluşturulan değiştirmek için proje ayarları oluşturmak her tür kitaplığı yeniden MkTypLib
UUID tanımları MkTypLib oluşturulan üstbilgi dosyasından projenize eklemek için:
/ / initIIDs.c: IID'leri için çift arabirimleri tanımlar
/ / Bu derlenmiş başlığı ile inşa edilmelidir değildir.
# include lt;ole2.h >
# include <initguid.h>
# include "acdual.h"
Tip Kitaplığı'nda doğru nesne sınıfını adı belirtme
Visual c++ ile yanlış sevk sihirbazlar uygulama sınıf adı ole createable sınıfları için sunucunun odl dosyasındaki coclass belirtmek için kullanın. Bu-ecek iş ise, uygulama sınıfı adı büyük olasılıkla kullanıcıların nesne istediğiniz sınıfın adını değil. Doğru adı belirtmek için odl dosyayı açın, her coclass deyimi bulun ve uygulama sınıf adını doğru dış adıyla değiştirin.
Coclass deyimi değiştirildiğinde, değişken isimleri CLSIDs MkTypLib oluşturulan üstbilgi dosyasında buna göre değişeceğini unutmayın. Sen-ecek lüzum-e yeni değişken adlarını kullanmak için kodunuzu güncelleştirmek için.
Özel durumlar ve otomasyon hata arabirimler
Otomasyon nesnesinin yöntem ve özellik erişimcisi işlevleri istisna atabilir. Eğer öyleyse, onları ikili arabirim uygulamasında idare ve sırt-e doğru denetleyicisi IErrorInfo, ole Otomasyonu hata işleme arabiriminden özel durum hakkında bilgi aktarmak gerekir. Bu arabirim IDispatch ve vtbl arabirimleri üzerinden ayrıntılı, bağlamsal hata bilgileri sağlar. Bir hata işleyicisi kullanılabilir olduğunu belirtmek üzere ISupportErrorInfo arabirimi uygulamak.
Hata işleme mekanizması göstermek için standart gönderme desteği uygulamak için kullanılan ClassWizard tarafından üretilen işlevleri istisnalar atmak varsayalım. IDispatch::Invoke MFC'ın uygulanması genelde bu özel durumlary yakalar ve onları bir EXCEPTINFO yani yapısına dönüştürür Invoke çağrı geri döndü. vtbl arabirimi kullanıldığında, ancak, size kendinizi özel durumları yakalamak için sorumludur. Örnek olarak, ikili arabirim yöntemleri korumak
STDMETHODIMP CAutoClickDoc::XDualAClick::put_text(BSTR newText)
{
nbsp; method_prologue (CAutoClickDoc, DualAClick)
TRY_DUAL(IID_IDualAClick)
{
/ / mfc otomatik olarak dönüştürür gelen Unicode bstr / / ANSI CString, gerekirse...
pThis - > m_str = newText;
noerror dönmek;
}
CATCH_ALL_DUAL
}
CATCH_ALL_DUALbir istisna oluştuğunda, doğru hata kodunu döndürerek ilgilenir. CATCH_ALL_DUAL ICreateErrorInfo arabirimini kullanarak ole Otomasyonu hata işleme bilgileri mfc istisna dönüştürür. (Örnek CATCH_ALL_DUAL makro olduğu dosya mfcdual.H acdual örnek. Özel durumları işlemek için aramaları işlevi DualHandleException , mfcdual dosyasındadır.CPP.) CATCH_ALL_DUALoluşan istisna türüne göre dönmek için hata kodunu belirler
hr = make_hresult (SEVERITY_ERROR, FACILITY_ITF, nbsp; (e - > m_wCode + 0x200))
Bu bir hresult özel durum neden arabirimi oluşturur. Hata kodu sistem tanımlı hresults standart ole arabirimlerin ile çakışmaları önlemek için 0x200 tarafından dengeleniyor.
E_OUTOFMEMORY döner.E_UNEXPECTED döner.Ole Otomasyon hatası tanıtıcısı kullanıldığını belirtmek için de ISupportErrorInfo arabirimi uygulamak.
Birincisi, ISupportErrorInfo destekler göstermek için otomasyon sınıf tanımı kodu ekleyin.
İkinci olarak, otomasyon sınıfın arabirim göster ISupportErrorInfo uygulama sınıfı MFC'ın QueryInterface mekanizması ile ilişkilendirmek için kod ekleyin. INTERFACE_PARTDeyimi eşleşen ISupportErrorInfo için tanımlanan sınıf.
Son olarak, ISupportErrorInfo desteklemek için tanımlanan sınıf uygulamak.
( acdual örnek içeren bu üç adım yardımcı olacak üç makro DECLARE_DUAL_ERRORINFO , DUAL_ERRORINFO_PART , ve IMPLEMENT_DUAL_ERRORINFO , tüm mfcdual içinde bulunan.H.)
Aşağıdaki örnek, ISupportErrorInfodesteklemek için tanımlanmış bir sınıf uygular. CAutoClickDocOtomasyon sınıf adı ve IID_IDualAClick IID hatalarının kaynağını arabirim Otomasyonu hata nesnesi yoluyla bildirilir:
STDMETHODIMP_(ulong) CAutoClickDoc::XSupportErrorInfo::AddRef() {}
nbsp; method_prologue (CAutoClickDoc, SupportErrorInfo) pThis - döndürür > ExternalAddRef();
} STDMETHODIMP_(ULONG) CAutoClickDoc::XSupportErrorInfo::Release() {return method_prologue (CAutoClickDoc, SupportErrorInfo) pThis - > ExternalRelease();
} STDMETHODIMP CAutoClickDoc::XSupportErrorInfo::QueryInterface (REFIID IID, LPVOID * ppvObj) {return method_prologue (CAutoClickDoc, SupportErrorInfo) pThis - > ExternalQueryInterface (& IID, ppvObj);
} STDMETHODIMP CAutoClickDoc::XSupportErrorInfo::InterfaceSupportsErrorInfo (REFIID IID) {method_prologue (CAutoClickDoc, SupportErrorInfo) dönüş (IID == IID_IDualAClick)? S_OK: S_FALSE;
}
Teknik notlar numarasına göre |nbsp; Teknik notlar kategorisine göre