Partilhar via


Implementando uma coleção com base STL-

ATL fornece a interface de ICollectionOnSTLImpl para permitir que você rapidamente implementar interfaces com base na coleção de (STL) de biblioteca padrão do modelo em seus objetos.Para entender como essa classe funciona, você trabalhará com um exemplo simples (abaixo) que usa essa classe implementar clientes voltadas para uma coleção somente leitura de automação.

O código de exemplo é de exemplo de ATLCollections.

Para concluir este procedimento, você:

  • Gerar um novo objeto simples.

  • Edite o arquivo de IDL para a interface gerado.

  • crie cinco typedefs que descreve como os itens de coleção são armazenados e como eles serão expostos aos clientes através da interface.

  • Crie dois typedefs para classes de diretiva de impressão.

  • Crie typedefs para as implementações do enumerador e de coleção.

  • Editar o código gerado assistentes C++ para usar o typedef de coleção.

  • Adicione código para preencher a coleção.

Gerando um novo objeto simples

Crie um novo projeto, garantindo que a caixa de atributos em configurações de aplicativo está desmarcada.Use o ATL adiciona a caixa de diálogo da classe e adiciona o assistente simples do objeto para gerar um objeto simples chamado Words.Certifique-se de que uma interface dupla chamada IWords é gerada.Os objetos da classe gerada serão usados para representar uma coleção da palavra (isto é, cadeias de caracteres).

Editando o Arquivo IDL

Agora, abra o arquivo de IDL e adicione as três propriedades necessárias para transformar IWords em uma interface somente leitura de coleção, como mostrado abaixo:

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

};

Este é o formulário padrão para uma interface somente leitura de coleção criada com clientes de automação em mente.Os comentários numerados em esta definição de interface correspondem aos comentários em:

  1. As interfaces duais de coleção são geralmente porque os clientes de automação acessam a propriedade de _NewEnum através de IDispatch::Invoke.Em o entanto, os clientes de automação podem acessar os métodos restantes através de vtable, para que as interfaces duais são preferíveis a dispinterfaces.

  2. Se uma interface dupla ou um dispinterface não serão estendidos em tempo de execução (ou seja, você não irá fornecer métodos adicionais ou propriedades através de IDispatch::Invoke), você deve aplicar o atributo de nonextensible a sua definição.Esse atributo permite que clientes de automação para executar em tempo de compilação completa a verificação de código.Em esse caso, a interface não deve ser estendido.

  3. O DISPID correto é importante se você deseja clientes de automação para poder usar essa propriedade.(Observe que há apenas um sublinhado em DISPID_NEWENUM.)

  4. Você pode fornecer qualquer como o valor DISPID da propriedade de Item .Em o entanto, Item normalmente usa DISPID_VALUE para fazer-lhe a propriedade padrão.Isso permite que os clientes de automação se referirem a propriedade sem nomeá-la explicitamente.

  5. O tipo de dados usado para valores de retorno da propriedade de Item é o tipo de item armazenado na coleção tanto quanto os clientes COM.A interface retorna cadeias de caracteres, portanto você deve usar o tipo cadeia de caracteres do padrão COM, BSTR.Você pode armazenar os dados em um formato diferente internamente como será visto brevemente.

  6. O usado para o valor DISPID da propriedade de Contagem é completamente arbitrário.Não há padrão DISPID para essa propriedade.

Criando Typedefs para armazenamento e a exposição

Uma vez que a interface da coleção é definida, você precisa decidir como os dados serão armazenados, e como os dados serão expostas através de enumeração.

As respostas a essas perguntas podem ser fornecidas na forma de um número de typedefs, que você pode adicionar próximo à parte superior do arquivo de cabeçalho para sua classe recém-criado:

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

Em esse caso, você irá armazenar os dados como std::vector de std::stringS.std::vector é uma classe do contêiner de STL que se comporta como uma matriz gerenciado.std::string é a classe de cadeia de caracteres da biblioteca do C++ padrão.Essas classes facilitam trabalhar com uma coleção de cadeias de caracteres.

Desde que o suporte do Visual Basic é vital para o sucesso de essa interface, o enumerador retornado pela propriedade de _NewEnum deve oferecer suporte a interface de IEnumVARIANT .Esta é a única interface de enumerador compreendido pelo Visual Basic.

Criando Typedefs para classes de diretiva de impressão

Os typedefs que você criou até agora fornecem todas as informações que você precisa criar um typedefs adicionais para as classes de impressão que serão usadas pelo enumerador e a coleção:

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

Em esse exemplo, você pode usar a classe de GenericCopy personalizada definida em VCUE_Copy.h e em VCUE_CopyString.h do exemplo de ATLCollections .Você pode usar esta classe no outro código, mas você pode precisar definir uma especializações adicionais de GenericCopy para oferecer suporte aos tipos de dados usados em suas próprias coleções.Para obter mais informações, consulte Classes de diretiva de impressão de ATL.

Criando Typedefs para a enumeração e da coleção

Agora todos os parâmetros de modelo necessários especializar as classes de CComEnumOnSTL e de ICollectionOnSTLImpl para essa situação foram fornecidos na forma de typedefs.Para simplificar o uso de especializações, crie dois mais typedefs como mostrado abaixo:

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

Agora CollectionType é um sinónimo para uma especialização de ICollectionOnSTLImpl que implementa o definido anteriormente interface de IWords e fornece um enumerador que suporte IEnumVARIANT.

Editando código Gerado assistentes

Agora você deve derivar CWords de implementação de interface representada pelo typedef de CollectionType em vez de IWords, como mostrado abaixo:

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.

Adicionando código para preencher a coleção

A única coisa que resta é preencher o vetor com dados.Em esse exemplo simples, você pode adicionar algumas palavra à coleção no construtor para a classe:

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

Agora, você pode testar o código com o cliente de sua escolha.

Consulte também

Conceitos

Coleções e enumeradores de ATL

exemplo de ATLCollections

Classes de diretiva de impressão de ATL