Partager via


Guide pratique pour utiliser OLE dans des contrôles d’édition enrichis

Cette section contient des informations sur l’utilisation de la liaison et de l’incorporation d’objets (OLE) dans des contrôles d’édition enrichis.

Bon à savoir

Technologies

Prérequis

  • C/C++
  • Programmation de l’interface utilisateur Windows

Instructions

Utiliser une interface d’édition enrichie

Les contrôles d’édition enrichis exposent certaines de leurs fonctionnalités via des interfaces COM (Component Object Model). En obtenant une interface à partir d’un contrôle, vous obtenez la possibilité d’utiliser d’autres objets dans le contrôle. Vous pouvez obtenir cette interface en envoyant le message EM_GETOLEINTERFACE . À partir de l’interface IRichEditOle , vous pouvez ensuite obtenir les interfaces utilisées dans le modèle objet texte.

Une autre interface, IRichEditOleCallback, est implémentée par les applications pour définir le comportement du contrôle lorsqu’il interagit avec des objets.

Insérer un objet dans un contrôle d’édition enrichi

L’exemple de code suivant insère un objet file dans un contrôle d’édition enrichi. Si un programme est associé au type de fichier sur l’ordinateur de l’utilisateur (par exemple, Microsoft Excel pour un fichier .xls), le contenu du fichier s’affiche dans le contrôle ; sinon, une icône s’affiche.

  1. Obtenez l’interface IRichEditOle .

    BOOL InsertObject(HWND hRichEdit, LPCTSTR pszFileName)
    {
        HRESULT hr;
    
        LPRICHEDITOLE pRichEditOle;
        SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle);
    
        ...
    
  2. Créer un stockage structuré.

        LPLOCKBYTES pLockBytes = NULL;
        hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes);
    
        LPSTORAGE pStorage;
        hr = StgCreateDocfileOnILockBytes(pLockBytes, 
                                          STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 
                                          0, &pStorage);
        ...
    
  3. Configurez le format de données.

        FORMATETC formatEtc;
    
        formatEtc.cfFormat = 0;
        formatEtc.ptd      = NULL;
        formatEtc.dwAspect = DVASPECT_CONTENT;
        formatEtc.lindex   = -1;
        formatEtc.tymed    = TYMED_NULL;
    
        ...
    
  4. Obtenir un pointeur vers le site d’affichage.

        LPOLECLIENTSITE pClientSite;
        hr = pRichEditOle->GetClientSite(&pClientSite);
    
        ...
    
  5. Créez l’objet et récupérez son interface IUnknown .

        LPUNKNOWN pUnk;
        CLSID clsid = CLSID_NULL;
    
        hr = OleCreateFromFile(clsid, 
                               pszFileName, 
                               IID_IUnknown, 
                               OLERENDER_DRAW, 
                               &formatEtc, 
                               pClientSite, 
                               pStorage, 
                               (void**)&pUnk);
    
        pClientSite->Release();
    
        ...
    
  6. Obtenez l’interface IOleObject pour l’objet .

        LPOLEOBJECT pObject;
    
        hr = pUnk->QueryInterface(IID_IOleObject, (void**)&pObject);
    
        pUnk->Release();
    
        ...
    
  7. Pour vous assurer que les références sont comptées correctement, informez l’objet qu’il est contenu.

        OleSetContainedObject(pObject, TRUE);
    
        ...
    
  8. Configurer les informations sur l’objet.

        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. Déplacez le signe à la fin du texte et ajoutez un retour chariot.

        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. Insérez l’objet .

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

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

Utilisation de IRichEditOleCallback

Les applications implémentent l’interface IRichEditOleCallback pour répondre aux requêtes ou actions ole effectuées par un contrôle d’édition enrichi. Vous associez votre implémentation de l’interface au contrôle en envoyant un message EM_SETOLECALLBACK . Le contrôle appelle ensuite des méthodes sur votre implémentation de l’interface, le cas échéant.

Par exemple, QueryAcceptData est appelé lorsque l’utilisateur tente de faire glisser ou coller un objet dans le contrôle. Si votre application peut accepter les données, votre implémentation de la méthode retourne S_OK ; sinon, elle retourne un code d’erreur. La méthode peut également effectuer d’autres actions, comme avertir l’utilisateur que les fichiers de ce type ne peuvent pas être placés dans le contrôle.

Complete InsertObject Example Function

L’exemple de code suivant illustre les extraits de code précédents combinés en une seule fonction complète qui inclut la gestion des erreurs.

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

Utilisation de contrôles d’édition enrichie

Démonstration des contrôles communs Windows (CppWindowsCommonControls)