Visão geral da Interface de IDispatch OLE
A interface de IDispatch é os meios pelos quais aplicativos expõem métodos e propriedades tais que outros aplicativos, como Visual BASIC, ou outros idiomas, podem fazer usam de recursos do aplicativo. A parte mais importante dessa interface é IDispatch:: Invoke função. MFC usa "mapas de expedição" para implementar IDispatch:: Invoke. O mapa de expedição fornece as informações de implementação do MFC no layout ou "forma" de seu CCmdTarget-classes derivadas, tal que ele possa diretamente manipular as propriedades do objeto, ou chamar membro funções dentro de seu objeto para satisfazer às solicitações do IDispatch:: Invoke.
Na maior parte, ClassWizard e MFC cooperarem para ocultar a maioria dos detalhes de automação de OLE do programador de aplicativo. O programador concentra-se na funcionalidade real para expor no aplicativo e não tem que preocupar-se sobre o encanamento subjacente.
Há casos, no entanto, em que é necessário compreender o MFC está fazendo nos bastidores. Esta anotação irá abordar como a estrutura atribui DISPIDs a propriedades e funções de membro. Conhecimento do algoritmo que MFC usa para atribuição de DISPIDs só é necessário quando você precisa conhecer as identificações, como quando você cria uma biblioteca de"tipo" para objetos do seu aplicativo.
Atribuição de DISPID MFC
Embora o usuário final de automação (Visual Basic utilizador, por exemplo), vê os nomes reais da automação habilitada propriedades e métodos em seu código (por exemplo, obj.ShowWindow), a implementação de IDispatch:: Invoke não recebe os nomes reais. Por motivos de otimização, ele recebe um DISPID, que é um 32-bit "mágico cookie" que descreve o método ou propriedade a ser acessado. Esses valores DISPID são retornados da implementação IDispatch por outro método, chamado IDispatch:: GetIDsOfNames. Um aplicativo de cliente de automação irá chamar GetIDsOfNames uma vez para cada membro ou propriedade que pretende acessar e armazenar em cache-los para chamadas posteriores para IDispatch:: Invoke. Desta forma, a pesquisa de Cadeia de caracteres caro é feita apenas uma vez por uso de objeto, em vez de uma vez por IDispatch:: Invoke chamada.
MFC determina o s DISPIDpara cada método e propriedade com base em duas coisas:
O DISPID é dividido em duas partes. O LOWORD do DISPID contém o primeiro componente, a distância da parte superior do mapa de distribuição. O HIWORD contém a distância entre a classe mais derivada. Por exemplo:
classe CDispPoint: público CCmdTarget
{
público:
nbsp; curto m_x, m_y;
...
DECLARE_DISPATCH_MAP()
...
};
classe CDisp3DPoint da: CDispPoint pública
{
público:
m_y curto;
...
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 da, CDispPoint)
DISP_PROPERTY (CDisp3DPoint da, "z", m_z, VT_I2)
END_DISPATCH_MAP()
Como você pode ver, há duas classes, os quais expõem interfaces de automação de OLE. Uma dessas classes é derivada de outro e, assim, aproveita a funcionalidade da classe base, incluindo a parte de automação OLE ("x" e "y" Propriedades neste caso).
MFC gerará DISPIDs para classe CDispPoint da seguinte maneira:
propriedade X (DISPID) 0 X 00000001
Propriedade Y (DISPID) 0 x 00000002
Como as propriedades não estão em uma classe base, o HIWORD do DISPID é sempre zero (a distância entre a classe mais derivada para CDispPoint é zero).
MFC gerará DISPIDs para classe CDisp3DPoint da seguinte maneira:
propriedade Z (DISPID) 0 X 00000001
Propriedade X (DISPID) 0x00010001
Propriedade Y (DISPID) 0x00010002
A propriedade z é dado um DISPID com um zero HIWORD desde que ele é definido na classe que é expor as propriedades, CDisp3DPoint da. Uma vez que as propriedades x e y são definidas em uma classe base, o HIWORD do DISPID é 1, uma vez que a classe na qual essas propriedades são definidas está a uma distância de uma derivação da classe mais derivada.
&Notanbsp; O LOWORD sempre é determinado pela posição no mapa, mesmo se há entradas no mapa com explícito DISPID (consulte a próxima seção para obter informações sobre as versões de ID do DISP_PROPERTY e DISP_FUNCTION macros).
Avançados recursos de mapa de expedição MFC
Há uma série de recursos adicionais que ClassWizard não tem suporte nesta versão do Visual C++. ClassWizard oferece suporte a macro DISP_PROPERTY_EX , que definem um método, propriedade de membro de variável e propriedade de função de membro get/set, respectivamente, DISP_PROPERTYe DISP_FUNCTION. Esses recursos são, geralmente, tudo o que é necessário para criar a maioria dos servidores de automação.
As seguintes macros adicionais podem ser usadas quando as macros ClassWizard suportada não são adequadas: DISP_PROPERTY_NOTIFYe DISP_PROPERTY_PARAM.
DISP_PROPERTY_NOTIFY — Descrição da Macro
DISP_PROPERTY_NOTIFY (theClass, pszName, memberName, pfnAfterSet, vtPropType)
theClass
Nome da classe.
pszName
Nome externo da propriedade.
memberName
Nome da variável de membro no qual a propriedade é armazenada.
pfnAfterSet
Nome da função de membro para chamar quando a propriedade é alterada.
vtPropType
Um valor especificando o tipo da propriedade.
&Notanbsp; Essa macro é muito parecido com DISP_PROPERTY, exceto que ele aceita um argumento adicional. O argumento adicional, pfnAfterSet, deve ser uma função de membro que retorna nada e sem parâmetros, 'void OnPropertyNotify()'. Ele será chamado depois que a variável de membro tiver sido modificada.
DISP_PROPERTY_PARAM — Descrição da Macro
DISP_PROPERTY_PARAM (theClass, pszName, pfnGet, pfnSet, vtPropType, vtsParams)
theClass
Nome da classe.
pszName
Nome externo da propriedade.
memberGet
Nome da função membro usada para obter a propriedade.
conjunto de membros
Nome da função membro usada para definir a propriedade.
vtPropType
Um valor especificando o tipo da propriedade.
vtsParams
Uma Cadeia de caracteres de espaço separados VTS _ para cada parâmetro.
&Notanbsp; Muito como a macro macro DISP_PROPERTY_EX , essa macro define uma propriedade acessada com separado Get e Set funções de membro. Essa macro, no entanto, permite que você especifique uma lista de parâmetro para a propriedade. Isso é útil para implementar propriedades que são indexadas ou parametrizadas de alguma outra forma. Os parâmetros serão sempre colocados em primeiro lugar, seguido pelo novo valor para a propriedade. Por exemplo:
DISP_PROPERTY_PARAM (CMyObject, "item", GetItem, SetItem, VT_DISPATCH, VTS_I2 VTS_I2)
corresponderia a obter e definir funções de membro:
CMyObject::GetItem(short row, short col) LPDISPATCH
void CMyObject::SetItem (linha pequeno, curto col, LPDISPATCH newValue)
DISP_XXXX_ID — As descrições de Macro
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)
theClass
Nome da classe.
pszName
Nome externo da propriedade.
dispid
O DISPID fixo para o método ou propriedade.
pfnGet
Nome da função membro usada para obter a propriedade.
pfnSet
Nome da função membro usada para definir a propriedade.
memberName
O nome da variável membro para mapear a propriedade
vtPropType
Um valor especificando o tipo da propriedade.
vtsParams
Uma Cadeia de caracteres de espaço separados VTS _ para cada parâmetro.
&Notanbsp; Essas macros permitem que você especifique um DISPID em vez de permitir que o MFC atribuir automaticamente um. Estas avançadas macros têm os mesmos nomes, exceto que ID é acrescentada ao nome da macro (por exemplo, DISP_PROPERTY_ID) e a identificação é determinada pelo parâmetro especificado apenas após o pszName parâmetro. Consulte AFXDISP.H para obter mais informações sobre essas macros. As entradas de ID devem ser colocadas no final do mapa de distribuição. Elas irão afetar a geração de automática DISPID da mesma forma como um não-ID versão da macro seria (o s DISPIDsão determinadas pela posição). Por exemplo:
BEGI&N_DISPATCH_MAP (CDisp3DPoint da, CCmdTarget)
nbsp; DISP_PROPERTY (CDisp3DPoint da, "y", m_y, VT_I2)
DISP_PROPERTY (CDisp3DPoint da, "z", m_z, VT_I2)
DISP_PROPERTY_ID (CDisp3DPoint da, "x", 0x00020003, m_x, VT_I2)
END_DISPATCH_MAP()
MFC gerará DISPIDs para classe CDisp3DPoint da seguinte maneira:
propriedade X (DISPID) 0X00020003
Propriedade Y (DISPID) 0 x 00000002
Propriedade Z (DISPID) 0 x 00000001
Especificando um fixo DISPID é útil para manter compatibilidade com versões anteriores para uma interface dispatch previamente existentes, ou para implementar determinado sistema definido métodos ou propriedades (normalmente indicadas por um negativo DISPID, como a coleção DISPID_NEWENUM ).
Recuperar a Interface de IDispatch para um COleClientItem
Número de servidores oferecerá suporte automação dentro de seus objetos de documento, juntamente com a funcionalidade de servidor OLE. Para ter acesso a essa interface de automação, é necessário acessar diretamente a variável de membro COleClientItem::m_lpObject . O código a seguir irá recuperar a interface de IDispatch para um objeto derivado de COleClientItem. Você pode incluir o código abaixo em seu aplicativo se você encontrar esta funcionalidade necessários
CMyClientItem::GetIDispatch() LPDISPATCH
{
nbsp; ASSERT_VALID(this);
ASSERT (m_lpObject! = NULL);
LPUNKNOWN lpUnk = m_lpObject;
Run (); / / deve estar sendo executado
LPOLELINK lpOleLink = NULL;
se (m_lpObject - > falha de QueryInterface (IID_IOleLink, (LPVOID FAR *) & lpOleLink) = = NOERROR)
{
ASSERT (lpOleLink! = NULL);
lpUnk = NULL;
se (lpOleLink - > GetBoundSource(&lpUnk)! = NOERROR)
{
TRACE0 ("aviso: Link não está ligado! \n");
lpOleLink - > Release();
retornar NULL;
}
ASSERT (lpUnk! = NULL);
}
LPDISPATCH lpDispatch = NULL;
se (lpUnk - > falha de QueryInterface (IID_IDispatch & lpDispatch)! = NOERROR)
{
TRACE0 ("aviso: não dá suporte a IDispatch! \n");
retornar NULL;
}
ASSERT (lpDispatch! = NULL);
retornar lpDispatch;
}
A interface dispatch retornado dessa função, em seguida, pode ser usada diretamente ou anexada a um COleDispatchDriver para acessar de tipo seguro. Se você usá-lo diretamente, certifique-se de que você chamar seu membro de lançamento quando através com o ponteiro (o destruidor COleDispatchDriver faz isso por padrão).
Técnico anotações por número |nbsp; &Notas técnicas por categoria