Condividi tramite


TN039: implementazione di automazione di MFC/OLE

[!NOTA]

La seguente nota tecnica non è stata aggiornata dalla prima volta che viene inclusa nella documentazione online.Di conseguenza, alcune procedure e argomenti potrebbero non essere aggiornati o errati.Per le informazioni più recenti, è consigliabile cercare l'argomento di interesseindice della documentazione online.

Panoramica dell'interfaccia IDispatch OLE

L'interfaccia di IDispatch è il modo in cui le applicazioni espongono metodi e le proprietà in modo che le altre applicazioni in Visual Basic, o altri linguaggi, possono utilizzare le funzionalità dell'applicazione.La parte più importante di questa interfaccia è la funzione di IDispatch::Invoke .MFC utilizza “le mappe di invio„ per implementare IDispatch::Invoke.La mappa submit fornisce informazioni sull'implementazione mfc nel layout o su “forma„ del CCmdTargetalle classi derivate, in modo che possibile modificare direttamente le proprietà dell'oggetto, o chiama le funzioni membro all'interno dell'oggetto per soddisfare le richieste di IDispatch::Invoke .

In genere, ClassWizard e MFC prevedono per nascondere la maggior parte dei dettagli di automazione OLE dal programmatore di applicazione.Il programmatore è incentrato sulla funzionalità per esporre nell'applicazione e non è necessario preoccuparsi del modello grid idraulico sottostante.

Vi sono casi, tuttavia, dove è necessario capire cosa MFC esegue automaticamente.Questa nota si farà riferimento a nel framework assegna DISPIDoggetti alle funzioni membro e proprietà.La conoscenza di utilizza l'algoritmo MFC per assegnare DISPIDgli oggetti è necessaria solo quando è necessario conoscere gli ID, ad esempio quando si crea una “libreria dei tipi„ per gli oggetti dell'applicazione.

assegnazione di MFC DISPID

Sebbene l'utente finale di automazione (un utente di Visual Basic, ad esempio, vedere i nomi effettivi delle proprietà animate automazione i metodi e nel codice (ad esempio obj.ShowWindow), l'implementazione di IDispatch::Invoke non riceve i nomi effettivi.Per motivi di ottimizzazione, riceve DISPID, che è un 32 bit “cookie magiche„ che descrive il metodo o la proprietà che è necessario accedervi.Questi valori di DISPID vengono restituiti dall'implementazione di IDispatch con un altro metodo, chiamato IDispatch::GetIDsOfNames.Un'applicazione client di automazione chiamerà una volta GetIDsOfNames per ogni membro o proprietà che intende accedere e li memorizza nella cache per le chiamate successive a IDispatch::Invoke.In questo modo, la ricerca nella stringa viene eseguita solo una volta per l'utilizzo dell'oggetto, anziché una volta per chiamata di IDispatch::Invoke .

MFC determina DISPIDs per ogni metodo e proprietà basati su due fattori:

  • La distanza dall'inizio della mappa di invio (1) relativo

  • La distanza della mappa di invio dalla maggior parte della classe derivata (0 parenti)

DISPID viene diviso in due parti.LOWORD di DISPID contiene la prima parte, la distanza dall'inizio della mappa di invio.HIWORD contiene la distanza dalla maggior parte della classe derivata.Di seguito è riportato un esempio:

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

Come si può notare, esistono due classi, entrambi espongono le interfacce di automazione OLE.Una di queste classi è derivata dall'altro e così sfrutta le funzionalità della classe base, inclusa la parte di automazione OLE (proprietà y “e„ x in questo caso).

MFC genererà DISPIDoggetti per classe CDispPoint come segue:

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

Poiché le proprietà non sono in una classe base, HIWORD di DISPID è sempre zero (la distanza dalla maggior parte della classe derivata per CDispPoint è zero).

MFC genererà DISPIDoggetti per classe CDisp3DPoint come segue:

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

La proprietà Z viene fornita DISPID con HIWORD zero poiché è definita nella classe che si sta esponendo le proprietà, CDisp3DPoint.La X le proprietà e Y viene definito in una classe base, HIWORD di DISPID è 1, la classe in cui tali proprietà sono definite corrisponde a una distanza di una derivazione dalla maggior parte della classe derivata.

[!NOTA]

LOWORD è determinato sempre dalla posizione nel mapping, anche se esiste alcuna voce nella mappa con DISPID esplicito (vedere la sezione successiva per informazioni sulle versioni di _ID delle macro di DISP_FUNCTION e di DISP_PROPERTY ).

Funzionalità avanzate della mappa di invio MFC

Esistono numerose funzionalità aggiuntive che ClassWizard non supporta con questa versione di Visual C++.ClassWizard supporta DISP_FUNCTION, DISP_PROPERTYe DISP_PROPERTY_EX che definiscono un metodo, una proprietà delle variabili membro e ottengono/una proprietà funzione del membro del gruppo, rispettivamente.Queste funzionalità sono in genere tutte che siano necessarie per creare la maggior parte dei server di automazione.

