Bitmaps in RichEditView 
Author Message
 Bitmaps in RichEditView

Hi
do you how to manipulate bitmaps in RichEdit View along with Text


Fri, 26 Mar 2004 15:26:55 GMT  
 Bitmaps in RichEditView
I mean how to insert a bitmap between text in RichEdit control


Fri, 26 Mar 2004 16:11:16 GMT  
 Bitmaps in RichEditView
Hi,

My name is Lion Shi. Thank you for using Microsoft Visual C++ Newsgroup.

The RichEdit control does not provide a direct method for loading a bitmap
and inserting it into an RTF document. The ActiveX control (RichTextBox)
provides the Add method through the COleObjects class, but this action
loads the bitmap for editing in the registered bitmap editor (usually
Paintbrush) before inserting it into the document. Both the DLL and the OCX
expose the IRichEditOle interface which provides the InsertObject method.
This requires a fully-populated RichEdit Object (REOBJECT) structure to
function.

The following code is based on a project in which the Microsoft RichTextBox
control has been inserted. With minor changes, it can apply to the RichEdit
DLL as well.

1. First, add four OLE interface pointers as member variables:
        LPRICHEDITOLE   m_pRichEditOle;
        LPOLEOBJECT     m_lpObject;
        LPSTORAGE         m_lpStorage;
        LPOLECLIENTSITE m_lpClientSite;
NOTE: Set these variables to NULL in your constructor.

2. Get the IRichEditOLE interface early on in your program and keep it
available    in OnInitDialog or OnInitialUpdate. For the RichTextBox
control, use the following method:

        ::SendMessage((HWND)m_ctlRichText.GetHwnd(), EM_GETOLEINTERFACE, 0,
(LPARAM)&m_pRichEditOle);
        ASSERT(m_pRichEditOle != NULL);

NOTE: M_ctlRichText is an instance of the Visual C++ wrapper class MFC
generates when inserting a RichTextBox ActiveX control through the
component gallery. The MFC CRichEditCtrl class provides the
GetRichEditOle() method that wraps code similar to the above and produces
the same result.

3. To insert the bitmap, create an embedded object from a file. OLE
provides the OleCreateFromFile function call to make this easier, but you
still need to prepare for the call. The following code is an amalgam of
techniques used within the MFC classes to provide similar functionality.

   BOOL CRichTextDlg::CreateFromFile(LPCTSTR lpszFileName)
   {
        USES_CONVERSION;
        ASSERT_VALID(this);
        ASSERT(m_lpObject == NULL);     // one time only
        ASSERT(m_lpStorage == NULL);
        ASSERT(m_lpClientSite == NULL);
        LPLOCKBYTES lpLockBytes = NULL;
        CLSID clsid = CLSID_NULL;
        OLERENDER render = OLERENDER_DRAW;
        CLIPFORMAT cfFormat = 0;
        LPFORMATETC lpFormatEtc = NULL;
        SCODE sc;
        sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
        if (sc != S_OK)
                AfxThrowOleException(sc);
        ASSERT(lpLockBytes != NULL);
        sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
                STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0,
&m_lpStorage);
        if (sc != S_OK)
        {
                VERIFY(lpLockBytes->Release() == 0);
                lpLockBytes = NULL;
                AfxThrowOleException(sc);
        }
        ASSERT(m_lpStorage != NULL);
        // fill in FORMATETC struct
        FORMATETC formatEtc;
        lpFormatEtc = &formatEtc;
        lpFormatEtc->cfFormat = cfFormat;
        lpFormatEtc->ptd = NULL;
        lpFormatEtc->dwAspect = DVASPECT_CONTENT;
        lpFormatEtc->lindex = -1;
        lpFormatEtc->tymed = TYMED_NULL;
        // attempt to create the object
        m_pRichEditOle->GetClientSite(&m_lpClientSite);
        sc = ::OleCreateFromFile(clsid, T2COLE(lpszFileName),
                IID_IUnknown, OLERENDER_DRAW, lpFormatEtc, m_lpClientSite,
m_lpStorage,
                (void**)&m_lpObject);
        if (sc != S_OK)
                AfxThrowOleException(sc);
        // m_lpObject is currently an IUnknown, convert to IOleObject
        if (m_lpObject != NULL)
        {
                LPUNKNOWN lpUnk = m_lpObject;
                lpUnk->QueryInterface(IID_IOleObject, (void**)&m_lpObject);
                lpUnk->Release();
                if (m_lpObject == NULL)
                        AfxThrowOleException(E_OUTOFMEMORY);
        }
        // all items are "contained" -- this makes our reference to this
