Movatterモバイル変換


[0]ホーム

URL:


Wayback Machine
28 captures
23 Dec 2007 - 28 Oct 2016
OctJANJun
Previous capture02Next capture
201020122013
success
fail
COLLECTED BY
Organization:Alexa Crawls
Starting in 1996,Alexa Internet has been donating their crawl data to the Internet Archive. Flowing in every day, these data are added to theWayback Machine after an embargo period.
Collection:Alexa Crawls
Starting in 1996,Alexa Internet has been donating their crawl data to the Internet Archive. Flowing in every day, these data are added to theWayback Machine after an embargo period.
TIMESTAMPS
loading
The Wayback Machine - https://web.archive.org/web/20120102072555/http://www.codeproject.com:80/KB/edit/MyExtRichTextBox.aspx
Click here to Skip to main content
8,377,579 members and growing!
EmailPassword Lost password?
Home
Search within:




Licence 
First Posted 1 Nov 2005
Views 164,054
Downloads 1,595
Bookmarked 83 times

Inserting images into a RichTextBox control (the OLE way)

ByOscar Londono | 1 Nov 2005
This article shows how you can insert images, controls and ActiveX objects into a .NET RichTextBox control by using the OLE way. There are several samples about how it could be done, but all of them are in C++ and I needed it for managed code (C#).
 
See Also
Print Article
add
Add to your CodeProject bookmarks
Discuss
Discuss this article
86
  4.96 (17 votes)
1 vote, 5.9%
1

2

3
1 vote, 5.9%
4
15 votes, 88.2%
5
4.96/5 - 17 votes
1 removed
μ 4.83, σa 1.72 [?]
Sponsored Links

Sample Image - MyExtRichTextBox.jpg

Introduction

This article shows how you can insert images, controls and ActiveX objects into a .NETRichTextBox control by using the OLE way, like explained in theMicrosoft site. Unfortunately, it covers only the sample with a C++ source code, so I need to implement a similar solution in managed code (C#).

There are other related articles for inserting images and OLE objects into aRichTextBox, but they are using RTF codes, and I need a more specialized control suitable to be used for chat and to provide a way to insert emoticons, progress bars and images, and finally, recover them by getting their OLE handles or any object attribute.

Special thanks toKhendys Gordon for the article: "Insert Plain Text and Images into RichTextBox at Runtime" andJohn Fisher for his article: "Use IRichEditOle from C#".

Background

To achieve the solution, I need to use the P/Invoke (Platform Invoke) methods. I got a lot of information frompinvoke.net.

The first step to insert an OLE object into aRichTextBox is to get itsIRichEditOle interface. It could be done, by sending the messageEM_GETOLEINTERFACE to the control:

this.IRichEditOle = SendMessage(richEditHandle, EM_GETOLEINTERFACE,0);

With this interface, you can insert objects through theREOBJECTstruct. It is important to note the you can specify the insertion point, the aspect and thedwUser variable to store flags or any related information for this object, so you can recover it at any time for update.

//-----------------------REOBJECT reoObject=new REOBJECT();reoObject.cp =this._richEdit.TextLength;reoObject.clsid = guid;reoObject.pstg = pStorage;reoObject.poleobj = Marshal.GetIUnknownForObject(control);reoObject.polesite = pOleClientSite;reoObject.dvAspect = (uint)(DVASPECT.DVASPECT_CONTENT);reoObject.dwFlags = (uint)(REOOBJECTFLAGS.REO_BELOWBASELINE);reoObject.dwUser =1;this.IRicEditOle.InsertObject(reoObject);//-----------------------

For inserting images, you need to implement the interfaceIDataObject, in this case I named itmyDataObject. This class is an OLE callback object that uses theFORMATETC and theSTGMEDIUM structures to display the image, telling to the OLE container that this object is a GDI medium (TYMED_GDI) with a bitmap clipboard format (CF_BITMAP).

publicclass myDataObject : IDataObject{private Bitmap mBitmap;public FORMATETC mpFormatetc;#region IDataObject Membersprivateconstuint S_OK =0;privateconstuint E_POINTER = 0x80004003;privateconstuint E_NOTIMPL = 0x80004001;privateconstuint E_FAIL = 0x80004005;publicuint GetData(ref FORMATETC pFormatetc,ref STGMEDIUM pMedium)    {IntPtr hDst = mBitmap.GetHbitmap();        pMedium.tymed = (int)TYMED.TYMED_GDI;        pMedium.unionmember = hDst;        pMedium.pUnkForRelease =IntPtr.Zero;return (uint)S_OK;    }    ...#endregionpublic myDataObject()    {        mBitmap =new Bitmap(16,16);        mpFormatetc =new FORMATETC();    }publicvoid SetImage(string strFilename)    {try        {            mBitmap = (Bitmap)Bitmap.FromFile(strFilename,true);// Clipboard format = CF_BITMAP            mpFormatetc.cfFormat = CLIPFORMAT.CF_BITMAP;// Target Device = Screen            mpFormatetc.ptd =IntPtr.Zero;// Level of detail = Full content            mpFormatetc.dwAspect = DVASPECT.DVASPECT_CONTENT;// Index = Not applicaple            mpFormatetc.lindex = -1;// Storage medium = HBITMAP handle            mpFormatetc.tymed = TYMED.TYMED_GDI;        }catch        {        }    }publicvoid SetImage(Image image)    {try        {            mBitmap =new Bitmap(image);// Clipboard format = CF_BITMAP            mpFormatetc.cfFormat = CLIPFORMAT.CF_BITMAP;// Target Device = Screen            mpFormatetc.ptd =IntPtr.Zero;// Level of detail = Full content            mpFormatetc.dwAspect = DVASPECT.DVASPECT_CONTENT;// Index = Not applicaple            mpFormatetc.lindex = -1;// Storage medium = HBITMAP handle            mpFormatetc.tymed = TYMED.TYMED_GDI;        }catch        {        }    }}

Take a look at how the member methodSetImage creates aBitmap object to use its handle when theGetData is called.

Now, here is how the object is inserted into theRichEditBox creating a shared global memory and getting a pointer to it (IStorage) and using theOleClientSite interface from theIRichEditOle.

publicvoid InsertMyDataObject(myDataObject mdo){if (mdo ==null)return;//-----------------------    ILockBytes pLockBytes;int sc = CreateILockBytesOnHGlobal(IntPtr.Zero,true,out pLockBytes);    IStorage pStorage;    sc = StgCreateDocfileOnILockBytes(pLockBytes, (uint)        (STGM.STGM_SHARE_EXCLUSIVE|STGM.STGM_CREATE|                                   STGM.STGM_READWRITE),0,out pStorage);        IOleClientSite pOleClientSite;this.IRichEditOle.GetClientSite(out pOleClientSite);//-----------------------    Guid guid = Marshal.GenerateGuidForType(mdo.GetType());    Guid IID_IOleObject =new Guid("{00000112-0000-0000-C000-000000000046}");    Guid IID_IDataObject =new Guid("{0000010e-0000-0000-C000-000000000046}");    Guid IID_IUnknown =new Guid("{00000000-0000-0000-C000-000000000046}");object pOleObject;int hr = OleCreateStaticFromData(mdo,ref IID_IOleObject,         (uint)OLERENDER.OLERENDER_FORMAT,ref mdo.mpFormatetc,        pOleClientSite, pStorage,out pOleObject);if (pOleObject ==null)return;//-----------------------//-----------------------    OleSetContainedObject(pOleObject,true);    REOBJECT reoObject =new REOBJECT();    reoObject.cp =this._richEdit.TextLength;    reoObject.clsid = guid;    reoObject.pstg = pStorage;    reoObject.poleobj = Marshal.GetIUnknownForObject(pOleObject);    reoObject.polesite = pOleClientSite;    reoObject.dvAspect = (uint)(DVASPECT.DVASPECT_CONTENT);    reoObject.dwFlags = (uint)(REOOBJECTFLAGS.REO_BELOWBASELINE);    reoObject.dwUser =0;this.IRichEditOle.InsertObject(reoObject);//-----------------------//-----------------------    Marshal.ReleaseComObject(pLockBytes);    Marshal.ReleaseComObject(pOleClientSite);    Marshal.ReleaseComObject(pStorage);    Marshal.ReleaseComObject(pOleObject);//-----------------------}

There are other methods to insert controls and ActiveX objects, they look very similar to the above method, so please review the source code.

Points of Interest

And finally, how are the controls updated?

This is the trick, you need to use a timer and call the methodUpdateObjects. This method performs a search for all objects in theRichTextBox and if they are marked as special (in my case I use thedwUser variable), they will be updated:

publicvoid UpdateObjects(){int k =this.IRichEditOle.GetObjectCount();for (int i =0; i < k; i++)    {        REOBJECT reoObject =new REOBJECT();this.IRichEditOle.GetObject(i, reoObject,           GETOBJECTOPTIONS.REO_GETOBJ_ALL_INTERFACES);if (reoObject.dwUser ==1)        {            Point pt =this._richEdit.GetPositionFromCharIndex(reoObject.cp);            Rectangle rect =new Rectangle(pt, reoObject.sizel);this._richEdit.Invalidate(rect,false);// repaint        }    }}

There is a lot of work required for optimizing this control but for now, any suggestion is appreciated.

Using the code

To use the code, simply add a reference to the control, put a normalRichTextBox into the form and then replace the type forMyExtRichTextBox:

MyExtRichTextBox.MyExtRichTextBox richTextBox1;

Tip

I update objects by creating an array of controls (buttons and progress bars) and adding a timer to the form, then calling the methodUpdateObjects like this:

privatevoid timer1_Tick(object sender, System.EventArgs e){for (int i =0; i < ar.Count; i++)    {        itimer++;if (itimer >100)            itimer =0;object obj = ar[i];if (objis Button)        {            Button bt = (Button) obj;if (bt.Text !="Clicked")                bt.Text ="button " + i.ToString() +" - " + itimer.ToString();        }else        {            ProgressBar pb = (ProgressBar) obj;if (pb.Value +1 >100)                pb.Value =0;            pb.Value = pb.Value +1;        }    }    richTextBox1.UpdateObjects();}

History

  • Version 1.0 - Nov. 1 / 2005

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be foundhere

About the Author

Oscar Londono

Software Developer (Senior)
Kinecor Ltee
Canada Canada

Member
I have been working for 16 years as Analyst Programmer in several companies.
 
I love the Object Oriented Programming paradigm and now, I love C#. Currently, I works with X++ in Microsoft Dynamics AX systems.
 
Also, I like to perform my work by using methodologies like Rational Unified Process (RUP).
 
Please, take a look to my last project:Meetgate

loading...
Sign Up to vote  PoorExcellent
Add a reason or comment to your vote:x
Votes of 3 or less require a comment

Comments and Discussions

 
 RefreshFirstPrevNext
Questionhow to print?membersbryu916@naver.com16:03 9 Mar '11  
GeneralNot able to access COM activex control's property before inserting it to myExtRichTextBOx controlmemberbibhucodeproject2:16 3 May '10  
Generalimage (-object) is not below the baselinememberchand0054:34 13 Mar '10  
GeneralObject and Memory ManagementmemberCLoUdYvIsIoN10:33 2 Dec '09  
QuestionAnimated gifsmemberMember 39617226:34 4 Aug '09  
AnswerRe: Animated gifsmemberCLoUdYvIsIoN10:42 2 Dec '09  
GeneralUnable to cast COM object of type 'System.__ComObject' to interface type 'MyExtRichTextBox.IRichEditOle'memberchenyonghao16:01 30 Mar '09  
GeneralRemoving Ole Object from RTBmemberThe Innovator10:10 24 Mar '09  
QuestionHow could the OLE content be saved in SQL Server?memberRadox4:18 26 Jan '09  
AnswerRe: How could the OLE content be saved in SQL Server?membercodemachine9998:24 11 Nov '09  
Last Visit: 19:00 31 Dec '99     Last Update: 21:25 1 Jan '12123456789Next »

General General   News News   Suggestion Suggestion   Question Question   Bug Bug   Answer Answer   Joke Joke   Rant Rant   Admin Admin   

Permalink |Advertise |Privacy |Mobile
Web04 |2.5.111208.1 |Last Updated 1 Nov 2005
Article Copyright 2005 by Oscar Londono
Everything elseCopyright ©CodeProject, 1999-2012
Terms of Use
Layout:fixed|fluid

See Also...
The Daily Insider

[8]ページ先頭

©2009-2025 Movatter.jp