Nell'esempio di macro aggiuntive possono essere utilizzate quando macro supportate di ClassWizard non sono appropriate: DISP_PROPERTY_NOTIFYe DISP_PROPERTY_PARAM.

DISP PROPERTY NOTIFY - macro descrizione

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

Note

w7a36sdf.collapse_all(it-it,VS.110).gifParametri

  • theClass
    Nome della classe.

  • pszName
    Nome esterno della proprietà.

  • memberName
    Nome della variabile membro in cui la proprietà viene archiviata.

  • pfnAfterSet
    Nome della funzione membro per chiamare quando la proprietà viene modificata.

  • vtPropType
    Un valore che specifica il tipo della proprietà.

Note

Questa macro è molto simile a DISP_PROPERTY, con la differenza che accetta un argomento aggiuntivo.L'argomento aggiuntivo, pfnAfterSet, deve essere una funzione membro che non restituisce alcun e non accetta parametri, “OnPropertyNotify void ()„.Verrà chiamato dopo che la variabile membro è stato modificato.

DISP PROPERTY PARAM - macro descrizione

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

Note

w7a36sdf.collapse_all(it-it,VS.110).gifParametri

  • theClass
    Nome della classe.

  • pszName
    Nome esterno della proprietà.

  • memberGet
    Nome della funzione membro utilizzata per ottenere la proprietà.

  • memberSet
    Il nome della funzione membro ha utilizzato per impostare la proprietà.

  • vtPropType
    Un valore che specifica il tipo della proprietà.

  • vtsParams
    Una serie di spazio separati VTS_ per ogni parametro.

Note

Analogamente alla macro di DISP_PROPERTY_EX , questa macro viene definita una proprietà accede con separato funzioni membro del gruppo e ottiene.Questa macro, tuttavia, consente di specificare un elenco di parametri per la proprietà.Ciò è utile per implementare le proprietà che vengono indicizzate o con parametri in altro modo.I parametri vengono sempre inseriti per primo, seguito dal nuovo valore per la proprietà.Di seguito è riportato un esempio:

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

corrispondono a per ottenere e funzioni membro del gruppo:

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

- Macro descrizioni

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 
)

Note

w7a36sdf.collapse_all(it-it,VS.110).gifParametri

  • theClass
    Nome della classe.

  • pszName
    Nome esterno della proprietà.

  • dispid
    Il DISPID fisso per la proprietà o il metodo.

  • pfnGet
    Nome della funzione membro utilizzata per ottenere la proprietà.

  • pfnSet
    Il nome della funzione membro ha utilizzato per impostare la proprietà.

  • memberName
    Il nome della variabile membro per eseguire il mapping alla proprietà

  • vtPropType
    Un valore che specifica il tipo della proprietà.

  • vtsParams
    Una serie di spazio separati VTS_ per ogni parametro.

Note

Queste macro consentono di specificare DISPID anziché lasciare MFC automaticamente assegnare uno.Queste macro avanzate hanno gli stessi nomi con la differenza che l'ID viene accodato al nome della macro (ad esempioDISP_PROPERTY_ID) e l'ID è determinato dal parametro specificato immediatamente dopo il parametro di pszName .vedere AFXDISP.H per ulteriori informazioni su queste macro.Le voci di _ID devono essere inserite alla fine della mappa di invio.Avranno effetto sulla generazione automatica di DISPID come una versione non di**_ID** della macro ( DISPIDgli oggetti è determinato dalla posizione).Di seguito è riportato un esempio:

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 genera i dispid per classe CDisp3DPoint come segue:

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

Specificare DISPID fisso è utile mantenere la compatibilità con le versioni precedenti a un'interfaccia dispatch già esistente, o ai metodi definiti o le proprietà di un determinato sistema di utilizzo (in genere indicati da DISPIDnegativo, ad esempio la raccolta di DISPID_NEWENUM ).

w7a36sdf.collapse_all(it-it,VS.110).gifrecuperare l'interfaccia IDispatch per un COleClientItem

Molti server supportano l'automazione all'interno degli oggetti documento, con la funzionalità del server OLE.Per accedere a questa interfaccia di automazione, è necessario direttamente da accedere alla variabile membro di COleClientItem::m_lpObject .Il codice riportato di seguito vengono recuperati l'interfaccia di IDispatch per un oggetto derivato da COleClientItem.È possibile includere il codice riportato di seguito nell'applicazione se si verifica questa funzionalità necessarie:

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'interfaccia dispatch restituita dalla funzione può quindi essere utilizzata direttamente o essere associata a COleDispatchDriver per l'accesso indipendente dai tipi.Se si utilizza direttamente, assicurarsi di chiamare il relativo membro di Release quando tramite con il puntatore (il distruttore di COleDispatchDriver questa operazione viene eseguita per impostazione predefinita).

Vedere anche

Altre risorse

Note tecniche del numero

Note tecniche per categoria