Come usare OLE nei controlli Rich Edit

Questa sezione contiene informazioni sull'uso del collegamento di oggetti e dell'incorporamento (OLE) in controlli di modifica avanzati.

Informazioni importanti

Tecnologie

Prerequisiti

  • C/C++
  • Programmazione dell'interfaccia utente di Windows

Istruzioni

Usare un'interfaccia rich edit

I controlli di modifica avanzati espongono alcune delle relative funzionalità tramite interfacce COM (Component Object Model). Ottenendo un'interfaccia da un controllo, si ottiene la possibilità di lavorare con altri oggetti all'interno del controllo. È possibile ottenere questa interfaccia inviando il messaggio di EM_GETOLEINTERFACE . Dall'interfaccia IRichEditOle è quindi possibile ottenere le interfacce usate nel modello a oggetti di testo.

Un'altra interfaccia, IRichEditOleCallback, viene implementata dalle applicazioni per definire il comportamento del controllo quando interagisce con gli oggetti.

Inserire un oggetto in un controllo Rich Edit

Nell'esempio di codice seguente viene inserito un oggetto file in un controllo rich edit. Se un programma è associato al tipo di file nel computer dell'utente (ad esempio, Microsoft Excel per un file .xls), il contenuto del file visualizzato nel controllo; in caso contrario, viene visualizzata un'icona.

  1. Ottenere l'interfaccia IRichEditOle .

    BOOL InsertObject(HWND hRichEdit, LPCTSTR pszFileName)
    {
        HRESULT hr;
    
        LPRICHEDITOLE pRichEditOle;
        SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle);
    
        ...
    
  2. Creare una risorsa di archiviazione strutturata.

        LPLOCKBYTES pLockBytes = NULL;
        hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes);
    
        LPSTORAGE pStorage;
        hr = StgCreateDocfileOnILockBytes(pLockBytes, 
                                          STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 
                                          0, &pStorage);
        ...
    
  3. Configurare il formato dati.

        FORMATETC formatEtc;
    
        formatEtc.cfFormat = 0;
        formatEtc.ptd      = NULL;
        formatEtc.dwAspect = DVASPECT_CONTENT;
        formatEtc.lindex   = -1;
        formatEtc.tymed    = TYMED_NULL;
    
        ...
    
  4. Ottenere un puntatore al sito di visualizzazione.

        LPOLECLIENTSITE pClientSite;
        hr = pRichEditOle->GetClientSite(&pClientSite);
    
        ...
    
  5. Creare l'oggetto e recuperarne l'interfaccia IUnknown .

        LPUNKNOWN pUnk;
        CLSID clsid = CLSID_NULL;
    
        hr = OleCreateFromFile(clsid, 
                               pszFileName, 
                               IID_IUnknown, 
                               OLERENDER_DRAW, 
                               &formatEtc, 
                               pClientSite, 
                               pStorage, 
                               (void**)&pUnk);
    
        pClientSite->Release();
    
        ...
    
  6. Ottenere l'interfaccia IOleObject all'oggetto .

        LPOLEOBJECT pObject;
    
        hr = pUnk->QueryInterface(IID_IOleObject, (void**)&pObject);
    
        pUnk->Release();
    
        ...
    
  7. Per assicurarsi che i riferimenti vengano conteggiati correttamente, notificare all'oggetto che è contenuto.

        OleSetContainedObject(pObject, TRUE);
    
        ...
    
  8. Configurare le informazioni sull'oggetto.

        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. Spostare il cursore alla fine del testo e aggiungere un ritorno a capo.

        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. Inserire l'oggetto .

        hr = pRichEditOle->InsertObject(&reobject);
    
        ...
    
  11. Eseguire la pulizia.

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

Uso di IRichEditOleCallback

Le applicazioni implementano l'interfaccia IRichEditOleCallback per rispondere a query o azioni correlate a OLE eseguite da un controllo di modifica avanzato. Associare l'implementazione dell'interfaccia al controllo inviando un messaggio EM_edizione Standard TOLECALLBACK. Il controllo chiama quindi i metodi sull'implementazione dell'interfaccia in base alle esigenze.

Ad esempio, QueryAcceptData viene chiamato quando l'utente tenta di trascinare o incollare un oggetto nel controllo . Se l'applicazione può accettare i dati, l'implementazione del metodo restituisce S_OK; in caso contrario, restituisce un codice di errore. Il metodo potrebbe anche eseguire altre azioni, ad esempio avvisare l'utente che i file di quel tipo non possono essere inseriti nel controllo .

Funzione di esempio InsertObject completa

Nell'esempio di codice seguente vengono illustrati i frammenti di codice precedenti combinati in una funzione completa che include la gestione degli errori.

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 di controlli Rich Edit

Demo dei controlli comuni di Windows (CppWindowsCommonControls)