object
        //  weak -- which is needed for links to embedding silent update.
        OleSetContainedObject(m_lpObject, TRUE);
        ASSERT_VALID(this);
        return TRUE;
   }

4. To use the function, simply pass the full path to a bitmap as the file
name parameter. The function creates a byte array in global memory and a
compound file storage object in that memory. It then populates the
FORMATETC structure, gets the client site, and creates the object within
the provided storage. The result is an IUnknown pointer to the object that
is then converted to a true IOleObject pointer by a call to QueryInterface.

5. Populate the RichEdit Object (REOBJECT) structure so it can call
InsertObject through the IRichEditOle pointer stored earlier. The following
code fills this structure:

        REOBJECT reobject;
        ZeroMemory(&reobject, sizeof(REOBJECT));
        reobject.cbStruct = sizeof(REOBJECT);
        CLSID clsid;
        SCODE sc = m_lpObject->GetUserClassID(&clsid);
        if (sc != S_OK)
                AfxThrowOleException(sc);
        reobject.clsid = clsid;
        reobject.cp = REO_CP_SELECTION;
        reobject.dvaspect = DVASPECT_CONTENT;
        reobject.dwFlags = REO_RESIZABLE | REO_BELOWBASELINE;
        reobject.dwUser = 0;
        reobject.poleobj = m_lpObject;
        ASSERT(m_lpClientSite != NULL);
        reobject.polesite = m_lpClientSite;
        ASSERT(m_lpStorage != NULL);
        reobject.pstg = m_lpStorage;
        SIZEL sizel;
        sizel.cx = sizel.cy = 0;
        reobject.sizel = sizel;

6. At this point, make the InsertObject call. Insert the bitmap at the
bottom of the file. A combination of EM_GETSEL/EM_SETSEL messages selects
the document's text and positions the cursor at the end.

        HWND hWndRT = (HWND)m_ctlRichText.GetHwnd();
        ::SendMessage(hWndRT, EM_SETSEL, 0, -1);
        DWORD dwStart, dwEnd;
        ::SendMessage(hWndRT, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
        ::SendMessage(hWndRT, EM_SETSEL, dwEnd+1, dwEnd+1);

7. Call InsertObject but add a carriage return first as in the following
sample:

        CString strCr = "\r\n";
        m_ctlRichText.SetSelText((LPCTSTR)strCr);

Finally!

        m_pRichEditOle->InsertObject(&reobject);

8. The bitmap is dropped neatly at the bottom of the document with a
carriage return separating it from the body of the text as in the following
code sample:

        ::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);

9. This message scrolls the document to the caret position and the bitmap
rolls into view. To repeat this, release the interface pointers:

        if (m_lpObject)
        {
                m_lpObject->Release();
                m_lpObject = NULL;
        }
        if (m_lpStorage)
        {
                m_lpStorage->Release();
                m_lpStorage = NULL;
        }
        if (m_lpClientSite)
        {
                m_lpClientSite->Release();
                m_lpClientSite = NULL;
        }

10. Finally, release m_pRichEditOle.

There is a KB about this issue:
http://support.microsoft.com/support/kb/articles/Q220/8/44.ASP

This posting is provided "AS IS" with no warranties, and confers no rights.
You assume all risk for your use.   2001 Microsoft Corporation. All rights
reserved.

Lion Shi
Microsoft Support Engineer



Sat, 27 Mar 2004 10:21:26 GMT  
 Bitmaps in RichEditView
Hi Lion,
Thanks for you reply.
But I'm using rich Edit Control not Rich Edit View,
You use InsertObject function that request for a document, while I have no
document. Is any other way to insert a bitmap with in the Rich Edit Control

manish


Quote:
> Hi,

> My name is Lion Shi. Thank you for using Microsoft Visual C++ Newsgroup.

