TN071: implementação de IOleCommandTarget MFC
Observação
A nota técnica a seguir não foi atualizada desde que foi incluída pela primeira vez na documentação online. Como resultado, alguns procedimentos e tópicos podem estar desatualizados ou incorretos. Para obter as informações mais recentes, é recomendável que você pesquise o tópico de interesse no índice de documentação online.
A interface IOleCommandTarget
permite que objetos e seus contêineres enviem comandos uns para os outros. Por exemplo, as barras de ferramentas de um objeto podem conter botões para comandos como Print
, Print Preview
, Save
, New
e Zoom
. Se esse objeto tiver sido inserido em um contêiner compatível com IOleCommandTarget
, o objeto poderá habilitar seus botões e encaminhar os comandos para o contêiner para processamento quando o usuário clicar neles. Se um contêiner quisesse que o objeto inserido se imprimesse, ele poderia fazer essa solicitação enviando um comando por meio da interface IOleCommandTarget
do objeto inserido.
IOleCommandTarget
é uma interface semelhante ao Automação no sentido de que é usada por um cliente para invocar métodos em um servidor. No entanto, o uso de IOleCommandTarget
evita a sobrecarga de fazer chamadas por meio de interfaces de Automação porque os programadores não precisam usar o método Invoke
normalmente caro de IDispatch
.
No MFC, a interface IOleCommandTarget
é usada por servidores de documentos do Active para permitir que contêineres de documentos do Active enviem comandos para o servidor. A classe de servidor de documentos do Active, CDocObjectServerItem
, usa mapas de interface do MFC (confira TN038: implementação de MFC/OLE desconhecida) para implementar a interface IOleCommandTarget
.
IOleCommandTarget
também é implementado na classe COleFrameHook
. COleFrameHook
é uma classe do MFC não documentada que implementa a funcionalidade da janela de quadro de contêineres de edição in-loco. COleFrameHook
também usa mapas de interface do MFC para implementar a interface IOleCommandTarget
. A implementação de COleFrameHook
de IOleCommandTarget
encaminha os comandos OLE aos contêineres de documento do Active derivados de COleDocObjectItem
. Isso permite que qualquer contêiner de documentos do Active do MFC receba mensagens de servidores de documentos do Active contidos.
Mapas de comando OLE do MFC
Os desenvolvedores do MFC podem aproveitar IOleCommandTarget
usando mapas de comando OLE do MFC. Os mapas de comando OLE são como mapas de mensagens porque podem ser usados para mapear comandos OLE para funções de membros da classe que contém o mapa de comando. Para fazer isso funcionar, coloque macros no mapa de comando para especificar o grupo de comandos OLE do comando que você deseja manipular, o comando OLE e a ID de comando da mensagem WM_COMMAND que será enviada quando o comando OLE for recebido. O MFC também fornece várias macros predefinidas para comandos OLE padrão. Para obter uma lista dos comandos OLE padrão que foram originalmente projetados para uso com aplicativos do Microsoft Office, confira a enumeração OLECMDID, que é definida em docobj.h.
Quando um comando OLE é recebido por um aplicativo do MFC que contém um mapa de comando OLE, o MFC tenta localizar a ID de comando e o grupo de comandos do comando solicitado no mapa de comando OLE do aplicativo. Se uma correspondência for encontrada, uma mensagem WM_COMMAND será enviada para o aplicativo que contém o mapa de comando com a ID do comando solicitado. (Confira a descrição de ON_OLECMD
abaixo). Dessa forma, os comandos OLE enviados para um aplicativo são transformados em mensagens WM_COMMAND pelo MFC. As mensagens WM_COMMAND são roteadas por meio dos mapas de mensagens do aplicativo usando a arquitetura de roteamento de comando padrão do MFC.
Ao contrário dos mapas de mensagens, os mapas de comando OLE do MFC não têm suporte do ClassWizard. Os desenvolvedores do MFC devem adicionar suporte ao mapa de comando OLE e entradas de mapa de comando OLE manualmente. Os mapas de comando OLE podem ser adicionados aos servidores de documentos ativos do MFC em qualquer classe que esteja na cadeia de roteamento de mensagens WM_COMMAND no momento que o documento do Active estiver ativo em um contêiner. Essas classes incluem as classes do aplicativo derivadas de CWinApp, CView, CDocument e COleIPFrameWnd. Em contêineres de documentos do Active, os mapas de comando OLE só podem ser adicionados à classe derivada de COleDocObjectItem. Além disso, em contêineres de documentos do Active, as mensagens WM_COMMAND serão enviadas apenas para o mapa de mensagens na classe derivada de COleDocObjectItem
.
Macros de mapa de comando OLE
Use as seguintes macros para adicionar a funcionalidade de mapa de comando à sua classe:
DECLARE_OLECMD_MAP ()
Essa macro entra na declaração de classe (normalmente no arquivo de cabeçalho) da classe que contém o mapa de comando.
BEGIN_OLECMD_MAP(theClass, baseClass)
theClass
Nome da classe que contém o mapa de comando.
baseClass
Nome da classe base que contém o mapa de comando.
Essa macro marca o início do mapa de comando. Use essa macro no arquivo de implementação para a classe que contém o mapa de comando.
END_OLECMD_MAP()
Essa macro marca o fim do mapa de comando. Use essa macro no arquivo de implementação para a classe que contém o mapa de comando. Essa macro deve sempre seguir a macro BEGIN_OLECMD_MAP.
ON_OLECMD(pguid, olecmdid, id)
pguid
Ponteiro para o GUID do grupo de comandos do comando OLE. Esse parâmetro é NULL para o grupo de comandos OLE padrão.
olecmdid
ID de comando OLE do comando a ser invocado.
id
ID da mensagem WM_COMMAND a ser enviada ao aplicativo que contém o mapa de comando quando esse comando OLE é invocado.
Use a macro ON_OLECMD no mapa de comandos para adicionar entradas para os comandos OLE que você deseja manipular. Quando os comandos OLE forem recebidos, eles serão convertidos na mensagem WM_COMMAND especificada e roteados pelo mapa de mensagens do aplicativo usando a arquitetura de roteamento de comando MFC padrão.
Exemplo
O exemplo a seguir mostra como adicionar a funcionalidade de manipulação de comando OLE a um servidor de documentos do Active do MFC para lidar com o comando OLE OLECMDID_PRINT. Esse exemplo pressupõe que você usou o AppWizard para gerar um aplicativo do MFC que é um servidor de documentos ativo.
No arquivo de cabeçalho da classe derivada de
CView
, adicione a macro DECLARE_OLECMD_MAP à declaração de classe.Observação
Use a classe derivada de
CView
porque ela é uma das classes no servidor de documentos ativos que está na cadeia de roteamento de mensagens do WM_COMMAND.class CMyServerView : public CView { protected: // create from serialization only CMyServerView(); DECLARE_DYNCREATE(CMyServerView) DECLARE_OLECMD_MAP() // . . . };
No arquivo de implementação da classe derivada de
CView
, adicione as macros BEGIN_OLECMD_MAP e END_OLECMD_MAP:BEGIN_OLECMD_MAP(CMyServerView, CView) END_OLECMD_MAP()
Para manipular o comando de impressão OLE padrão, adicione uma macro ON_OLECMD ao mapa de comandos especificando a ID do comando OLE para o comando de impressão padrão e ID_FILE_PRINT para a ID do WM_COMMAND. ID_FILE_PRINT é a ID de comando de impressão padrão usada por aplicativos do MFC gerados pelo AppWizard:
BEGIN_OLECMD_MAP(CMyServerView, CView) ON_OLECMD(NULL, OLECMDID_PRINT, ID_FILE_PRINT) END_OLECMD_MAP()
Observe que uma das macros de comando OLE padrão, definidas em afxdocob.h, pode ser usada no lugar da macro ON_OLECMD porque OLECMDID_PRINT é uma ID de comando OLE padrão. A macro ON_OLECMD_PRINT realizará a mesma tarefa que a macro ON_OLECMD mostrada acima.
Quando um aplicativo de contêiner envia a esse servidor um comando OLECMDID_PRINT por meio da interface do IOleCommandTarget
do servidor, o manipulador de comandos de impressão do MFC será invocado no servidor, fazendo com que o servidor imprima o aplicativo. O código do contêiner do documento do Active para invocar o comando de impressão adicionado nas etapas acima seria semelhante a este:
void CContainerCntrItem::DoOleCmd()
{
IOleCommandTarget *pCmd = NULL;
HRESULT hr = E_FAIL;
OLECMD ocm={OLECMDID_PRINT, 0};
hr = m_lpObject->QueryInterface(
IID_IOleCommandTarget,reinterpret_cast<void**>(&pCmd));
if (FAILED(hr))
return;
hr = pCmd->QueryStatus(NULL, 1, &ocm, NULL);
if (SUCCEEDED(hr) && (ocm.cmdf& OLECMDF_ENABLED))
{
//Command is available and enabled so call it
COleVariant vIn;
COleVariant vOut;
hr = pCmd->Exec(NULL, OLECMDID_PRINT,
OLECMDEXECOPT_DODEFAULT, &vIn, &vOut);
ASSERT(SUCCEEDED(hr));
}
pCmd->Release();
}
Confira também
Observações técnicas por número
Observações técnicas por categoria