Compartir a través de


Implementar una colección STL-Basada

ATL proporciona la interfaz de ICollectionOnSTLImpl que permite implementar rápidamente interfaces de intercalación Biblioteca-basadas plantilla (STL) estándar en los objetos.Para entender cómo funciona esta clase, trabajará con un ejemplo simple (abajo) que utiliza esta clase para implementar los clientes dirigidos colección de solo lectura de una automatización.

El código de ejemplo es de Ejemplo ATLCollections.

Para completar este procedimiento, debe:

  • Genera un nuevo objeto sencillo.

  • Edite el archivo IDL para la interfaz generada.

  • cree cinco typedefs que describe cómo se almacenan los elementos de colección y cómo se van a exponer a los clientes mediante interfaces COM.

  • Cree dos definiciones de tipos para las clases de directivas de copia.

  • Crear tipos para implementaciones de enumerador y colección.

  • Edite el código generado por el asistente de C++ para utilizar typedef de colección.

  • Agregue código para rellenar la colección.

Generar un objeto New Simple

Cree un nuevo proyecto, asegurarse de que el cuadro de los atributos en la configuración de la aplicación está desactivada.Utilice el ATL agregan el cuadro de diálogo de la clase y agregue el asistente para objetos de Simple para generar un objeto sencillo denominado Words.Asegúrese de que una interfaz dual denominada IWords se genera.Los objetos de la clase generada se utilizarán para representar una colección de palabras (es decir, cadenas).

Editar el archivo IDL

Ahora, abra el archivo IDL y agrega las tres propiedades necesarias girar IWords en una interfaz de intercalación de sólo lectura, como se muestra a continuación:

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

};

Éste es el formulario estándar para una interfaz de intercalación de sólo lectura diseñada con clientes de automatización en mente.Los comentarios numerados en esta definición de interfaz corresponden a los comentarios a continuación:

  1. Las interfaces de intercalación son normalmente duales porque los clientes de automatización tienen acceso a la propiedad de _NewEnum mediante IDispatch::Invocar.Sin embargo, los clientes de automatización pueden tener acceso a los métodos restantes mediante vtable, de modo que las interfaces duales son preferibles a dispinterfaces.

  2. Si una interfaz dual o dispinterface no es extendida en tiempo de ejecución (es decir, no proporcionará otros métodos o propiedades mediante IDispatch::Invocar), debe aplicar el atributo de nonextensible a la definición.Este atributo permite a los clientes de automatización para realizar la comprobación completa del código en tiempo de compilación.En este caso, la interfaz no se extenderá.

  3. El identificador de envío correcto es importante si desea que los clientes de automatización para poder usar esta propiedad.(Observe que sólo hay un subrayado en DISPID_NEWENUM.)

  4. Puede proporcionar cualquier valor como el identificador de envío de la propiedad de Elemento .Sin embargo, Elemento utiliza normalmente DISPID_VALUE para convertirla en la propiedad predeterminada de la colección.Esto permite que los clientes de automatización hacen referencia a la propiedad sin llamarla explícitamente.

  5. El tipo de datos utilizado por el valor devuelto de la propiedad de Elemento es el tipo del elemento almacenado en la colección por lo que los clientes COM.La interfaz devuelve las cadenas, por lo que debe utilizar el tipo string COM estándar, BSTR.Puede almacenar los datos en un formato diferente internamente como verá pronto.

  6. El valor utilizado para el identificador de envío de la propiedad de Cuenta es totalmente arbitrario.No hay estándar DISPID para esta propiedad.

Crear definiciones de tipos para el almacenamiento y Exposición

Una vez que la interfaz de intercalación se define, debe decidir cómo los datos se almacenan, y cómo los datos se expuestos a través del enumerador.

Las respuestas a estas preguntas pueden suministrarse en forma de varios typedefs, que puede agregar cerca de la parte superior del archivo de encabezado para la clase creada recientemente:

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

En este caso, se almacenará los datos como std:: vector de s para std:: cadena.std:: vector es una clase de contenedor de STL que se comporta como una matriz administrada.std:: cadena es la clase de cadena estándar de la biblioteca de C++.Estas clases facilitan el trabajo con una colección de cadenas.

Puesto que la compatibilidad de Visual Basic es vital para el éxito de esta interfaz, el enumerador devuelto por la propiedad de _NewEnum debe admitir la interfaz de IEnumVARIANT .Esta es la única interfaz de enumerador entendida por Visual Basic.

Crear definiciones de tipos para las clases de directivas de copia

Tipos que ha creado hasta ahora proporcionan toda la información necesita crear otros typedefs para las clases de la copia que usarán el enumerador y la colección:

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

En este ejemplo, puede utilizar la clase personalizada de GenericCopy definida en VCUE_Copy.h y VCUE_CopyString.h de ejemplo de ATLCollections .Puede utilizar esta clase en otro código, pero puede que necesite definir otras especializaciones de GenericCopy para admitir los tipos de datos utilizados en dispone de colecciones.Para obtener más información, vea Clases de directivas de copia ATL.

Crear definiciones de tipos para Enumeration y la colección

Ahora todos los parámetros de plantilla necesarios especializar las clases de CComEnumOnSTL y de ICollectionOnSTLImpl de esta situación se han proporcionado en forma de definiciones de tipos.Para simplificar el uso de especializaciones, cree dos más typedefs como se muestra a continuación:

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

Ahora CollectionType es un sinónimo de una especialización de ICollectionOnSTLImpl que implemente el anterior definido de la interfaz de IWords y proporciona un enumerador que admite IEnumVARIANT.

Modificar el código generado por el asistente

Ahora debe derivar CWords de implementación de la interfaz representada por typedef de CollectionType en lugar de IWords, como se muestra a continuación:

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.

Agregar código para rellenar la colección

Lo único que queda es rellenar el vector con datos.En este ejemplo, puede agregar algunas palabras a la colección en el constructor para la clase:

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

Ahora, puede probar el código con el cliente de la opción.

Vea también

Conceptos

Colecciones y enumeradores ATL

Ejemplo ATLCollections

Clases de directivas de copia ATL