Kolekcja opartych na STL wykonawczych
Zapewnia ATL ICollectionOnSTLImpl interfejsu umożliwiające szybkie wdrożenie podstawie STL biblioteki szablonu standardowego zbioru interfejsów na obiekty.Aby zrozumieć sposób działania tej klasy, będzie działać przez prosty przykład (poniżej), który używa do kolekcji tylko do odczytu, zmierzające do klientów automatyzacji wdrożenia tej klasy.
Przykładowy kod jest z próbki ATLCollections.
Aby wykonać tę procedurę, będą:
Generowanie nowego obiektu proste.
Edytuj plik IDL dla interfejsu wygenerowane.
Tworzenie definicje TypeDef pięciu opisujące, jak są przechowywane elementy kolekcji i jak będą one narażone klientom za pośrednictwem interfejsów COM.
Utwórz dwie definicje TypeDef kopii klas zasad.
Tworzenie definicje TypeDef dla implementacji modułu wyliczającego i kolekcji.
Edycja kodu C++ generowane przez kreatora, aby użyć typedef kolekcji.
Dodawanie kodu do wypełniania kolekcji.
Generowanie nowego obiektu proste
Utwórz nowy projekt, zapewniając, że wyczyszczone jest pole atrybutów w obszarze Ustawienia aplikacji.Okno dialogowe ATL Add Class i prosty obiekt Kreatora dodawania do generowania prosty obiekt o nazwie Words.Upewnij się, że podwójne interfejsu o nazwie IWords jest generowany.Obiekty klasy generowane będą używane do reprezentowania zbiór słów (czyli ciągi).
Edytowanie pliku IDL
Teraz, otwórz plik IDL i dodać trzy właściwości niezbędne do włączenia IWords do interfejsu kolekcji tylko do odczytu, jak pokazano poniżej:
[
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);
};
Jest to standardowy formularz dla interfejsu kolekcji tylko do odczytu, zaprojektowane z klientów automatyzacji w uwadze.Ponumerowane komentarze w tej definicji interfejsu odpowiadają poniższe uwagi:
Kolekcji interfejsów są zazwyczaj podwójne, ponieważ klienci automatyzacji uzyskuje dostęp do _NewEnum właściwość via IDispatch::Invoke.Jednak automatyzacji klienci mogą uzyskać dostęp za pośrednictwem vtable, pozostałe metody więc dwa interfejsy są lepiej dispinterfaces.
Jeśli podwójnym interfejsem lub dispinterface nie zostanie przedłużony w czasie wykonywania (to znaczy nie udostępniają dodatkowe metody lub właściwości za pomocą uwzględniając), należy zastosować nonextensible atrybut do definicji użytkownika.Atrybut ten umożliwia klientom automatyzacji wykonać pełny kod weryfikacji w czasie kompilacji.W takim przypadku nie powinny rozszerzony interfejs.
Poprawne DISPID jest ważne, jeśli klienci automatyzacji, aby móc korzystać z tej właściwości.(Zauważ, że jest tylko jeden znak podkreślenia w DISPID_NEWENUM.)
Można podać dowolną wartość jako [DISPID o elementu właściwości.Jednakże elementu zwykle korzysta z DISPID_VALUE aby właściwości domyślne kolekcji.Pozwala to klientom automatyzacji do odwoływania się do właściwości bez nazywając go jawnie.
Typ danych używany dla wartości zwracanej przez elementu właściwość jest typ elementu w kolekcji w zakresie, w jakim dotyczy to COM klientów.Interfejs zwraca ciągi, więc należy użyć standardowego typu ciąg COM BSTR.Można przechowywać dane w innym formacie wewnętrznie jak zobaczymy wkrótce.
Wartość używana do DISPID o liczba właściwość jest całkowicie dowolnego.Nie ma żadnych DISPID standardowych dla tej właściwości.
Tworzenie definicje TypeDef magazynowania i ekspozycji
Po interfejs kolekcji jest zdefiniowana, należy zdecydować, jak dane będą przechowywane i w jaki sposób będzie narażona danych za pośrednictwem modułu wyliczającego.
Odpowiedzi na te pytania można dostarczone w formie liczby definicje typów, które można dodać w górnej części pliku nagłówka nowo utworzone klasy:
// 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;
W tym przypadku będzie przechowywać dane jako std::vector z szablonowejs.STD::Vector jest klasa container STL, który zachowuje się jak tablicy.szablonowej jest klasą string standardowa biblioteka języka C++.Klasy te ułatwiają pracować Kolekcja ciągów.
Ponieważ obsługa języka Visual Basic jest istotne dla powodzenia tego interfejsu, moduł wyliczający zwrócony przez _NewEnum musi obsługiwać właściwość IEnumVARIANT interfejsu.Jest to interfejs tylko moduł wyliczający zrozumiałym języku Visual Basic.
Tworzenie definicje TypeDef dla klasy zasad kopii
Definicje TypeDef dotąd utworzone zawierają wszystkie informacje potrzebne do utworzenia dalsze definicje TypeDef dla klas kopię używanych przez moduł wyliczający i kolekcji:
// Typedef the copy classes using existing typedefs
typedef VCUE::GenericCopy<EnumeratorExposedType, ContainerType::value_type> EnumeratorCopyType;
typedef VCUE::GenericCopy<CollectionExposedType, ContainerType::value_type> CollectionCopyType;
W tym przykładzie, można użyć niestandardowej GenericCopy klasy zdefiniowane w VCUE_Copy.h i VCUE_CopyString.h z ATLCollections próbki.W innym kodzie można używać tej klasy, ale trzeba zdefiniować dalsze specjalności z GenericCopy do obsługi typów danych używanych na własne kolekcje.Aby uzyskać więcej informacji, zobacz Klasy zasad kopii ATL.
Tworzenie definicje TypeDef wyliczania i kolekcji
Teraz wszystkie parametry szablonu konieczne specialize CComEnumOnSTL i ICollectionOnSTLImpl klasy dla tej sytuacji były udzielane w formie definicje TypeDef.Aby uprościć stosowanie specjalizacji, należy utworzyć dwie definicje TypeDef więcej jak pokazano poniżej:
typedef CComEnumOnSTL< EnumeratorInterface, &__uuidof(EnumeratorInterface), EnumeratorExposedType, EnumeratorCopyType, ContainerType > EnumeratorType;
typedef ICollectionOnSTLImpl< CollectionInterface, ContainerType, CollectionExposedType, CollectionCopyType, EnumeratorType > CollectionType;
Teraz CollectionType jest synonimem specjalizacji z ICollectionOnSTLImpl który implementuje IWords interfejsu zdefiniowane wcześniej i zawiera moduł wyliczający obsługiwane przez IEnumVARIANT.
Edycja kodu wygenerowany przez kreatora
Teraz musi pochodzić CWords z implementacji interfejsu reprezentowane przez CollectionType typedef zamiast IWords, jak pokazano poniżej:
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.
Dodawanie kodu do wypełniania kolekcji
Pozostaje się tylko do wypełnienia wektorowe z danymi.Ten prosty przykład można dodać kilka słów do kolekcji w konstruktorze klasy:
CWords()
{
m_coll.push_back("this");
m_coll.push_back("is");
m_coll.push_back("a");
m_coll.push_back("test");
}
Teraz można przetestować kod z dowolnego klienta.