> The RichEdit control does not provide a direct method for loading a bitmap
> and inserting it into an RTF document. The ActiveX control (RichTextBox)
> provides the Add method through the COleObjects class, but this action
> loads the bitmap for editing in the registered bitmap editor (usually
> Paintbrush) before inserting it into the document. Both the DLL and the
OCX
> expose the IRichEditOle interface which provides the InsertObject method.
> This requires a fully-populated RichEdit Object (REOBJECT) structure to
> function.

> The following code is based on a project in which the Microsoft
RichTextBox
> control has been inserted. With minor changes, it can apply to the
RichEdit
> DLL as well.

> 1. First, add four OLE interface pointers as member variables:
>         LPRICHEDITOLE   m_pRichEditOle;
>         LPOLEOBJECT     m_lpObject;
>         LPSTORAGE         m_lpStorage;
>         LPOLECLIENTSITE m_lpClientSite;
> NOTE: Set these variables to NULL in your constructor.

> 2. Get the IRichEditOLE interface early on in your program and keep it
> available    in OnInitDialog or OnInitialUpdate. For the RichTextBox
> control, use the following method:

>         ::SendMessage((HWND)m_ctlRichText.GetHwnd(), EM_GETOLEINTERFACE,
0,
> (LPARAM)&m_pRichEditOle);
>         ASSERT(m_pRichEditOle != NULL);

> NOTE: M_ctlRichText is an instance of the Visual C++ wrapper class MFC
> generates when inserting a RichTextBox ActiveX control through the
> component gallery. The MFC CRichEditCtrl class provides the
> GetRichEditOle() method that wraps code similar to the above and produces
> the same result.

> 3. To insert the bitmap, create an embedded object from a file. OLE
> provides the OleCreateFromFile function call to make this easier, but you
> still need to prepare for the call. The following code is an amalgam of
> techniques used within the MFC classes to provide similar functionality.

>    BOOL CRichTextDlg::CreateFromFile(LPCTSTR lpszFileName)
>    {
>         USES_CONVERSION;
>         ASSERT_VALID(this);
>         ASSERT(m_lpObject == NULL);     // one time only
>         ASSERT(m_lpStorage == NULL);
>         ASSERT(m_lpClientSite == NULL);
>         LPLOCKBYTES lpLockBytes = NULL;
>         CLSID clsid = CLSID_NULL;
>         OLERENDER render = OLERENDER_DRAW;
>         CLIPFORMAT cfFormat = 0;
>         LPFORMATETC lpFormatEtc = NULL;
>         SCODE sc;
>         sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
>         if (sc != S_OK)
>                 AfxThrowOleException(sc);
>         ASSERT(lpLockBytes != NULL);
>         sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
>                 STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0,
> &m_lpStorage);
>         if (sc != S_OK)
>         {
>                 VERIFY(lpLockBytes->Release() == 0);
>                 lpLockBytes = NULL;
>                 AfxThrowOleException(sc);
>         }
>         ASSERT(m_lpStorage != NULL);
>         // fill in FORMATETC struct
>         FORMATETC formatEtc;
>         lpFormatEtc = &formatEtc;
>         lpFormatEtc->cfFormat = cfFormat;
>         lpFormatEtc->ptd = NULL;
>         lpFormatEtc->dwAspect = DVASPECT_CONTENT;
>         lpFormatEtc->lindex = -1;
>         lpFormatEtc->tymed = TYMED_NULL;
>         // attempt to create the object
>         m_pRichEditOle->GetClientSite(&m_lpClientSite);
>         sc = ::OleCreateFromFile(clsid, T2COLE(lpszFileName),
>                 IID_IUnknown, OLERENDER_DRAW, lpFormatEtc, m_lpClientSite,
> m_lpStorage,
>                 (void**)&m_lpObject);
>         if (sc != S_OK)
>                 AfxThrowOleException(sc);
>         // m_lpObject is currently an IUnknown, convert to IOleObject
>         if (m_lpObject != NULL)
>         {
>                 LPUNKNOWN lpUnk = m_lpObject;
>                 lpUnk->QueryInterface(IID_IOleObject,

(void**)&m_lpObject);

- Show quoted text -

Quote:
>                 lpUnk->Release();
>                 if (m_lpObject == NULL)
>                         AfxThrowOleException(E_OUTOFMEMORY);
>         }
>         // all items are "contained" -- this makes our reference to this
> object
>         //  weak -- which is needed for links to embedding silent update.
>         OleSetContainedObject(m_lpObject, TRUE);
>         ASSERT_VALID(this);
>         return TRUE;
>    }

