Como usar OLE em controles de edição avançados
Esta seção contém informações sobre como usar vinculação e incorporação de objetos (OLE) em controles de edição avançados.
O que precisa de saber
Tecnologias
Pré-requisitos
- C/C++
- Programação da interface do usuário do Windows
Instruções
Usar uma interface de edição avançada
Controles de edição avançados expõem algumas de suas funcionalidades por meio de interfaces COM (Component Object Model). Ao obter uma interface de um controle, você ganha a capacidade de trabalhar com outros objetos dentro do controle. Você pode obter essa interface enviando a mensagem EM_GETOLEINTERFACE. A partir da interface IRichEditOle, pode-se então obter interfaces usadas no Text Object Model.
Outra interface, IRichEditOleCallback, é implementada por aplicativos para definir o comportamento do controle quando ele interage com objetos.
Inserir um objeto em um controle Rich Edit
O exemplo de código a seguir insere um objeto de arquivo em um controle de edição avançado. Se um programa estiver associado ao tipo de arquivo na máquina do usuário (por exemplo, Microsoft Excel para um arquivo .xls), o conteúdo do arquivo será exibido no controle; caso contrário, será exibido um ícone.
Obtenha a interface IRichEditOle .
BOOL InsertObject(HWND hRichEdit, LPCTSTR pszFileName) { HRESULT hr; LPRICHEDITOLE pRichEditOle; SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle); ...
Crie armazenamento estruturado.
LPLOCKBYTES pLockBytes = NULL; hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes); LPSTORAGE pStorage; hr = StgCreateDocfileOnILockBytes(pLockBytes, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &pStorage); ...
Configure o formato de dados.
FORMATETC formatEtc; formatEtc.cfFormat = 0; formatEtc.ptd = NULL; formatEtc.dwAspect = DVASPECT_CONTENT; formatEtc.lindex = -1; formatEtc.tymed = TYMED_NULL; ...
Obtenha um ponteiro para o site de exibição.
LPOLECLIENTSITE pClientSite; hr = pRichEditOle->GetClientSite(&pClientSite); ...
Crie o objeto e obtenha sua IUnknown interface.
LPUNKNOWN pUnk; CLSID clsid = CLSID_NULL; hr = OleCreateFromFile(clsid, pszFileName, IID_IUnknown, OLERENDER_DRAW, &formatEtc, pClientSite, pStorage, (void**)&pUnk); pClientSite->Release(); ...
Obtenha a interface IOleObject para o objeto.
LPOLEOBJECT pObject; hr = pUnk->QueryInterface(IID_IOleObject, (void**)&pObject); pUnk->Release(); ...
Para garantir que as referências sejam contadas corretamente, notifique o objeto que ele está contido.
OleSetContainedObject(pObject, TRUE); ...
Configure as informações do objeto.
REOBJECT reobject = { sizeof(REOBJECT)}; hr = pObject->GetUserClassID(&clsid); reobject.clsid = clsid; reobject.cp = REO_CP_SELECTION; reobject.dvaspect = DVASPECT_CONTENT; reobject.dwFlags = REO_RESIZABLE | REO_BELOWBASELINE; reobject.dwUser = 0; reobject.poleobj = pObject; reobject.polesite = pClientSite; reobject.pstg = pStorage; SIZEL sizel = { 0 }; reobject.sizel = sizel; ...
Mova o cursor para o final do texto e adicione um retorno de carro.
SendMessage(hRichEdit, EM_SETSEL, 0, -1); DWORD dwStart, dwEnd; SendMessage(hRichEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd); SendMessage(hRichEdit, EM_SETSEL, dwEnd+1, dwEnd+1); SendMessage(hRichEdit, EM_REPLACESEL, TRUE, (WPARAM)L"\n"); ...
Insira o objeto.
hr = pRichEditOle->InsertObject(&reobject); ...
Limpeza.
pObject->Release(); pRichEditOle->Release(); return TRUE; }
Usando IRichEditOleCallback
Os aplicativos implementam o interface de IRichEditOleCallback para responder a consultas ou ações relacionadas ao OLE que são executadas por um controle de edição avançado. Você associa sua implementação da interface com o controle enviando uma mensagem EM_SETOLECALLBACK. Em seguida, o controlo chama métodos na sua implementação da interface, conforme apropriado.
Por exemplo, QueryAcceptData é chamado quando o usuário tenta arrastar ou colar um objeto no controle. Se o seu aplicativo pode aceitar os dados, sua implementação do método retorna S_OK; caso contrário, ele retorna um código de erro. O método também pode executar alguma outra ação, como avisar o usuário que arquivos desse tipo não podem ser colocados no controle.
Exemplo Completo da Função InsertObject
O exemplo de código a seguir demonstra os trechos de código anteriores combinados em uma função completa que inclui manipulação de erros.
BOOL InsertObject(HWND hRichEdit, LPCTSTR pszFileName)
{
HRESULT hr;
LPRICHEDITOLE pRichEditOle;
SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle);
if (pRichEditOle == NULL)
{
return FALSE;
}
LPLOCKBYTES pLockBytes = NULL;
hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes);
if (FAILED(hr))
{
return FALSE;
}
LPSTORAGE pStorage;
hr = StgCreateDocfileOnILockBytes(pLockBytes,
STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE,
0, &pStorage);
if (FAILED(hr))
{
return FALSE;
}
FORMATETC formatEtc;
formatEtc.cfFormat = 0;
formatEtc.ptd = NULL;
formatEtc.dwAspect = DVASPECT_CONTENT;
formatEtc.lindex = -1;
formatEtc.tymed = TYMED_NULL;
LPOLECLIENTSITE pClientSite;
hr = pRichEditOle->GetClientSite(&pClientSite);
if (FAILED(hr))
{
return FALSE;
}
LPUNKNOWN pUnk;
CLSID clsid = CLSID_NULL;
hr = OleCreateFromFile(clsid, pszFileName, IID_IUnknown, OLERENDER_DRAW,
&formatEtc, pClientSite, pStorage, (void**)&pUnk);
pClientSite->Release();
if (FAILED(hr))
{
return FALSE;
}
LPOLEOBJECT pObject;
hr = pUnk->QueryInterface(IID_IOleObject, (void**)&pObject);
pUnk->Release();
if (FAILED(hr))
{
return FALSE;
}
OleSetContainedObject(pObject, TRUE);
REOBJECT reobject = { sizeof(REOBJECT)};
hr = pObject->GetUserClassID(&clsid);
if (FAILED(hr))
{
pObject->Release();
return FALSE;
}
reobject.clsid = clsid;
reobject.cp = REO_CP_SELECTION;
reobject.dvaspect = DVASPECT_CONTENT;
reobject.dwFlags = REO_RESIZABLE | REO_BELOWBASELINE;
reobject.dwUser = 0;
reobject.poleobj = pObject;
reobject.polesite = pClientSite;
reobject.pstg = pStorage;
SIZEL sizel = { 0 };
reobject.sizel = sizel;
SendMessage(hRichEdit, EM_SETSEL, 0, -1);
DWORD dwStart, dwEnd;
SendMessage(hRichEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
SendMessage(hRichEdit, EM_SETSEL, dwEnd+1, dwEnd+1);
SendMessage(hRichEdit, EM_REPLACESEL, TRUE, (WPARAM)L"\n");
hr = pRichEditOle->InsertObject(&reobject);
pObject->Release();
pRichEditOle->Release();
if (FAILED(hr))
{
return FALSE;
}
return TRUE;
}
Tópicos relacionados