CRichEditCtrl and inserting images (JPG)

时间:2016-02-12 19:38:31

标签: c++ image mfc

Using MFC vs2010 c++ I'm trying to use the CRichEditCtrl to display an image.

Using the process explained here https://support.microsoft.com/en-us/kb/220844

I'm able to see the "icon" with the name of the image under the icon but I want to see the actual image in the control. If I double click on the icon I then get a pop up app that shows me the original image.

My images will all be JPG. I'm look for something like what the Windows 8.1 WordPad Insert Picture does.

I've read the version that uses an HBITMAP but does that show the actual image or the same icon/name. I was also hoping to keep the jpg format as it is smaller in my cases. So does anyone know if this version shows the image and not the icon?

Am I missing something simple?

1 个答案:

答案 0 :(得分:1)

The MSDN example should work with bitmap images. You can use Gdiplus to open jpeg/png, then get HBITMAP from Gdiplus handle. Use OleCreateStaticFromData to insert images in RichEdit control

void InsertBitmap(CRichEditCtrl *edit, HBITMAP hBitmap, int position)
{
    STGMEDIUM stgm;
    stgm.tymed = TYMED_GDI;
    stgm.hBitmap = hBitmap;
    stgm.pUnkForRelease = NULL;

    FORMATETC fm;
    fm.cfFormat = CF_BITMAP;
    fm.ptd = NULL;
    fm.dwAspect = DVASPECT_CONTENT;
    fm.lindex = -1;
    fm.tymed = TYMED_GDI;

    COleDataSource oleDataSource;
    oleDataSource.CacheData(CF_BITMAP, &stgm);
    LPDATAOBJECT dataObject = (LPDATAOBJECT)oleDataSource.GetInterface(&IID_IDataObject);

    if (OleQueryCreateFromData(dataObject) != OLE_S_STATIC)
        return;

    LPOLECLIENTSITE oleClientSite;
    if (S_OK != edit->GetIRichEditOle()->GetClientSite(&oleClientSite))
        return;

    //allocate memory
    LPLOCKBYTES lockBytes = NULL;
    if (S_OK == CreateILockBytesOnHGlobal(NULL, TRUE, &lockBytes) && lockBytes)
    {
        IStorage *storage = NULL;
        if (S_OK == StgCreateDocfileOnILockBytes(lockBytes, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &storage) && storage)
        {
            IOleObject *oleObject = NULL;
            if (S_OK == OleCreateStaticFromData(dataObject, IID_IOleObject, OLERENDER_FORMAT, &fm, oleClientSite, storage, (void **)&oleObject) && oleObject)
            {
                CLSID clsid;
                if (S_OK == oleObject->GetUserClassID(&clsid))
                {
                    REOBJECT reobject = { sizeof(REOBJECT) };
                    reobject.clsid = clsid;
                    reobject.cp = position;
                    reobject.dvaspect = DVASPECT_CONTENT;
                    reobject.poleobj = oleObject;
                    reobject.polesite = oleClientSite;
                    reobject.pstg = storage;
                    edit->GetIRichEditOle()->InsertObject(&reobject);
                }
                oleObject->Release();
            }
            storage->Release();
        }
        lockBytes->Release();
    }
    oleClientSite->Release();
}

usage:

Gdiplus::Bitmap *gdibmp = Gdiplus::Bitmap::FromFile(filename);
HBITMAP hbitmap = NULL;
gdibmp->GetHBITMAP(0, &hbitmap);
if (hbitmap)
    InsertBitmap(&richEdit, hbitmap, 0);
delete gdibmp;

Note, Gdiplus needs Unicode file name. If your project is ANSI (which it shouldn't be) then use CStringW to convert filename to Unicode.