C++ Standart Kitaplığı Temelli Koleksiyon Uygulama
ATL, nesnelerinize C++ Standart Kitaplık tabanlı koleksiyon arabirimlerini hızlı bir şekilde uygulamanızı sağlayan arabirim sağlar ICollectionOnSTLImpl
. Bu sınıfın nasıl çalıştığını anlamak için, Otomasyon istemcilerini hedefleyen salt okunur bir koleksiyon uygulamak için bu sınıfı kullanan basit bir örnek (aşağıda) üzerinden çalışacaksınız.
Örnek kod ATLCollections örneğinden alınıyor.
Bu yordamı tamamlamak için şunları yapacaksınız:
Yeni bir Basit Nesne oluşturun.
Oluşturulan arabirim için IDL dosyasını düzenleyin.
Koleksiyon öğelerinin nasıl depolandığını ve COM arabirimleri aracılığıyla istemcilere nasıl gösterileceğini açıklayan beş tür tanımı oluşturun.
Kopyalama ilkesi sınıfları için iki tür tanımı oluşturun.
Numaralandırıcı ve koleksiyon uygulamaları için tür tanımları oluşturun.
Koleksiyon typedef'ini kullanmak için sihirbaz tarafından oluşturulan C++ kodunu düzenleyin.
Koleksiyonu doldurmak için kod ekleyin.
Yeni Basit Nesne Oluşturma
Uygulama Ayarları altındaki Öznitelikler kutusunun temizlendiğinden emin olarak yeni bir proje oluşturun. adlı Words
basit bir Nesne oluşturmak için ATL Sınıf Ekle iletişim kutusunu ve Basit Nesne Ekleme Sihirbazı'nı kullanın. adlı IWords
bir çift arabirimin oluşturulduğundan emin olun. Oluşturulan sınıfın nesneleri, bir sözcük koleksiyonunu (yani dizeleri) temsil etmek için kullanılır.
IDL Dosyasını Düzenleme
Şimdi IDL dosyasını açın ve aşağıda gösterildiği gibi salt okunur koleksiyon arabirimine dönüştürmek IWords
için gereken üç özelliği ekleyin:
[
object,
uuid(7B3AC376-509F-4068-87BA-03B73ADC359B),
dual, // (1)
nonextensible, // (2)
pointer_default(unique)
]
interface IWords : IDispatch
{
[id(DISPID_NEWENUM), propget] // (3)
HRESULT _NewEnum([out, retval] IUnknown** ppUnk);
[id(DISPID_VALUE), propget] // (4)
HRESULT Item([in] long Index, [out, retval] BSTR* pVal); // (5)
[id(0x00000001), propget] // (6)
HRESULT Count([out, retval] long* pVal);
};
Bu, Otomasyon istemcileri göz önünde bulundurularak tasarlanmış salt okunur koleksiyon arabirimi için standart formdur. Bu arabirim tanımındaki numaralandırılmış açıklamalar aşağıdaki açıklamalara karşılık gelir:
Otomasyon istemcileri özelliğine aracılığıyla
IDispatch::Invoke
eriştiğinden_NewEnum
koleksiyon arabirimleri genellikle çifttir. Ancak, Otomasyon istemcileri vtable aracılığıyla kalan yöntemlere erişebilir, bu nedenle çift arabirimler dispinterfaces için tercih edilir.Çift arabirim veya dispinterface çalışma zamanında genişletilmeyecekse (başka bir ifadeyle ek yöntemler veya özellikler
IDispatch::Invoke
sağlamayacaksınız), tanımınıza genişletilebilir olmayan özniteliği uygulamanız gerekir. Bu öznitelik, Otomasyon istemcilerinin derleme zamanında tam kod doğrulaması gerçekleştirmesini sağlar. Bu durumda, arabirim genişletilmemelidir.Otomasyon istemcilerinin bu özelliği kullanabilmesini istiyorsanız doğru DISPID önemlidir. (DISPID_NEWENUM yalnızca bir alt çizgi olduğunu unutmayın.)
Özelliğin DISPID
Item
değeri olarak herhangi bir değer sağlayabilirsiniz. Ancak,Item
genellikle koleksiyonun varsayılan özelliği yapmak için DISPID_VALUE kullanır. Bu, Otomasyon istemcilerinin açıkça adlandırmadan özelliğine başvurmasını sağlar.özelliğinin dönüş değeri
Item
için kullanılan veri türü, COM istemcileri açısından koleksiyonda depolanan öğenin türüdür. Arabirim dizeleri döndürür, bu nedenle standart COM dize türü olan BSTR'yi kullanmanız gerekir. Kısa süre içinde göreceğiniz gibi verileri dahili olarak farklı bir biçimde depolayabilirsiniz.Özelliğin DISPID değeri
Count
için kullanılan değer tamamen rastgeledir. Bu özellik için standart DISPID yoktur.
Depolama ve Açığa Çıkarma için Tür Tanımları Oluşturma
Koleksiyon arabirimi tanımlandıktan sonra verilerin nasıl depolanacağına ve verilerin numaralandırıcı aracılığıyla nasıl gösterileceğine karar vermeniz gerekir.
Bu soruların yanıtları, yeni oluşturduğunuz sınıfınız için üst bilgi dosyasının üst kısmına ekleyebileceğiniz bir dizi tür tanımı biçiminde sağlanabilir:
// Store the data in a vector of std::strings
typedef std::vector< std::string > ContainerType;
// The collection interface exposes the data as BSTRs
typedef BSTR CollectionExposedType;
typedef IWords CollectionInterface;
// Use IEnumVARIANT as the enumerator for VB compatibility
typedef VARIANT EnumeratorExposedType;
typedef IEnumVARIANT EnumeratorInterface;
Bu durumda, verileri std::strings öğesinin std::vektör olarak depolayacaksınız. std::vector , yönetilen bir dizi gibi davranan bir C++ Standart Kitaplık kapsayıcı sınıfıdır. std::string , C++ Standart Kitaplığı'nın dize sınıfıdır. Bu sınıflar, bir dize koleksiyonuyla çalışmayı kolaylaştırır.
Visual Basic desteği bu arabirimin başarısı için çok önemli olduğundan, özelliği tarafından döndürülen numaralandırıcı arabirimi _NewEnum
desteklemelidir IEnumVARIANT
. Bu, Visual Basic tarafından anlaşılan tek numaralandırıcı arabirimidir.
Kopyalama İlkesi Sınıfları için Tür Tanımları Oluşturma
Şimdiye kadar oluşturduğunuz tür tanımları, numaralandırıcı ve koleksiyon tarafından kullanılacak kopyalama sınıfları için daha fazla tür tanımı oluşturmak için ihtiyacınız olan tüm bilgileri sağlar:
// Typedef the copy classes using existing typedefs
typedef VCUE::GenericCopy<EnumeratorExposedType, ContainerType::value_type> EnumeratorCopyType;
typedef VCUE::GenericCopy<CollectionExposedType, ContainerType::value_type> CollectionCopyType;
Bu örnekte, ATLCollections örneğinden VCUE_Copy.h ve VCUE_CopyString.h içinde tanımlanan özel GenericCopy
sınıfı kullanabilirsiniz. Bu sınıfı başka kodlarda kullanabilirsiniz, ancak kendi koleksiyonlarınızda kullanılan veri türlerini desteklemek için daha fazla uzmanlık GenericCopy
tanımlamanız gerekebilir. Daha fazla bilgi için bkz . ATL Kopyalama İlkesi Sınıfları.
Numaralandırma ve Koleksiyon için Typedef oluşturma
Artık bu duruma yönelik ve ICollectionOnSTLImpl
sınıflarını özelleştirmek CComEnumOnSTL
için gereken tüm şablon parametreleri tür tanımları biçiminde sağlanmıştır. Özelleştirmelerin kullanımını basitleştirmek için aşağıda gösterildiği gibi iki tür tanımı daha oluşturun:
typedef CComEnumOnSTL< EnumeratorInterface, &__uuidof(EnumeratorInterface), EnumeratorExposedType, EnumeratorCopyType, ContainerType > EnumeratorType;
typedef ICollectionOnSTLImpl< CollectionInterface, ContainerType, CollectionExposedType, CollectionCopyType, EnumeratorType > CollectionType;
ŞimdiCollectionType
, daha önce tanımlanan arabirimi uygulayan IWords
ve destekleyen IEnumVARIANT
bir numaralandırıcı sağlayan bir özelleştirmenin ICollectionOnSTLImpl
eş anlamlısı.
Sihirbaz Tarafından Oluşturulan Kodu Düzenleme
Şimdi aşağıda gösterildiği gibi yerine typedef IWords
ile temsil edilen arabirim uygulamasından CollectionType
türetmelisinizCWords
:
class ATL_NO_VTABLE CWords :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CWords, &CLSID_Words>,
// 'CollectionType' replaces 'IWords' in next line
public IDispatchImpl<CollectionType, &IID_IWords, &LIBID_NVC_ATL_COMLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
DECLARE_REGISTRY_RESOURCEID(IDR_WORDS)
BEGIN_COM_MAP(CWords)
COM_INTERFACE_ENTRY(IWords)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
// Remainder of class declaration omitted.
Koleksiyonu Doldurmak için Kod Ekleme
Geriye kalan tek şey vektöre veri eklemektir. Bu basit örnekte, sınıfının oluşturucusunda koleksiyona birkaç sözcük ekleyebilirsiniz:
CWords()
{
m_coll.push_back("this");
m_coll.push_back("is");
m_coll.push_back("a");
m_coll.push_back("test");
}
Artık kodu istediğiniz istemciyle test edebilirsiniz.
Ayrıca bkz.
Koleksiyonlar ve Numaralandırıcılar
ATLCollections Örneği
ATL Kopyalama İlkesi Sınıfları