Sdílet prostřednictvím


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 vlastnost

  • vtPropType
    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í).

Viz také

Další zdroje

Technické poznámky podle čísel

Technické poznámky podle kategorií