Partager via


TN039 : Implémentation d'automation MFC/OLE

[!REMARQUE]

La note technique suivante n'a pas été modifiée depuis si c'était première inclus dans la documentation en ligne.Par conséquent, certaines procédures et rubriques peuvent être obsolètes ou incorrects.Pour obtenir les informations les plus récentes, il est recommandé que vous trouviez la rubrique d'intérêt dans l'index de la documentation en ligne.

Vue d'ensemble de la notion interface IDispatch

L'interface d' IDispatch est le mécanisme par lequel les applications exposent des méthodes et des propriétés de sorte que d'autres applications telles que Visual Basic, ou d'autres langages, peuvent utiliser les fonctionnalités de l'application.La plus importante de cette interface est la fonction d' IDispatch::Invoke .MFC utilise des « tables de dispatch » pour implémenter IDispatch::Invoke.La table de dispatch fournit des informations d'implémentation MFC dans la disposition ou « forme » de votre CCmdTargetclasses dérivées, telles qu'elle peut manipuler directement les propriétés de l'objet, ou appeler des fonctions membres dans votre objet pour satisfaire les demandes d' IDispatch::Invoke .

Pour la plupart, l'assistant classe et MFC coopèrent pour masquer la plupart des détails d'OLE automation du programmeur d'application.Le programmeur se concentre sur la fonctionnalité réelle pour exposer dans l'application et ne doit pas à vous préoccuper de les fondations sous-jacente.

Dans certains cas, toutefois, où il est nécessaire de comprendre ce que MFC procède en arrière-plan.Cette remarque présente comment l'infrastructure assigne DISPIDs aux fonctions membres et aux propriétés.Une connaissance MFC utilise l'algorithme pour assigner DISPIDs est uniquement requis lorsque vous devez connaître les ID, par exemple lorsque vous créez une « bibliothèque de types » pour les objets de votre application.

Assignation de MFC DISPID

Bien que l'utilisateur de l'automation (un utilisateur Visual Basic, par exemple), façon dont les noms réels des propriétés activées et méthodes automation dans leur code (tel qu'obj.ShowWindow), l'implémentation de IDispatch::Invoke n'accepte pas les noms réels.Pour des raisons d'optimisation, il reçoit DISPID, qui est « un cookie magique » 32 bits qui décrit la méthode ou la propriété qui doivent être accessibles.Ces valeurs de DISPID sont retournées de l'implémentation d' IDispatch via une autre méthode, IDispatch::GetIDsOfNamesappelé.Une application cliente Automation appelle GetIDsOfNames une fois pour chaque membre ou propriété qu'il vise à accéder, et les mettre en cache pour les appels ultérieurs à IDispatch::Invoke.De cette façon, la recherche économique de chaîne est effectuée uniquement une fois par l'utilisation des objets, au lieu d ' une fois par appel d' IDispatch::Invoke .

MFC détermine DISPIDs pour chaque méthode et propriété en fonction de deux opérations :

  • La distance entre le haut de la table de dispatch (1 parent)

  • La distance de la table de dispatch de la classe la plus dérivée (0 parents)

DISPID est divisé en deux parties.LOWORD de DISPID contient le premier composant, la distance entre le haut de la table de dispatch.HIWORD contient la distance de la classe la plus dérivée.Par exemple :

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()

Comme vous pouvez le constater, il existe deux classes, qui exposent de interfaces OLE Automation.Une de ces classes sont dérivées de l'autre et tire parti de la fonctionnalité de classe de base, y compris la notion de partie d'automation (propriétés « x » et « y » dans ce cas).

MFC génère DISPIDs pour la classe CDispPoint comme suit :

property X    (DISPID)0x00000001
property Y    (DISPID)0x00000002

Étant donné que les propriétés ne sont pas dans une classe de base, HIWORD de DISPID est toujours zéro (la distance de la classe la plus dérivée dans CDispPoint est zéro).

MFC génère DISPIDs pour la classe CDisp3DPoint comme suit :

property Z    (DISPID)0x00000001
property X    (DISPID)0x00010001
property Y    (DISPID)0x00010002

La propriété Z est fournie DISPID avec HIWORD zéro étant donné qu'elle est définie dans la classe qui expose les propriétés, CDisp3DPoint.Depuis les propriétés de X et y sont définis dans une classe de base, HIWORD de DISPID est 1, étant donné que la classe dans laquelle ces propriétés sont définies est à une distance d'une dérivation de la classe la plus dérivée.

[!REMARQUE]

LOWORD est toujours déterminé par la position dans le mappage, même s'il existe des entrées dans le mappage avec DISPID explicite (consultez la section suivante pour plus d'informations sur les versions de _ID des macros d' DISP_PROPERTY et d' DISP_FUNCTION ).

Fonctionnalités avancées de table de dispatch MFC

Il existe de nombreuses fonctionnalités supplémentaires que l'assistant classe ne prend pas en charge avec cette version de Visual C++.Assistant classe prend en charge DISP_FUNCTION, DISP_PROPERTY, et DISP_PROPERTY_EX qui définissent une méthode, une propriété de variable membre, et un get/une propriété fonction membre d'ensemble, respectivement.Ces fonctions sont généralement toutes ce qui sont nécessaires pour créer la plupart des serveurs Automation.

Les macros supplémentaires suivantes peuvent être utilisées lorsque les macros prises en charge par l'assistant classe ne sont pas adéquates : DISP_PROPERTY_NOTIFY, et DISP_PROPERTY_PARAM.

