using LYFZ.OtherExpansion.Win32; using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Runtime.InteropServices; using System.Windows.Forms; namespace LYFZ.OtherExpansion.SkinControl { public class RichEditOle { private SkinRichTextBox _richEdit; private IRichEditOle _richEditOle; public IRichEditOle IRichEditOle { get { if (this._richEditOle == null) { this._richEditOle = NativeMethods.SendMessage(this._richEdit.Handle, 1084, 0); } return this._richEditOle; } } public RichEditOle(SkinRichTextBox richEdit) { this._richEdit = richEdit; } public void InsertControl(Control control) { if (control != null) { Guid guid = Marshal.GenerateGuidForType(control.GetType()); ILockBytes bytes; NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true, out bytes); IStorage storage; NativeMethods.StgCreateDocfileOnILockBytes(bytes, 4114u, 0u, out storage); IOleClientSite site; this.IRichEditOle.GetClientSite(out site); REOBJECT lpreobject = new REOBJECT(); lpreobject.cp = this._richEdit.TextLength; lpreobject.clsid = guid; lpreobject.pstg = storage; lpreobject.poleobj = Marshal.GetIUnknownForObject(control); lpreobject.polesite = site; lpreobject.dvAspect = 1u; lpreobject.dwFlags = 2u; lpreobject.dwUser = 1u; this.IRichEditOle.InsertObject(lpreobject); Marshal.ReleaseComObject(bytes); Marshal.ReleaseComObject(site); Marshal.ReleaseComObject(storage); } } public bool InsertImageFromFile(string strFilename) { ILockBytes bytes; NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true, out bytes); IStorage storage; NativeMethods.StgCreateDocfileOnILockBytes(bytes, 4114u, 0u, out storage); IOleClientSite site; this.IRichEditOle.GetClientSite(out site); FORMATETC pFormatEtc = default(FORMATETC); pFormatEtc.cfFormat = (CLIPFORMAT)0; pFormatEtc.ptd = IntPtr.Zero; pFormatEtc.dwAspect = DVASPECT.DVASPECT_CONTENT; pFormatEtc.lindex = -1; pFormatEtc.tymed = TYMED.TYMED_NULL; Guid riid = new Guid("{00000112-0000-0000-C000-000000000046}"); Guid rclsid = new Guid("{00000000-0000-0000-0000-000000000000}"); object obj2; NativeMethods.OleCreateFromFile(ref rclsid, strFilename, ref riid, 1u, ref pFormatEtc, site, storage, out obj2); if (obj2 == null) { Marshal.ReleaseComObject(bytes); Marshal.ReleaseComObject(site); Marshal.ReleaseComObject(storage); return false; } IOleObject pUnk = (IOleObject)obj2; Guid pClsid = default(Guid); pUnk.GetUserClassID(ref pClsid); NativeMethods.OleSetContainedObject(pUnk, true); REOBJECT lpreobject = new REOBJECT(); lpreobject.cp = this._richEdit.TextLength; lpreobject.clsid = pClsid; lpreobject.pstg = storage; lpreobject.poleobj = Marshal.GetIUnknownForObject(pUnk); lpreobject.polesite = site; lpreobject.dvAspect = 1u; lpreobject.dwFlags = 2u; lpreobject.dwUser = 0u; this.IRichEditOle.InsertObject(lpreobject); Marshal.ReleaseComObject(bytes); Marshal.ReleaseComObject(site); Marshal.ReleaseComObject(storage); Marshal.ReleaseComObject(pUnk); return true; } public REOBJECT InsertOleObject(IOleObject oleObject, int index) { if (oleObject == null) { return null; } ILockBytes pLockBytes; NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true, out pLockBytes); IStorage pStorage; NativeMethods.StgCreateDocfileOnILockBytes(pLockBytes, 4114u, 0u, out pStorage); IOleClientSite pOleClientSite; this.IRichEditOle.GetClientSite(out pOleClientSite); Guid guid = default(Guid); oleObject.GetUserClassID(ref guid); NativeMethods.OleSetContainedObject(oleObject, true); REOBJECT reoObject = new REOBJECT(); reoObject.cp = this._richEdit.TextLength; reoObject.clsid = guid; reoObject.pstg = pStorage; reoObject.poleobj = Marshal.GetIUnknownForObject(oleObject); reoObject.polesite = pOleClientSite; reoObject.dvAspect = 1u; reoObject.dwFlags = 2u; reoObject.dwUser = (uint)index; this.IRichEditOle.InsertObject(reoObject); Marshal.ReleaseComObject(pLockBytes); Marshal.ReleaseComObject(pOleClientSite); Marshal.ReleaseComObject(pStorage); return reoObject; } public void UpdateObjects() { int objectCount = this.IRichEditOle.GetObjectCount(); for (int i = 0; i < objectCount; i++) { REOBJECT lpreobject = new REOBJECT(); this.IRichEditOle.GetObject(i, lpreobject, GETOBJECTOPTIONS.REO_GETOBJ_ALL_INTERFACES); Point positionFromCharIndex = this._richEdit.GetPositionFromCharIndex(lpreobject.cp); Rectangle rc = new Rectangle(positionFromCharIndex.X, positionFromCharIndex.Y, 50, 50); this._richEdit.Invalidate(rc, false); } } public void UpdateObjects(int pos) { REOBJECT lpreobject = new REOBJECT(); this.IRichEditOle.GetObject(pos, lpreobject, GETOBJECTOPTIONS.REO_GETOBJ_ALL_INTERFACES); this.UpdateObjects(lpreobject); } public void UpdateObjects(REOBJECT reObj) { Point positionFromCharIndex = this._richEdit.GetPositionFromCharIndex(reObj.cp); Size size = this.GetSizeFromMillimeter(reObj); Rectangle rc = new Rectangle(positionFromCharIndex, size); this._richEdit.Invalidate(rc, false); } private Size GetSizeFromMillimeter(REOBJECT lpreobject) { Size result; using (Graphics graphics = Graphics.FromHwnd(this._richEdit.Handle)) { Point[] pts = new Point[1]; graphics.PageUnit = GraphicsUnit.Millimeter; pts[0] = new Point(lpreobject.sizel.Width / 100, lpreobject.sizel.Height / 100); graphics.TransformPoints(CoordinateSpace.Device, CoordinateSpace.Page, pts); result = new Size(pts[0]); } return result; } } }