Implementieren einer STL-Basierten Auflistung

ATL stellt die ICollectionOnSTLImpl-Schnittstelle, um es Ihnen ermöglicht, Auflistungsschnittstellen der Standardvorlagenbibliothek (STL) auf den Objekten - basierte schnell zu implementieren.Um zu verstehen wie diese Klasse funktioniert, arbeiten Sie durch ein einfaches Beispiel (unten) dieses mithilfe dieser Klasse angestrebte Automatisierung zu implementieren Clients einer schreibgeschützte Auflistung.

Der Beispielcode ist von ATLCollections-Beispiel.

Um diese Prozedur abzuschließen, werden Sie:

  • Generieren Sie ein neues einfaches Objekt.

  • Bearbeiten Sie die IDL-Datei für die generierte Schnittstelle.

  • Erstellen Sie fünf Typdefinitionen, das beschreibt, wie die Auflistungselemente gespeichert werden und wie sie von Clients über COM-Schnittstellen verfügbar gemacht werden.

  • Erstellen Sie zwei Typdefinitionen für Kopierrichtlinienklassen.

  • Erstellen Sie Typdefinitionen für die Enumerator- und Auflistungsimplementierungen.

  • Bearbeiten Sie den vom Assistenten generierten C++-Code, um die Auflistung Typedef zu verwenden.

  • Fügen Sie Code hinzu, um die Auflistung aufzufüllen.

Generieren eines neuen einfachen Objekts

Erstellen Sie ein neues Projekt und sicherstellen, dass das Attributfeld mit Anwendungseinstellungen gelöscht wird.Verwenden Sie das ATL hinzufügen Klassendialogfeld und einfachen Objekt-Assistenten hinzufügen, um ein einfaches Objekt zu generieren, das Words aufgerufen wird.Überprüfen Sie, ob eine duale Schnittstelle, die IWords aufgerufen wird, generiert wird.Objekte der generierten Klasse werden verwendet, um eine Auflistung Wörter (das heißt, Zeichenfolgen) darzustellen.

Bearbeiten der IDL-Datei

Jetzt öffnen Sie die IDL-Datei und fügen Sie die drei Eigenschaften hinzu, die erforderlich sind, IWords zu eine schreibgeschützte Auflistungsschnittstelle auszuführen, wie unten dargestellt:

[
   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);

};

Dies ist das Standardformular für eine schreibgeschützte Auflistungsschnittstelle, die mit Automatisierungsclients im Auge entworfen wurde.Die nummerierten Kommentare in dieser Schnittstellendefinition entsprechen den Kommentaren folgendermaßen:

  1. Auflistungsschnittstellen sind normalerweise Dual, da Automatisierungsclients auf die _NewEnum-Eigenschaft über IDispatch::Invoke zugreift.Allerdings können Automatisierungsclients auf die übrigen Methoden zum vtable zugreifen, daher sind duale Schnittstellen in Dispatchschnittstellen vorzuziehen.

  2. Wenn eine duale Schnittstelle oder eine Dispatchschnittstelle nicht zur Laufzeit (das heißt, stellen zusätzliche Methoden oder Eigenschaften nicht über IDispatch::Invoke) bereit, erweitert werden, sollten Sie das nonextensible-Attribut auf die Definition anwenden.Mit diesem Attribut können Automatisierungsclients, um die Überprüfung des vollständigen Code zur Kompilierzeit auszuführen.In diesem Fall sollte die Schnittstelle nicht erweitert werden.

  3. Das richtige DISPID ist wichtig, wenn Sie Automatisierungsclients in der Lage sein sollen, diese Eigenschaft zu verwenden.(Beachten Sie, dass es nur einen Unterstrich in DISPID_NEWENUM gibt).

  4. Sie können einen beliebigen Wert als den DISPID der Item-Eigenschaft bereitstellen.verwendet jedoch Item in der Regel DISPID_VALUE, um es die Standardeigenschaft aus der Auflistung zu machen.Dadurch können Automatisierungsclients, um die Eigenschaft zuzugreifen, ohne sie explizit zu benennen.

  5. Der Datentyp, der für den Rückgabewert der Item-Eigenschaft verwendet wird, ist der Typ des Elements, das in der Auflistung gespeichert wird, insoweit COM-Clients.Die Schnittstelle gibt Zeichenfolgen zurück, sollten Sie den Zeichenfolgentyp des standardmäßigen COM, BSTR verwenden.Sie können die Daten in einem anderen Format intern speichern, da Sie weiter unten unter.

  6. Der Wert, der für das DISPID der Count-Eigenschaft verwendet wird, ist vollständig beliebig.Es gibt keinen Standardwert DISPID für diese Eigenschaft.