> 4. To use the function, simply pass the full path to a bitmap as the file
> name parameter. The function creates a byte array in global memory and a
> compound file storage object in that memory. It then populates the
> FORMATETC structure, gets the client site, and creates the object within
> the provided storage. The result is an IUnknown pointer to the object that
> is then converted to a true IOleObject pointer by a call to
QueryInterface.

> 5. Populate the RichEdit Object (REOBJECT) structure so it can call
> InsertObject through the IRichEditOle pointer stored earlier. The
following
> code fills this structure:

>         REOBJECT reobject;
>         ZeroMemory(&reobject, sizeof(REOBJECT));
>         reobject.cbStruct = sizeof(REOBJECT);
>         CLSID clsid;
>         SCODE sc = m_lpObject->GetUserClassID(&clsid);
>         if (sc != S_OK)
>                 AfxThrowOleException(sc);
>         reobject.clsid = clsid;
>         reobject.cp = REO_CP_SELECTION;
>         reobject.dvaspect = DVASPECT_CONTENT;
>         reobject.dwFlags = REO_RESIZABLE | REO_BELOWBASELINE;
>         reobject.dwUser = 0;
>         reobject.poleobj = m_lpObject;
>         ASSERT(m_lpClientSite != NULL);
>         reobject.polesite = m_lpClientSite;
>         ASSERT(m_lpStorage != NULL);
>         reobject.pstg = m_lpStorage;
>         SIZEL sizel;
>         sizel.cx = sizel.cy = 0;
>         reobject.sizel = sizel;

> 6. At this point, make the InsertObject call. Insert the bitmap at the
> bottom of the file. A combination of EM_GETSEL/EM_SETSEL messages selects
> the document's text and positions the cursor at the end.

>         HWND hWndRT = (HWND)m_ctlRichText.GetHwnd();
>         ::SendMessage(hWndRT, EM_SETSEL, 0, -1);
>         DWORD dwStart, dwEnd;
>         ::SendMessage(hWndRT, EM_GETSEL, (WPARAM)&dwStart,
(LPARAM)&dwEnd);
>         ::SendMessage(hWndRT, EM_SETSEL, dwEnd+1, dwEnd+1);

> 7. Call InsertObject but add a carriage return first as in the following
> sample:

>         CString strCr = "\r\n";
>         m_ctlRichText.SetSelText((LPCTSTR)strCr);

> Finally!

>         m_pRichEditOle->InsertObject(&reobject);

> 8. The bitmap is dropped neatly at the bottom of the document with a
> carriage return separating it from the body of the text as in the
following
> code sample:

>         ::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);

> 9. This message scrolls the document to the caret position and the bitmap
> rolls into view. To repeat this, release the interface pointers:

>         if (m_lpObject)
>         {
>                 m_lpObject->Release();
>                 m_lpObject = NULL;
>         }
>         if (m_lpStorage)
>         {
>                 m_lpStorage->Release();
>                 m_lpStorage = NULL;
>         }
>         if (m_lpClientSite)
>         {
>                 m_lpClientSite->Release();
>                 m_lpClientSite = NULL;
>         }

> 10. Finally, release m_pRichEditOle.

> There is a KB about this issue:
> http://support.microsoft.com/support/kb/articles/Q220/8/44.ASP

> This posting is provided "AS IS" with no warranties, and confers no
rights.
> You assume all risk for your use.   2001 Microsoft Corporation. All rights
> reserved.

> Lion Shi
> Microsoft Support Engineer



Sat, 27 Mar 2004 15:23:17 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. Display bitmaps in Print Preview and printing bitmaps.

2. 8 bit (256 color) bitmaps vs 24 bit bitmaps

3. Richeditview,printing and windows 2000

4. RichEditView Read Only Caret Problem?

5. RichEditView StreamIn Problem?

6. Printing RichEditView

7. How can I Insert OLE Item into RichEditView?

8. Printing in RichEditView

9. About RichEditView

10. Problem with Set Text Format in RichEditView class

11. RichEditView Page Breaks

12. RichEditView (like) functionality

 

 
Powered by phpBB® Forum Software