TN039: MFC/OLE Automation attuazione

Panoramica dell'interfaccia IDispatch OLE

L'interfaccia IDispatch è il mezzo da cui applicazioni espongono metodi e le proprietà tali che le altre applicazioni quali Visual BASIC o altre lingue, possono fare uso delle funzionalità dell'applicazione. La parte più importante di questa interfaccia è la funzione di se . MFC utilizza "mappe della spedizione" per implementare se. Mappa di invio del fornisce le informazioni di implementazione MFC sul layout o "forma" del vostro CCmdTarget-classi, derivate tale che può direttamente manipolare le proprietà dell'oggetto oppure chiamare membri funzioni all'interno del tuo oggetto per soddisfare le richieste se.

Per la maggior parte, ClassWizard e MFC cooperare per nascondere la maggior parte dei dettagli di automazione OLE da programmatore di applicazione. Il programmatore si concentra sulla effettiva funzionalità per esporre nell'applicazione e non devi preoccuparti dell'impianto idraulico sottostante.

Ci sono casi, tuttavia, dove è necessario per capire che cosa sta facendo MFC dietro le quinte. Questa nota affronterà come quadro assegna DISPIDs alla proprietà e funzioni membro. Conoscenza dell'algoritmo che MFC viene utilizzata per assegnare DISPIDs è necessario solo quando è necessario conoscere gli ID, ad esempio quando si crea un "type library" per gli oggetti dell'applicazione.

Assegnazione DISPID MFC

Anche se l'utente finale di automazione (un Visual Basic utente, ad esempio), vede i nomi reali di automazione abilitato proprietà e i metodi nel loro codice (ad esempio obj.ShowWindow), l'implementazione di se non riceve i veri nomi. Per motivi di ottimizzazione, riceve un DISPID, che è a 32-bit "magico cookie" che descrive il metodo o proprietà ovvero a cui accedere. Questi valori DISPID vengono restituiti dall'implementazione IDispatch tramite un altro metodo, chiamato GetIDsOfNames. Un'applicazione client di automazione chiamare GetIDsOfNames una volta per ogni membro o proprietà che intende accedere e memorizzare nella cache per le successive chiamate a se. In questo modo, la ricerca della stringa costoso solo verrà eseguita una volta per uso oggetto, anziché una sola volta per ogni chiamata se.

MFC determina la s DISPIDper ogni metodo e proprietà basato su due cose:

Il DISPID è diviso in due parti. Il LOWORD del DISPID contiene il primo componente, la distanza dalla parte superiore della mappa di invio. Il HIWORD contiene la distanza dalla classe più derivata. Ad esempio:

classe CDispPoint: CCmdTarget pubblica
{
pubblica:
 nbsp;  breve m_x, m_y;
    ...
    DECLARE_DISPATCH_MAP()
    ...
};

classe CDisp3DPoint: pubblico CDispPoint
{
pubblica:
    breve m_y;
    ...
    DECLARE_DISPATCH_MAP()
    ...
};

BEGI&N_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 potete vedere, ci sono due classi, entrambi i quali espongono le interfacce di automazione OLE. Una di queste classi è derivata da altra e quindi sfrutta la funzionalità della classe base, compresa la parte di automazione OLE ("x" e "y" proprietà in questo caso).

MFC genererà DISPIDs per la classe CDispPoint come segue:

proprietà X    (DISPID) 0X00000001
Proprietà Y (DISPID) 0x00000002

Poiché le proprietà non sono in una classe base, il HIWORD del DISPID è sempre pari a zero (la distanza tra la classe più derivata per CDispPoint è zero).

MFC genererà DISPIDs per la classe CDisp3DPoint come segue:

proprietà Z    (DISPID) 0X00000001
Proprietà X (DISPID) 0x00010001
Proprietà Y (DISPID) 0x00010002

La proprietà z è dato un DISPID con uno zero HIWORD , dal momento che essa è definita nella classe che espone le proprietà, CDisp3DPoint. Poiché le proprietà x e y sono definite in una classe base, il HIWORD del DISPID è 1, dal momento che la classe in cui queste proprietà sono definite a una distanza di una derivazione dalla classe più derivata.

&Notanbsp;  Il LOWORD è sempre determinato dalla posizione nella mappa, anche se esistono voci della mappa con esplicito DISPID (vedere la sezione successiva per informazioni sulle versioni ID delle macro DISP_PROPERTY e DISP_FUNCTION ).

MFC Dispatch mappa funzionalità avanzate

Ci sono una serie di funzionalità aggiuntive che non supporta ClassWizard con questa versione di Visual C++. ClassWizard supporta DISP_FUNCTION, DISP_PROPERTYe DISP_PROPERTY_EX che definire un metodo, proprietà variabile membro e proprietà di funzione membro get/set, rispettivamente. Queste funzionalità sono di solito tutto ciò che è necessario per creare la maggior parte dei server di automazione.

Le seguenti macro supplementare possono essere utilizzate quando le macro ClassWizard supportati non sono sufficienti: DISP_PROPERTY_NOTIFYe DISP_PROPERTY_NOTIFY.

DISP_PROPERTY_NOTIFY — Macro descrizione

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

theClass

Nome della classe.

pszName

Nome esterno della proprietà.

memberName

Nome della variabile membro in cui la proprietà è memorizzata.

pfnAfterSet

Nome della funzione membro da chiamare quando viene modificata la proprietà.

vtPropType

Un valore che specifica il tipo della proprietà.