Erstellen von Typdefinitionen für Speicher und verursachte

Sobald die Auflistungsschnittstelle definiert ist, müssen Sie entscheiden, wie die Daten gespeichert werden und wie die Daten über den Enumerator verfügbar gemacht werden.

Antworten auf diese Fragen können in Form von einigen Typdefinitionen bereitgestellt werden, die Sie im oberen Bereich der Headerdatei für die neu erstellte Klasse hinzufügen können:

// 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;

In diesem Fall speichern Sie die Daten als std::vector of std::strings.std::vector ist eine STL-Containerklasse, die wie ein verwaltetes Array verhält.std::string ist die Standard-Zeichenfolgenklasse der C++-Bibliothek.Diese Klassen ist es einfach, mit einer Auflistung von Zeichenfolgen zu arbeiten.

Da Visual Basic-Unterstützung zum Erfolg dieser Schnittstelle wichtig ist, muss der Enumerator, der von der _NewEnum-Eigenschaft zurückgegeben wird, die IEnumVARIANT-Schnittstelle unterstützen.Dies ist die einzige Enumeratorschnittstelle, die von Visual Basic erkannt wird.

Erstellen von Typdefinitionen für Kopierrichtlinienklassen

Die Typdefinitionen, die Sie bis jetzt erstellt haben, stellen alle Informationen Sie weitere Typdefinitionen für die Kopienklassen erstellen müssen, die durch den Enumerator und die Auflistung verwendet werden:

// Typedef the copy classes using existing typedefs
typedef VCUE::GenericCopy<EnumeratorExposedType, ContainerType::value_type> EnumeratorCopyType;
typedef VCUE::GenericCopy<CollectionExposedType, ContainerType::value_type> CollectionCopyType;

In diesem Beispiel können Sie die benutzerdefinierte GenericCopy-Klasse verwenden, die in VCUE_Copy.h und VCUE_CopyString.h vom ATLCollections-Beispiel definiert ist.Sie können diese Klasse in anderem Code verwenden, jedoch müssen Sie möglicherweise weitere Spezialisierungen von GenericCopy definieren, um die Datentypen zu unterstützen, die in eigenen Auflistungen verwendet werden.Weitere Informationen finden Sie unter ATL-Kopierrichtlinien-Klassen.

Erstellen von Typdefinitionen für Enumeration und Auflistung

Jetzt sind alle Vorlagenparameter, die erforderlich sind, die CComEnumOnSTL und ICollectionOnSTLImpl-Klassen für diese Situation zu spezialisieren, in Form von Typdefinitionen bereitgestellt wurde.Um die Verwendung der Spezialisierungen zu vereinfachen, erstellen Sie zwei weitere Typdefinitionen wie unten dargestellt:

typedef CComEnumOnSTL< EnumeratorInterface, &__uuidof(EnumeratorInterface), EnumeratorExposedType, EnumeratorCopyType, ContainerType > EnumeratorType;
typedef ICollectionOnSTLImpl< CollectionInterface, ContainerType, CollectionExposedType, CollectionCopyType, EnumeratorType > CollectionType;

Jetzt ist CollectionType ein Synonym für eine Spezialisierung von ICollectionOnSTLImpl, die die IWords-Schnittstelle implementiert, die zuvor definiert ist und stellt einen Enumerator, der IEnumVARIANT unterstützt.

Bearbeiten des vom Assistenten generierten Codes

Jetzt müssen Sie CWords aus der Schnittstellenimplementierung abgeleitet sind, die von CollectionType-Typedef statt IWords, wie unten dargestellt wird:

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.

Hinzufügen von Code, um die Auflistung aufzufüllen

Lediglich, bleibt, besteht darin, den Vektor mit Daten aufzufüllen.In diesem einfachen Beispiel können Sie mehrere Wörter der Auflistung im Konstruktor für die Klasse hinzufügen:

CWords()
{
    m_coll.push_back("this");
    m_coll.push_back("is");
    m_coll.push_back("a");
    m_coll.push_back("test");
}

Jetzt können Sie den Code mit dem Client Ihrer Wahl testen.

Siehe auch

Konzepte

ATL-Auflistungen und -Enumeratoren

ATLCollections-Beispiel

ATL-Kopierrichtlinien-Klassen