Descripción de la interfaz IDispatch OLE
La interfaz IDispatch es el medio por qué aplicaciones exponer métodos y propiedades tales que otras aplicaciones como Visual BASIC, o en otros idiomas, pueden hacer uso de características de la aplicación. La parte más importante de esta interfaz es la función de IDispatch:: Invoke . MFC utiliza "enviar mapas" para implementar IDispatch:: Invoke. El mapa de envíos proporciona la información de implementación de MFC en el diseño o la "forma" de tu CCmdTarget.-derivadas de clases, que directamente puede manipular las propiedades del objeto, o llamar a funciones dentro de su objeto para satisfacer las solicitudes de IDispatch:: Invoke miembro.
En su mayor parte, ClassWizard y MFC cooperan para ocultar la mayoría de los detalles de automatización OLE desde el programador de aplicaciones. El programador se concentra en la funcionalidad real para exponer en la aplicación y no tiene que preocuparse de la fontanería subyacente.
Hay casos, sin embargo, donde es necesario entender lo que está haciendo MFC detrás de las escenas. Esta nota ocupará de cómo el marco asigna DISPIDs propiedades y funciones miembro. Conocimiento del algoritmo que MFC utiliza para asignar DISPIDs sólo es necesario cuando se necesita conocer los ID, como cuando se crea una "biblioteca de tipo" para los objetos de la aplicación.
Asignación de DISPID de MFC
A pesar de que el usuario final de automatización (Visual Basic usuario, por ejemplo), ve los nombres reales de la automatización activa las propiedades y métodos en su código (por ejemplo, obj.ShowWindow), la implementación de IDispatch:: Invoke no reciben los nombres reales. Por razones de optimización, recibe un DISPID, que es un 32-bit "cookie mágica" que describe el método o propiedad que deba tener acceso. Estos valores DISPID se devuelven desde la implementación de IDispatch mediante otro método, llamado IDispatch:: GetIDsOfNames. Una aplicación de cliente de automatización se llame GetIDsOfNames una vez para cada miembro o propiedad que tiene la intención de acceder y caché para posteriores llamadas a IDispatch:: Invoke. De esta forma, la búsqueda de cadena caro es sólo hacer una vez por uso del objeto, en lugar de una vez por llamada IDispatch:: Invoke.
MFC determina la s DISPIDde cada método y la propiedad basado en dos cosas:
El DISPID se divide en dos partes. El LOWORD de la DISPID contiene el primer componente, la distancia desde la parte superior de la hoja de envío. El HIWORD contiene la distancia desde la clase derivada más. Por ejemplo:
clase CDispPoint: CCmdTarget pública.
{
público:
nbsp; m_x corto, m_y;
...
DECLARE_DISPATCH_MAP()
...
};
clase CDisp3DPoint: CDispPoint pública
{
público:
m_y corto;
...
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()
Como puede ver, hay dos clases, que expongan las interfaces de automatización OLE. Una de estas clases se deriva de la otra y así aprovecha la funcionalidad de la clase base, incluida la parte de automatización OLE ("x" e "y" Propiedades en este caso).
MFC generará el siguiente s DISPIDde clase CDispPoint:
propiedad X (DISPID) 0 X 00000001
propiedad Y (DISPID) 0x00000002
Dado que las propiedades no están en una clase base, el HIWORD de la DISPID siempre es cero (la distancia desde la clase derivada más para CDispPoint es cero).
MFC generará el siguiente s DISPIDde clase CDisp3DPoint:
propiedad Z (DISPID) 0 X 00000001
propiedad X (DISPID) 0x00010001
propiedad Y (DISPID) 00010002
La propiedad z se da un DISPID con un cero HIWORD ya está definida en la clase que está exponiendo las propiedades, CDisp3DPoint. Dado que las propiedades x e y están definidas en una clase base, el HIWORD de la DISPID es 1, ya que la clase en la que se definen estas propiedades está a una distancia de una derivación de la clase derivada más.
&Notanbsp; El LOWORD siempre está determinada por la posición en el mapa, incluso si hay entradas en el mapa con explícita DISPID (consulte la sección siguiente para obtener información sobre las versiones _ID de las macros DISP_PROPERTY y DISP_FUNCTION ).
MFC envío mapa características avanzadas
Hay una serie de características adicionales que no admiten ClassWizard con esta versión de Visual C++. ClassWizard soporta DISP_FUNCTION, DISP_PROPERTYy DISP_PROPERTY_EX que define un método, propiedad variable de miembro y propiedad de función get/set miembros, respectivamente. Estas capacidades suelen ser todo lo que se necesita para crear la mayoría de servidores de automatización.
Pueden utilizarse las siguientes macros adicionales cuando las macros ClassWizard compatible no son suficientes: DISP_PROPERTY_NOTIFYy DISP_PROPERTY_PARAM.
DISP_PROPERTY_NOTIFY: Descripción de la Macro
DISP_PROPERTY_NOTIFY (theClass, pszName, nombreDeUsuario, pfnAfterSet, vtPropType)
theClass
Nombre de la clase.
pszName
Nombre externo de la propiedad.
nombreDeUsuario
Nombre de la variable de miembro en el que se almacena la propiedad.
pfnAfterSet
Nombre de función miembro llamar cuando cambia la propiedad.
vtPropType
Un valor que especifica el tipo de la propiedad.
&Notanbsp; Esta macro es igual que DISP_PROPERTY, excepto que acepta un argumento adicional. El argumento adicional, pfnAfterSet, debe ser una función miembro que devuelve nothing y no toma ningún parámetro, 'void OnPropertyNotify()'. Se llamará después de que la variable miembro se ha modificado.
DISP_PROPERTY_PARAM: Descripción de la Macro
DISP_PROPERTY_PARAM (theClass, pszName, pfnGet, pfnSet, vtPropType, vtsParams)
theClass
Nombre de la clase.
pszName
Nombre externo de la propiedad.
memberGet
Nombre de la función miembro que se utiliza para obtener la propiedad.
conjunto de miembros
Nombre de la función miembro que se utiliza para establecer la propiedad.
vtPropType
Un valor que especifica el tipo de la propiedad.
vtsParams
Una cadena de espacio separado VTS_ para cada parámetro.
&Notanbsp; Mucho como la macro DISP_PROPERTY_EX , esta macro define una propiedad visitada con distintas funciones de miembro de Get y Set. Esta macro, sin embargo, le permite especificar una lista de parámetros para la propiedad. Esto es útil para implementar propiedades indizadas o parametrizadas que de alguna otra manera. Los parámetros siempre se colocará en primer lugar, seguido por el nuevo valor para la propiedad. Por ejemplo:
DISP_PROPERTY_PARAM (CMyObject, "partida", GetItem, SetItem, VT_DISPATCH, VTS_I2 VTS_I2)
correspondería a obtener y establecer funciones miembro:
LPDISPATCH CMyObject::GetItem(short row, short col)
void CMyObject::SetItem (fila corto, corto Collado, LPDISPATCH newValue)
DISP_XXXX_ID: Descripciones de Macro
DISP_FUNCTION_ID (theClass, pszName, dispid, pfnMember, vtRetVal, vtsParams)
DISP_PROPERTY_ID (theClass, pszName, dispid, nombreDeUsuario, vtPropType)
DISP_PROPERTY_NOTIFY_ID (theClass, pszName, dispid, nombreDeUsuario, pfnAfterSet, vtPropType)
DISP_PROPERTY_EX_ID (theClass, pszName, dispid, pfnGet, pfnSet, vtPropType)
DISP_PROPERTY_PARAM_ID (theClass, pszName, dispid, pfnGet, pfnSet, vtPropType, vtsParams)
theClass
Nombre de la clase.
pszName
Nombre externo de la propiedad.
dispid
El DISPID fijo para la propiedad o método.
pfnGet
Nombre de la función miembro que se utiliza para obtener la propiedad.
pfnSet
Nombre de la función miembro que se utiliza para establecer la propiedad.
nombreDeUsuario
El nombre de la variable miembro para asignar a la propiedad
vtPropType
Un valor que especifica el tipo de la propiedad.
vtsParams
Una cadena de espacio separado VTS_ para cada parámetro.
&Notanbsp; Estas macros permiten especificar un DISPID en lugar de dejar que MFC automáticamente asigne uno. Estas avanzadas las macros tienen los mismos nombres, excepto ese ID se anexa al nombre de la macro (por ejemplo, DISP_PROPERTY_ID) y el ID está determinado por el parámetro especificado sólo después del parámetro pszName . Véase AFXDISP.H para obtener más información sobre estas macros. Las entradas _ID deben colocarse al final de la ruta de envío. Afectan la generación automática de DISPID de la misma manera como un no -_ID versión de la macro sería (la s DISPIDestán determinados por la posición). Por ejemplo:
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 generará identificadores DispId de clase CDisp3DPoint como sigue:
propiedad X (DISPID) 0X00020003
propiedad Y (DISPID) 0x00000002
propiedad Z (DISPID) 0 x 00000001
Especificar un fijo DISPID es útil para mantener la compatibilidad con versiones anteriores para una interfaz de envío previamente existentes, o para implementar cierto sistema define métodos o propiedades (generalmente indicadas por una negativa DISPID, tales como la colección de DISPID_NEWENUM ).
Recuperar la interfaz IDispatch para un COleClientItem
Muchos servidores apoyará la automatización dentro de sus objetos de documento, junto con la funcionalidad de servidor OLE. Para acceder a esta interfaz de automatización, es necesario acceder directamente a la variable miembro COleClientItem::m_lpObject . El código siguiente recupera la interfaz IDispatch para un objeto derivado de COleClientItem. Puede incluir el código siguiente en la aplicación si encuentras esta funcionalidad necesaria
LPDISPATCH CMyClientItem::GetIDispatch()
{
nbsp; ASSERT_VALID(this);
ASSERT (m_lpObject! = NULL);
LPUNKNOWN lpUnk = m_lpObject;
Run(); / / debe ejecutar
LPOLELINK lpOleLink = NULL;
Si (m_lpObject - > QueryInterface (IID_IOleLink, (LPVOID lejano **) & lpOleLink) == NOERROR)
{
ASSERT (lpOleLink! = NULL);
lpUnk = NULL;
Si (lpOleLink - > GetBoundSource(&lpUnk)! = NOERROR)
{
TRACE0 ("Advertencia: vínculo no está conectado! \n");
lpOleLink - > Release();
devolver NULL;
}
ASSERT (lpUnk! = NULL);
}
LPDISPATCH lpDispatch = NULL;
Si (lpUnk - > QueryInterface (IID_IDispatch & lpDispatch)! = NOERROR)
{
TRACE0 ("Advertencia: no se admiten IDispatch! \n");
devolver NULL;
}
ASSERT (lpDispatch! = NULL);
Return lpDispatch;
}
La interfaz de envío devuelto por esta función podría utilizar directamente o conectada a un COleDispatchDriver acceso a la seguridad de tipos. Si se utiliza directamente, asegúrese de llamar a sus miembros de lanzamiento cuando mediante con el puntero (el destructor de COleDispatchDriver lo hace por defecto).
&Notas técnicas por número |nbsp; Notas técnicas por categoría