TN039: MFC/OLE – implementace automatizace
[!POZNÁMKA]
Následující technická poznámka nebyla aktualizována, protože byla poprvé zahrnuta v dokumentaci online.V důsledku toho některé postupy a témata mohou být nesprávné nebo zastaralé.Pro nejnovější informace je vhodné vyhledat téma zájmu v dokumentaci online index.
Přehled rozhraní OLE IDispatch
IDispatch Rozhraní je prostředkem, jímž vystavit aplikací metody a vlastnosti, které jsou takové, které jinými aplikacemi, například Visual BASIC nebo v jiných jazycích, můžete použít funkce aplikace.Nejdůležitější součástí tohoto rozhraní je volání metody IDispatch::Invoke funkce.Knihovna MFC používá "odeslání mapy" implementovat volání metody IDispatch::Invoke.Odeslání mapy obsahuje informace o implementaci knihovny MFC rozložení nebo "tvar" v CCmdTarget-odvozené třídy, tak, že může přímo pracovat s vlastnostmi objektu, nebo volat členské funkce v rámci vašeho objektu k uspokojení volání metody IDispatch::Invoke požadavky.
ClassWizard a knihovny MFC z větší části spolupracovat skrýt většinu detailů automatizace OLE z programátor aplikace.Programátor soustřeďuje na skutečné funkce v aplikaci zpřístupnit a nemá starosti o základní domovní instalace.
Existují případy, ale kde je třeba pochopit, co probíhá na pozadí knihovny MFC.Tato poznámka se zaměří jak rámci přiřadí DISPIDs členské funkce a vlastnosti.Znalost MFC používá pro přiřazování algoritmus DISPIDs je nezbytné pouze v případě, že potřebujete znát ID, například při vytváření knihovny"typ" pro objekty aplikace.
Přiřazení DISPID knihovny MFC
Ačkoli automatizace (Visual Basic uživatele, například), koncový uživatel vidí skutečné názvy povolena automatizace vlastností a metod v jejich kódu (například objektu vývoz.ShowWindow) provádění volání metody IDispatch::Invoke nepřijímá skutečná jména.Z důvodu optimalizace dostane DISPID, což je 32-bit "magic cookie" popisující metodu nebo vlastnost, která je přístupná.Tyto DISPID hodnoty jsou vráceny z IDispatch implementace prostřednictvím jiné metody, nazvaný funkce IDispatch::GetIDsOfNames.Automatizace aplikace klient zavolá GetIDsOfNames jednou pro každý člen nebo vlastnost hodlá získat přístup a je v mezipaměti pro pozdější volání volání metody IDispatch::Invoke.Tímto způsobem vyhledávací řetězec nákladné se provádí pouze jednou za použití objektu namísto jednou za volání metody IDispatch::Invoke volání.
Určuje knihovnu MFC DISPIDs pro jednotlivé metody a vlastnosti založené na dvě věci:
Vzdálenost od horního okraje mapy odesílaní (1 relativní)
Vzdálenost mapě odeslání z nejvíce odvozené třídy (0 relativní)
DISPID je rozdělena do dvou částí.LOWORD ze DISPID obsahuje první komponenta je vzdálenost od horní části mapy odeslání.HIWORD obsahuje vzdálenost od Většina odvozených tříd.Příklad:
class CDispPoint : public CCmdTarget
{
public:
short m_x, m_y;
...
DECLARE_DISPATCH_MAP()
...
};
class CDisp3DPoint : public CDispPoint
{
public:
short m_z;
...
DECLARE_DISPATCH_MAP()
...
};
BEGIN_DISPATCH_MAP(CDispPoint, CCmdTarget)
DISP_PROPERTY(CDispPoint, "x", m_x, VT_I2)
DISP_PROPERTY(CDispPoint, "y", m_y, VT_I2)
END_DISPATCH_MAP()
BEGIN_DISPATCH_MAP(CDisp3DPoint, CDispPoint)
DISP_PROPERTY(CDisp3DPoint, "z", m_z, VT_I2)
END_DISPATCH_MAP()
Jak vidíte, existují dvě třídy, které poskytují rozhraní automatizace OLE.Jednu z těchto tříd je odvozen od druhého a tedy využívá funkce základní třídy, včetně části automatizace OLE ("x" a "y" v tomto případě vlastnosti).
MFC bude generovat DISPIDs pro třídu CDispPoint takto:
property X (DISPID)0x00000001
property Y (DISPID)0x00000002
Vzhledem k tomu, že vlastnosti nejsou v základní třídě HIWORD ze DISPID je vždy nula (vzdálenost od Většina odvozených tříd pro CDispPoint je nula).
MFC bude generovat DISPIDs pro třídu CDisp3DPoint takto:
property Z (DISPID)0x00000001
property X (DISPID)0x00010001
property Y (DISPID)0x00010002
Vlastnost je uveden DISPID s nulou HIWORD vzhledem k tomu, že je definována ve třídě, která vystavuje vlastnosti CDisp3DPoint.Vzhledem k tomu, že vlastnosti X a Y jsou definovány v základní třídě HIWORD ze DISPID je 1, protože je třída, která tyto vlastnosti jsou definovány ve vzdálenosti jeden odvození z nejvíce odvozené třídy.
[!POZNÁMKA]
LOWORD je vždy určena pozice v mapě, i když existují položky v mapě s explicitní DISPID (Další informace naleznete na _ID verze DISP_PROPERTY a DISP_FUNCTION makra).
Rozšířené funkce mapy odeslání knihovny MFC
Existuje několik dalších funkcí, které nepodporuje ClassWizard pomocí této verze aplikace Visual C++.ClassWizard podporuje DISP_FUNCTION, DISP_PROPERTY, a DISP_PROPERTY_EX která definují, metody, proměnné vlastnost člena a vlastnost funkce get a set členů, v uvedeném pořadí.Tyto možnosti jsou obvykle stačí k vytvoření většiny automatizační servery.
Následující další makra lze použít, pokud ClassWizard podporuje makra nejsou dostatečné: DISP_PROPERTY_NOTIFY, a DISP_PROPERTY_PARAM.
DISP_PROPERTY_NOTIFY – Popis makra
DISP_PROPERTY_NOTIFY(
theClass,
pszName,
memberName,
pfnAfterSet,
vtPropType
)
Poznámky
Parametry
theClass
Název třídy.pszName
Externí název vlastnosti.memberName
Název přidávané členské proměnné, ve kterém jsou uloženy vlastnosti.pfnAfterSet
Název členské funkce pro volání, pokud je změněna vlastnost.vtPropType
Hodnota, která určuje typ vlastnosti.
Poznámky
Toto makro je velmi podobný DISP_PROPERTY, s tím rozdílem, že přijme další argument.Další argument, pfnAfterSet, by měla být členská funkce, která vrátí nothing a nepřebírá žádné parametry "void OnPropertyNotify()".Bude mít název Po byl změněn členské proměnné.
DISP_PROPERTY_PARAM – Popis makra
DISP_PROPERTY_PARAM(
theClass,
pszName,
pfnGet,
pfnSet,
vtPropType,
vtsParams
)
Poznámky
Parametry
theClass
Název třídy.pszName
Externí název vlastnosti.memberGet
Název členskou funkci získat vlastnost použita.memberSet
Název členské funkce slouží k nastavení vlastnosti.vtPropType
Hodnota, která určuje typ vlastnosti.vtsParams
Místa řetězec oddělený VTS_ pro každý parametr.
Poznámky
Podobně jako DISP_PROPERTY_EX makro, toto makro definuje vlastnosti přistupovat pomocí samostatné členské funkce Get a Set.Toto makro však umožňuje zadat seznam parametrů pro vlastnost.To je užitečné pro implementaci vlastností, které jsou indexovány nebo Parametrizovaná jiným způsobem.Parametry budou vždy umístěny první, následovaný novou hodnotu pro vlastnost.Příklad:
DISP_PROPERTY_PARAM(CMyObject, "item", GetItem, SetItem, VT_DISPATCH, VTS_I2 VTS_I2)
odpovídá get a set funkce členů:
LPDISPATCH CMyObject::GetItem(short row, short col)
void CMyObject::SetItem(short row, short col, LPDISPATCH newValue)
DISP_XXXX_ID – Popis makra
DISP_FUNCTION_ID(
theClass,
pszName,
dispid,
pfnMember,
vtRetVal,
vtsParams
)
DISP_PROPERTY_ID(
theClass,
pszName,
dispid,
memberName,
vtPropType
)
DISP_PROPERTY_NOTIFY_ID(
theClass,
pszName,
dispid,
memberName,
pfnAfterSet,
vtPropType
)
DISP_PROPERTY_EX_ID(
theClass,
pszName,
dispid,
pfnGet,
pfnSet,
vtPropType
)
DISP_PROPERTY_PARAM_ID(
theClass,
pszName,
dispid,
pfnGet,
pfnSet,
vtPropType,
vtsParams
)
Poznámky
Parametry
theClass
Název třídy.pszName
Externí název vlastnosti.dispid
Pevné DISPID pro vlastnost nebo metodu.pfnGet
Název členskou funkci získat vlastnost použita.pfnSet
Název členské funkce slouží k nastavení vlastnosti.memberName
Název přidávané členské proměnné mapovat vlastnostvtPropType
Hodnota, která určuje typ vlastnosti.vtsParams
Místa řetězec oddělený VTS_ pro každý parametr.
Poznámky
Tato makra umožňují zadat DISPID Neumožnit MFC automaticky přiřadit.Tyto rozšířené makra mají stejné názvy, s tím rozdílem, že ID je připojen název makra (např.)DISP_PROPERTY_ID) a ID je určen parametr zadán hned za pszName parametr.Viz AFXDISP.H Další informace o těchto makrech._ID položky musí být umístěn na konci mapy odeslání.Ovlivňují automatické DISPID generace stejným způsobem jako non -_ID verzi makra by ( DISPIDs jsou určeny pozice).Příklad:
BEGIN_DISPATCH_MAP(CDisp3DPoint, CCmdTarget)
DISP_PROPERTY(CDisp3DPoint, "y", m_y, VT_I2)
DISP_PROPERTY(CDisp3DPoint, "z", m_z, VT_I2)
DISP_PROPERTY_ID(CDisp3DPoint, "x", 0x00020003, m_x, VT_I2)
END_DISPATCH_MAP()
Knihovna MFC se generují hodnoty dispID pro třídu CDisp3DPoint takto:
property X (DISPID)0x00020003
property Y (DISPID)0x00000002
property Z (DISPID)0x00000001
Určení pevným DISPID je vhodné udržovat zpětnou kompatibilitu pro dřívější odesílající rozhraní nebo implementaci některých systém definice metody nebo vlastnosti (obvykle označen negativní DISPID, jako DISPID_NEWENUM kolekce).
Načtení rozhraní IDispatch COleClientItem
Mnoho serverů bude podporovat v rámci svých objektů dokumentu, spolu s funkcí serveru OLE automation.Získat přístup k rozhraní pro automatizaci, je nezbytné pro přímý přístup COleClientItem::m_lpObject členské proměnné.Následující kód načte IDispatch rozhraní pro objekt odvozené z COleClientItem.V aplikaci můžete zahrnout následující kód nezbytné najít tuto funkci:
LPDISPATCH CMyClientItem::GetIDispatch()
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
LPUNKNOWN lpUnk = m_lpObject;
Run(); // must be running
LPOLELINK lpOleLink = NULL;
if (m_lpObject->QueryInterface(IID_IOleLink,
(LPVOID FAR*)&lpOleLink) == NOERROR)
{
ASSERT(lpOleLink != NULL);
lpUnk = NULL;
if (lpOleLink->GetBoundSource(&lpUnk) != NOERROR)
{
TRACE0("Warning: Link is not connected!\n");
lpOleLink->Release();
return NULL;
}
ASSERT(lpUnk != NULL);
}
LPDISPATCH lpDispatch = NULL;
if (lpUnk->QueryInterface(IID_IDispatch, &lpDispatch)
!= NOERROR)
{
TRACE0("Warning: does not support IDispatch!\n");
return NULL;
}
ASSERT(lpDispatch != NULL);
return lpDispatch;
}
Odesílající rozhraní vrátil tuto funkci potom může přímo použít nebo připojené k COleDispatchDriver pro bezpečný přístup.Pokud můžete použít přímo, ujistěte se, že volání jeho vydání člen kdy prostřednictvím ukazatel ( COleDispatchDriver destruktor to nemá ve výchozím nastavení).