&Notanbsp;  Questa macro è molto simile a DISP_PROPERTY, salvo che accetta un argomento aggiuntivo. L'argomento supplementare, pfnAfterSet, dovrebbe essere una funzione membro che restituisce nothing e non prende parametri, 'void OnPropertyNotify()'. Si chiamerà dopo che è stata modificata la variabile membro.

DISP_PROPERTY_NOTIFY — Macro descrizione

DISP_PROPERTY_NOTIFY (theClass, pszName, pszExternalName, pfnSet, vtPropType, vtsParams)

theClass

Nome della classe.

pszName

Nome esterno della proprietà.

memberGet

Nome della funzione membro utilizzata per ottenere la proprietà.

set di membri

Nome della funzione membro utilizzata per impostare la proprietà.

vtPropType

Un valore che specifica il tipo della proprietà.

vtsParams

Una stringa di spazio separato VTS_ per ogni parametro.

&Notanbsp;  Molto come la macro DISP_PROPERTY_EX , questa macro definisce una proprietà a che cui si accede con distinte funzioni membro Get e Set. Questa macro, tuttavia, consente di specificare un elenco di parametri per la proprietà. Questo è utile per l'implementazione di proprietà che sono indicizzate o parametrizzata in qualche altro modo. I parametri saranno sempre posto in primo luogo, seguito dal nuovo valore per la proprietà. Ad esempio:

DISP_PROPERTY_NOTIFY (CMyObject, "voce", GetItem, SetItem, VT_DISPATCH, VTS_I2 VTS_I2)

corrisponderebbe per ottenere e impostare le funzioni membro:

LPDISPATCH CMyObject::GetItem(short row, short col)
public static void CMyObject::SetItem (breve riga, col breve, LPDISPATCH newValue)

DISP_XXXX_ID — 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, pszExternalName, pfnSet, vtPropType)

DISP_PROPERTY_PARAM_ID (theClass, pszName, dispid, pszExternalName, pfnSet, vtPropType, vtsParams)

theClass

Nome della classe.

pszName

Nome esterno della proprietà.

dispid

Il DISPID fisso per la proprietà o il metodo.

pszExternalName

Nome della funzione membro utilizzata per ottenere la proprietà.

pfnSet

Nome della funzione membro utilizzata 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 stringa di spazio separato VTS_ per ogni parametro.

&Notanbsp;  Queste macro consentono di specificare un DISPID invece di lasciare MFC assegnare automaticamente uno. Queste avanzate macro hanno gli stessi nomi, tranne per il fatto che ID viene aggiunto al nome di macro (ad esempio DISP_PROPERTY_ID) e l'ID è determinato dal parametro specificato solo dopo il parametro pszName . Vedere AFXDISP.H per ulteriori informazioni su queste macro. Le voci ID devono essere collocate all'estremità della mappa di invio. Colpiscono la generazione automatica di DISPID nello stesso modo come un non-ID versione della macro sarebbe (il DISPIDs sono determinata dalla posizione). Ad esempio:

BEGI&N_DISPATCH_MAP (CDisp3DPoint, CCmdTarget)
 nbsp;  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 genererà DISPID per classe CDisp3DPoint come segue:

proprietà X    (DISPID) 0X00020003
Proprietà Y (DISPID) 0x00000002
Proprietà Z (DISPID) 0x00000001

Specificando un fisso DISPID è utile per mantenere la compatibilità con versioni precedenti di un'interfaccia dispatch precedentemente esistenti o di implementare determinato sistema definiti metodi o proprietà (di solito indicato da un negativo DISPID, come la raccolta di DISPID_NEWENUM ).

Recuperando l'interfaccia IDispatch per un COleClientItem

Molti server sosterrà automazione all'interno di oggetti loro documento, insieme con le funzionalità del server OLE. Al fine di ottenere l'accesso a questa interfaccia di automazione, è necessario accedere direttamente la variabile membro COleClientItem::m_lpObject . Il codice qui sotto recupererà l'interfaccia IDispatch per un oggetto derivato da COleClientItem. È possibile includere il codice qui sotto nella vostra applicazione se si trova questa funzionalità necessarie

LPDISPATCH CMyClientItem::GetIDispatch()
{
 nbsp;  ASSERT_VALID(this);
    ASSERT (m_lpObject! = NULL);

LPUNKNOWN lpUnk = m_lpObject;

Run ();    / / deve essere in esecuzione

LPOLELINK lpOleLink = NULL;
    Se (m_lpObject - > QueryInterface (IID_IOleLink, (LPVOID estremo *) & lpOleLink) = = NOERROR)
    {
        ASSERT (lpOleLink! = NULL);
        lpUnk = NULL;
        Se (lpOleLink - > GetBoundSource(&lpUnk)! = NOERROR)
        {
            TRACE0 ("Warning: Link non è connesso! \n");
            lpOleLink - > errato;
            return NULL;
        }
        ASSERT (lpUnk! = NULL);
    }

LPDISPATCH lpDispatch = NULL;
    Se (lpUnk - > QueryInterface (IID_IDispatch e lpDispatch)! = NOERROR)
    {
        TRACE0 ("Warning: non supporta IDispatch! \n");
        return NULL;
    }

ASSERT (lpDispatch! = NULL);
    return lpDispatch;
}

L'interfaccia dispatch restituito da questa funzione potrebbe essere utilizzata direttamente o collegata a un COleDispatchDriver per accesso type-safe. Se si utilizza direttamente, assicurarsi di chiamare il suo deputato Release quando attraverso con il puntatore (il distruttore COleDispatchDriver le fa per impostazione predefinita).

&Note tecniche per numero |nbsp; Note tecniche per la categoria

Index