TN039: Implementação de automação do MFC/OLE

Observação:

A seguinte nota técnica não foi atualizada desde que foi incluída pela primeira vez na documentação online.sistema autônomo resultado, alguns procedimentos e tópicos podem estar desatualizado ou incorreto.Para obter informações mais recentes, é recomendável que você procurar o tópico de interesse no índice de documentação online.

Visão geral da interface de IDispatch OLE

The IDispatch interface é o meio ao quais aplicativos expõem métodos e propriedades tais poderá fazer com que outros aplicativos, sistema autônomo o Visual BASIC ou outras linguagens, usar sistema autônomo recursos do aplicativo. A parte mais importante dessa interface é o IDispatch:: Invoke função.MFC usa "mapas de distribuição" implementarIDispatch:: Invoke.O MAP de despacho fornece as informações de implementação do MFC no layout ou "forma" de suaCCmdTarget-derivadas de classes, de modo que ele pode manipular diretamente as propriedades do objeto, ou telefonar funções de membro dentro de seu objeto para satisfazer IDispatch:: Invoke solicitações.

Em sua maioria, ClassWizard e MFC cooperam para ocultar a maioria dos detalhes de automação OLE do programador de aplicativo.O programador concentra-se na funcionalidade real para expor no aplicativo e não tem se preocupar com detalhes técnicos subjacentes.

Há casos, entretanto, onde é necessário compreender o que a MFC está fazendo nos bastidores.Esta nota abordará como a estrutura atribui DISPID s para funções de membro e propriedades.Conhecimento de algoritmo de MFC usa para a atribuição de DISPID sistema autônomo só é necessário quando você precisa conhecer sistema autônomo IDs, por exemplo, quando você cria "uma biblioteca de tipos" para objetos do aplicativo.

Atribuição MFC DISPID

Embora o usuário participante de automação (um Visual Basic usuário, por exemplo), visualiza sistema autônomo nomes real da automação habilitada propriedades e métodos em seu código (sistema autônomo obj.ShowWindow), a implementação de IDispatch:: Invoke não recebe sistema autônomo nomes real.Por motivos de otimização, ele recebe um DISPID, que é de 32 bit "magic cookie" que descreve o método ou propriedade a ser acessado.Esses DISPID valores de são retornados do IDispatch implementação por outro método, chamado IDispatch::GetIDsOfNames.Um aplicativo cliente de automação chamará GetIDsOfNames uma vez para cada membro ou uma propriedade que pretende acessar e armazenar em cache-los para posteriores chamadas para IDispatch:: Invoke.Dessa forma, a pesquisa de seqüência caro apenas é feita uma vez por uso de objeto, em vez de uma vez por IDispatch:: Invoke telefonar.

MFC determina o DISPID s para cada método e propriedade baseada em duas coisas:

  • A distância da parte superior do MAP de despacho (1 relativo)

  • A distância do MAP de despacho de mais classe derivada (0 relativo)

The DISPID é dividido em duas partes.The LOWORD of the DISPID contém o elemento, a distância da parte superior do MAP de despacho.The HIWORD contém a distância entre a maioria classe derivada.Por exemplo:

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

sistema autônomo você pode ver, há duas classes, que expõem interfaces de automação OLE.Uma dessas classes é derivada de Outros e, portanto, aproveita a funcionalidade da classe base, incluindo a parte de automação OLE ("x" e "y" propriedades no caso).

MFC será gerar DISPID sistema autônomo para classe CDispPoint da seguinte maneira:

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

Como as propriedades não são uma classe base, a HIWORD of the DISPID é sempre zero (a distância entre a maioria classe derivada CDispPoint é zero).

MFC gerará DISPID sistema autônomo para classe CDisp3DPoint da seguinte maneira:

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

A propriedade Z é fornecida um DISPID com um zero HIWORD, pois ele é definido na classe que está expondo as propriedades, CDisp3DPoint.Como as propriedades X e Y são definidas na classe base, a HIWORD of the DISPID é 1, pois a classe na qual essas propriedades são definidas é a uma distância de uma derivação da classe mais derivada.

Observação:

O LOWORD sempre é determinado pela posição no MAP, mesmo se há entradas no MAP com explícita DISPID (consulte a próxima seção para obter informações sobre o _ID o versõesDISP_PROPERTY e DISP_FUNCTION macros).

