Implementace založené na STL kolekce
Poskytuje ATL ICollectionOnSTLImpl rozhraní umožňující rychle implementovat rozhraní založené na standardní šablonu knihovny STL kolekce na objekty.Pochopit Princip této třídy, bude pracovat prostřednictvím jednoduchý příklad (níže) používající tato třída implementovat zaměřená na automatizaci klienty kolekce jen pro čtení.
Ukázkový kód je ATLCollections vzorku.
Tento postup bude:
Generovat nový jednoduchý objekt.
Upravte soubor IDL pro generované rozhraní.
Vytvoření pěti funkce TypeDef popisující, jak jsou uloženy položky kolekce a jak bude být vystaveni klientům prostřednictvím rozhraní COM.
Vytvořit dvě funkce TypeDef kopii zásady třídy.
Vytvoření funkce TypeDef pro implementace čítače výčtu a kolekce.
Upravit kód jazyka C++ generované průvodcem pomocí kolekce typedef.
Přidání kódu k naplnění kolekce.
Generování nového jednoduchého objektu
Vytvoření nového projektu, zajištění, že není zaškrtnuto pole atributů ve skupinovém rámečku nastavení aplikace.V dialogovém okně Přidat třídy ATL a jednoduchý objekt Průvodce přidáním vygenerovat jednoduchý objekt nazvaný Words .Ujistěte se, že se nazývá duální rozhraní IWords je generována.Objekty vytvořené třídy bude představovat kolekce slova (řetězce).
Úpravy souboru IDL
Nyní otevřete soubor, IDL a přidat tři vlastnosti nezbytné pro zapnutí IWords do rozhraní kolekce jen pro čtení, jak je ukázáno níže:
[
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);
};
Toto je standardní formulář pro sběr pouze pro čtení rozhraní s klienty automatizace v úvahu.Komentáře pod odpovídají číslované poznámky v této definici rozhraní:
Rozhraní kolekce jsou obvykle duální protože přistupuje k automatizaci klientů _NewEnum vlastnost via IDispatch::Invoke.Však automatizace mohou klienti získat přístup prostřednictvím virtuální tabulka, zbývající metody tak duální rozhraní jsou výhodnější než dispinterfaces.
Pokud duální rozhraní nebo omezené rozhraní IDispatch nebude prodlouženo za běhu (, nebude poskytovat zvláštní metody nebo vlastnosti prostřednictvím IDispatch::Invoke), byste měli použít nerozšiřitelnou vaše definice atributu.Tento atribut umožňuje klientům automatizace provedení úplné kód ověření v době kompilace.V tomto případě by neměla být rozšířena na rozhraní.
Je důležité, pokud chcete používat tuto vlastnost klienti automatizace správný identifikátor DISPID.(Je pouze jeden podtržítko v DISPID_NEWENUM.)
Lze zadat libovolnou hodnotu jako DISPID z zboží vlastnost.Však zboží obvykle používá DISPID_VALUE tak, aby výchozí vlastnosti kolekce.To umožňuje klientům automatizace bez jejího pojmenování explicitně odkazovat na vlastnost.
Typ dat používaný pro vrácenou hodnotu zboží vlastnost je typ položky uložené v kolekci COM klientů jsou dotyčné.Rozhraní vrátí řetězce, takže byste měli použít standardní typ řetězec COM BSTR .Můžete uložit data v jiném formátu interně uvidíte krátce.
Hodnota použitá pro DISPID z počet vlastnost je zcela libovolný.Neexistuje žádná standardní DISPID pro tuto vlastnost.
Vytváření funkce TypeDef pro skladování a expozice
Po definování rozhraní sběru, budete muset rozhodnout, jak budou data uložena a jak budou data exponované prostřednictvím čítače výčtu.
Odpovědi na tyto otázky lze poskytnuta ve formě počtu funkce TypeDef pro nově vytvořené třídy můžete přidat v horní části záhlaví souboru:
// 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;
V tomto případě bude ukládat data, jako std::vector z std::strings.std::Vector je třída kontejneru STL, který se chová jako spravovaného pole.std::String je třída string Standard C++ Library.Tyto třídy usnadňují práci s kolekce řetězců.
Podpora jazyka Visual Basic, protože je důležitá pro úspěch tohoto rozhraní Čítač vrácený _NewEnum vlastnost musí podporovat IEnumVARIANT rozhraní.Toto je pouze čítače výčtu rozhraní srozumitelném jazyce Visual Basic.
Funkce TypeDef vytvoření kopie zásady tříd
Funkce TypeDef, kterou jste doposud vytvořili poskytnout veškeré informace potřebné k vytvoření další funkce TypeDef kopie tříd, které bude používat výčet a kolekce:
// Typedef the copy classes using existing typedefs
typedef VCUE::GenericCopy<EnumeratorExposedType, ContainerType::value_type> EnumeratorCopyType;
typedef VCUE::GenericCopy<CollectionExposedType, ContainerType::value_type> CollectionCopyType;
V tomto příkladu použijete vlastní GenericCopy třídy definované v VCUE_Copy.h a z VCUE_CopyString.h ATLCollections vzorku.Můžete použít jiný kód v této třídy, ale je třeba definovat další specializace z GenericCopy na podporu datové typy používané v vlastní kolekce.Další informace naleznete v tématu ATL kopie zásady třídy.
Funkce TypeDef vytvoření výčtu a kolekce
Nyní všechny šablony parametry nezbytné specializují CComEnumOnSTL a ICollectionOnSTLImpl třídy pro tuto situaci byly poskytnuty ve formě funkce TypeDef.Zjednodušení používání odborností, vytvořte dvě další funkce TypeDef, jak je ukázáno níže:
typedef CComEnumOnSTL< EnumeratorInterface, &__uuidof(EnumeratorInterface), EnumeratorExposedType, EnumeratorCopyType, ContainerType > EnumeratorType;
typedef ICollectionOnSTLImpl< CollectionInterface, ContainerType, CollectionExposedType, CollectionCopyType, EnumeratorType > CollectionType;
Nyní CollectionType je synonymum pro specializace z ICollectionOnSTLImpl , implementuje IWords dříve definované rozhraní a poskytuje čítač výčtu, který podporuje IEnumVARIANT.
Úpravy kódu generované průvodcem
Nyní musí být odvozena CWords z implementace rozhraní zastoupen CollectionType typedef spíše než IWords , jak je ukázáno níže:
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.
Přidání kódu k naplnění kolekce
Jediná věc, která zůstává je naplnit vektorová data.V tomto příkladu jednoduché můžete přidat několik slov na kolekci v konstruktoru třídy:
CWords()
{
m_coll.push_back("this");
m_coll.push_back("is");
m_coll.push_back("a");
m_coll.push_back("test");
}
Nyní můžete testovat kód s klientem podle vašeho výběru.