Compartir a través de


Cómo usar OLE en controles de edición enriquecida

Esta sección contiene información sobre el uso de la vinculación de objetos y la inserción (OLE) en controles de edición enriquecidos.

Lo que necesita saber

Tecnologías

Requisitos previos

  • C/C++
  • Programación de la interfaz de usuario de Windows

Instrucciones

Usar una interfaz de edición enriquecida

Los controles de edición enriquecidos exponen parte de su funcionalidad a través de interfaces del Modelo de objetos componentes (COM). Al obtener una interfaz de un control, se obtiene la capacidad de trabajar con otros objetos dentro del control. Puede obtener esta interfaz enviando el mensaje EM_GETOLEINTERFACE . Desde la interfaz IRichEditOle , puede obtener las interfaces usadas en el modelo de objetos de texto.

Otra interfaz, IRichEditOleCallback, se implementa mediante aplicaciones para definir el comportamiento del control cuando interactúa con objetos.

Insertar un objeto en un control de edición enriquecido

En el ejemplo de código siguiente se inserta un objeto de archivo en un control de edición enriquecido. Si un programa está asociado al tipo de archivo en el equipo del usuario (por ejemplo, Microsoft Excel para un archivo .xls), el contenido del archivo se muestra en el control; de lo contrario, aparece un icono.

  1. Obtenga la interfaz IRichEditOle .

    BOOL InsertObject(HWND hRichEdit, LPCTSTR pszFileName)
    {
        HRESULT hr;
    
        LPRICHEDITOLE pRichEditOle;
        SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle);
    
        ...
    
  2. Crear almacenamiento estructurado.

        LPLOCKBYTES pLockBytes = NULL;
        hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes);
    
        LPSTORAGE pStorage;
        hr = StgCreateDocfileOnILockBytes(pLockBytes, 
                                          STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 
                                          0, &pStorage);
        ...
    
  3. Configure el formato de datos.

        FORMATETC formatEtc;
    
        formatEtc.cfFormat = 0;
        formatEtc.ptd      = NULL;
        formatEtc.dwAspect = DVASPECT_CONTENT;
        formatEtc.lindex   = -1;
        formatEtc.tymed    = TYMED_NULL;
    
        ...
    
  4. Obtener un puntero al sitio para mostrar.

        LPOLECLIENTSITE pClientSite;
        hr = pRichEditOle->GetClientSite(&pClientSite);
    
        ...
    
  5. Cree el objeto y recupere su interfaz IUnknown .

        LPUNKNOWN pUnk;
        CLSID clsid = CLSID_NULL;
    
        hr = OleCreateFromFile(clsid, 
                               pszFileName, 
                               IID_IUnknown, 
                               OLERENDER_DRAW, 
                               &formatEtc, 
                               pClientSite, 
                               pStorage, 
                               (void**)&pUnk);
    
        pClientSite->Release();
    
        ...
    
  6. Obtenga la interfaz IOleObject al objeto .

        LPOLEOBJECT pObject;
    
        hr = pUnk->QueryInterface(IID_IOleObject, (void**)&pObject);
    
        pUnk->Release();
    
        ...
    
  7. Para asegurarse de que las referencias se cuentan correctamente, notifique al objeto que está contenido.

        OleSetContainedObject(pObject, TRUE);
    
        ...
    
  8. Configurar la información del 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;
    
        ...
    
  9. Mueva el símbolo de intercalación al final del texto y agregue un 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"); 
    
        ...
    
  10. Inserte el objeto .

        hr = pRichEditOle->InsertObject(&reobject);
    
        ...
    
  11. Limpiar.

        pObject->Release();
    
        pRichEditOle->Release();
    
        return TRUE;
    
    }
    

Uso de IRichEditOleCallback

Las aplicaciones implementan la interfaz IRichEditOleCallback para responder a las consultas o acciones relacionadas con OLE realizadas por un control de edición enriquecido. Para asociar la implementación de la interfaz con el control, envíe un mensaje de EM_SETOLECALLBACK . A continuación, el control llama a métodos en la implementación de la interfaz según corresponda.

Por ejemplo, se llama a QueryAcceptData cuando el usuario intenta arrastrar o pegar un objeto en el control. Si la aplicación puede aceptar los datos, la implementación del método devuelve S_OK; de lo contrario, devuelve un código de error. El método también puede realizar alguna otra acción, como advertir al usuario de que los archivos de ese tipo no se pueden colocar en el control.

Función de ejemplo InsertObject completa

En el ejemplo de código siguiente se muestran los fragmentos de código anteriores combinados en una función completa que incluye el control de errores.

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

Uso de controles de edición enriquecida

Demostración de controles comunes de Windows (CppWindowsCommonControls)