Avançados recursos de MAP de despacho MFC

Há um número de recursos adicionais que não oferece suporte a ClassWizard com esta versão do Visual C++.ClassWizard suporta DISP_FUNCTION, DISP_PROPERTY, e DISP_PROPERTY_EX que defina um método, propriedade de membro de variável e propriedade de função de membro get/conjunto, respectivamente. Esses recursos normalmente são 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 suportado não são adequadas: DISP_PROPERTY_NOTIFY e DISP_PROPERTY_PARAM.

DISP_PROPERTY_NOTIFY — Descrição da macro

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

Comentários

Parâmetros

  • theClass
    Nome da classe.

  • pszName
    Nome externo da propriedade.

  • memberName
    Nome da variável de membro no qual a propriedade está armazenada.

  • pfnAfterSet
    Nome da função de membro para chamar quando a propriedade é alterada.

  • vtPropType
    Um valor que especifica o tipo da propriedade.

Comentários

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 não retorna nada e sem parâmetros, 'void OnPropertyNotify()'.Ele será chamado Depois de a variável de membro foi modificada.

DISP_PROPERTY_PARAM — Descrição da macro

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

Comentários

Parâmetros

  • theClass
    Nome da classe.

  • pszName
    Nome externo da propriedade.

  • memberGet
    Nome da função de membro usada para obter a propriedade.

  • memberSet
    Nome da função de membro usada para conjunto a propriedade.

  • vtPropType
    Um valor que especifica o tipo da propriedade.

  • vtsParams
    Uma seqüência de caracteres de espaço separados VTS_ para cada parâmetro.

Comentários

Muito semelhante a DISP_PROPERTY_EX macro, essa macro define uma propriedade acessada com funções de membro get e conjunto separadas. Essa macro, no entanto, permite que você especifique uma lista de parâmetros para a propriedade.Isso é útil para implementar propriedades que estão indexadas ou parâmetros definidas de alguma Outros maneira.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 conjunto funções de membro:

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

DISP_XXXX_ID — 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 
)

Comentários

Parâmetros

  • theClass
    Nome da classe.

  • pszName
    Nome externo da propriedade.

  • dispid
    DISPID fixo para a propriedade ou método.

  • pfnGet
    Nome da função de membro usada para obter a propriedade.

  • pfnSet
    Nome da função de membro usada para conjunto a propriedade.

  • memberName
    O nome da variável membro para mapear para a propriedade

  • vtPropType
    Um valor que especifica o tipo da propriedade.

  • vtsParams
    Uma seqüência de caracteres de espaço separados VTS_ para cada parâmetro.

Comentários

Essas macros permitem que você especifique um DISPID em vez de permitir que o MFC automaticamente o atribuir.Essas macros avançadas têm os mesmos nomes, exceto esse ID é acrescentado ao nome do macro (por exemploDISP_PROPERTY_ID) e a ID é determinada pelo parâmetro especificado logo após o pszName parâmetro. Para obter mais informações sobre essas macros, consulte AFXDISP.H.The _ID entradas devem ser colocadas no participante do MAP de despacho.Elas afetarão o automáticoDISPID geração da mesma forma sistema autônomo um não-_ID versão da macro seria (a DISPID sistema autônomo são determinadas pela posição).Por exemplo:

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 irá gerar DISPIDs para classe CDisp3DPoint da seguinte maneira:

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

Especificando um fixo DISPID é útil para manter a 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, sistema autônomo a DISPID_NEWENUM coleção).

Recuperar a interface IDispatch para um COleClientItem

Muitos servidores oferecerá suporte a automação dentro de seus objetos de documento, junto com a funcionalidade de servidor OLE.Para acessar essa interface de automação, é necessário acessar diretamente o COleClientItem::m_lpObject variável de membro.O código a seguir recuperará o IDispatch interface de um objeto derivado de COleClientItem. Você pode incluir o código abaixo no seu aplicativo se encontrar essa funcionalidade necessários:

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

Interface dispatch retornado por essa função pode ser usada diretamente ou anexada a um COleDispatchDriver para acesso de fortemente tipado. Se usá-lo diretamente, certifique-se de que você chamar sua Versão membro quando através com o ponteiro do (a COleDispatchDriver Destrutor faz isso por padrão).

Consulte também

Outros recursos

Notas técnicas por número

Notas técnicas por categoria