DISP PROPERTY NOTIFY - macro description

DISP_PROPERTY_NOTIFY( 
   theClass, 
   pszName, 
   memberName, 
   pfnAfterSet, 
   vtPropType 
)

Remarques

w7a36sdf.collapse_all(fr-fr,VS.110).gifParamètres

  • theClass
    Nom de la classe.

  • pszName
    Nom externe de la propriété.

  • memberName
    Nom de la variable membre dans laquelle la propriété est stockée.

  • pfnAfterSet
    Nom de la fonction membre à appeler lorsque la propriété est modifiée.

  • vtPropType
    Une valeur spécifiant le type de propriété.

Remarques

Cette macro est très comparable à DISP_PROPERTY, excepté qu'elle accepte un argument supplémentaire.L'argument supplémentaire, pfnAfterSet, doit être une fonction membre qui ne retourne aucune opération et n'accepte aucun paramètre, « OnPropertyNotify() void ».Il sera appelé après que la variable membre a été modifiée.

DISP PROPERTY PARAM - macro description

DISP_PROPERTY_PARAM( 
   theClass,
   pszName,
   pfnGet,
   pfnSet,
   vtPropType,
   vtsParams 
)

Remarques

w7a36sdf.collapse_all(fr-fr,VS.110).gifParamètres

  • theClass
    Nom de la classe.

  • pszName
    Nom externe de la propriété.

  • memberGet
    Nom de la fonction membre utilisée pour obtenir la propriété.

  • memberSet
    Le nom de la fonction membre définissait la propriété.

  • vtPropType
    Une valeur spécifiant le type de propriété.

  • vtsParams
    Une chaîne de VTS_ séparé par des espaces pour chaque paramètre.

Remarques

À l'instar de la macro d' DISP_PROPERTY_EX , cette macro définit une propriété accessible avec l'option d'obtention séparé et les fonctions membres définies.Cette macro, toutefois, vous permet de spécifier une liste de paramètres pour la propriété.Ceci est utile pour implémenter des propriétés qui sont indexées paramétrées ou d'une autre manière.Les paramètres toujours seront placés en premier, suivi de la nouvelle valeur à la propriété.Par exemple :

DISP_PROPERTY_PARAM(CMyObject, "item", GetItem, SetItem, VT_DISPATCH,    VTS_I2 VTS_I2)

correspondrait pour obtenir et définir des fonctions membres :

LPDISPATCH CMyObject::GetItem(short row, short col)
void CMyObject::SetItem(short row, short col, LPDISPATCH newValue)

- Macro descriptions

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 
)

Remarques

w7a36sdf.collapse_all(fr-fr,VS.110).gifParamètres

  • theClass
    Nom de la classe.

  • pszName
    Nom externe de la propriété.

  • dispid
    Le DISPID modifiable de la propriété ou la méthode.

  • pfnGet
    Nom de la fonction membre utilisée pour obtenir la propriété.

  • pfnSet
    Le nom de la fonction membre définissait la propriété.

  • memberName
    Le nom de la variable membre à mapper à la propriété

  • vtPropType
    Une valeur spécifiant le type de propriété.

  • vtsParams
    Une chaîne de VTS_ séparé par des espaces pour chaque paramètre.

Remarques

Ces macros permettent de spécifier DISPID au lieu de laisser MFC assignent automatiquement un.Ces macros avancées ont le même nom mais l'ID est ajouté au nom de la macro (par exemple.DISP_PROPERTY_ID) et l'ID est déterminé par le paramètre spécifié juste après le paramètre d' pszName .Consultez l'AFXDISP.H pour plus d'informations sur ces macros.Les entrées de _ID doivent être placées à la fin de la table de dispatch.Elles peuvent affecter la génération automatique de DISPID de la même façon qu'une version non de**_ID** de la macro ( DISPIDs sont déterminés par position).Par exemple :

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()

MFC génère les dispid pour la classe CDisp3DPoint comme suit :

property X    (DISPID)0x00020003
property Y    (DISPID)0x00000002
property Z     (DISPID)0x00000001

Spécifier DISPID fixe est utile pour des raisons de compatibilité descendante à une interface de dispatch précédemment existante, ou pour implémenter certain système a défini les méthodes et les propriétés (généralement indiquées par DISPIDnégatif, telles que la collection de DISPID_NEWENUM ).

w7a36sdf.collapse_all(fr-fr,VS.110).gifRécupérer l'interface IDispatch pour un COleClientItem

De nombreux serveurs prennent en charge l'automation dans leurs objets document, avec OLE fonctionnalités serveur.Pour accéder à cette interface Automation, il est nécessaire d'accéder directement à la variable membre de COleClientItem::m_lpObject .Le code ci-dessous extrait l'interface d' IDispatch pour un objet dérivé d' COleClientItem.Vous pouvez inclure le code ci-dessous dans votre application si vous recherchez cette fonctionnalité besoins :

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

L'interface de dispatch retournée par cette fonction peut ensuite être utilisée directement ou jointe à COleDispatchDriver pour l'accès de type sécurisé.Si vous utilisez directement, assurez -vous que vous appelez son membre de Release lorsque via avec le pointeur (le destructeur d' COleDispatchDriver fait par défaut).

Voir aussi

Autres ressources

Notes techniques de nombres

Notes techniques de catégorie