画像ファイルをドロップすればRichTextBoxに画像を挿入することができますが、ダブルクリックしても編集することができません。編集可能なbmpオブジェクトを挿入するためにはどうすればいいのでしょうか?
参照の追加でMicrosoft.VisualStudio.OLE.Interop.dllを追加しておく必要があります。また
1 2 |
using Microsoft.VisualStudio.OLE.Interop; using System.Runtime.InteropServices; |
をいれておきましょう。
IRichEditOleインターフェイスを取得する
IRichEditOle.InsertObjectメソッドを実行
これで可能ですが、そのためにはInsertObjectメソッドに渡すREOBJECTのメンバーをセットする必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 |
typedef struct _reobject { DWORD cbStruct; LONG cp; // どこに挿入するか CLSID clsid; // クラスID LPOLEOBJECT poleobj; // IOleObject LPSTORAGE pstg; // IStorage LPOLECLIENTSITE polesite; // IOleClientSite SIZEL sizel; // 表示サイズ DWORD dvaspect; // Display aspect used DWORD dwFlags; // Object status flag DWORD dwUser; } |
Contents
IRichEditOleを取得する方法
まずIRichEditOleインターフェイスを取得する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
public partial class Form1 : Form { [ComImport(), Guid("00020D00-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IRichEditOle { [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int GetClientSite(out IOleClientSite site); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int GetObjectCount(); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int GetLinkCount(); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int GetObject(int iob, [In, Out] REOBJECT lpreobject, [MarshalAs(UnmanagedType.U4)]GETOBJECTOPTIONS flags); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int InsertObject(REOBJECT lpreobject); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int ConvertObject(int iob, Guid rclsidNew, string lpstrUserTypeNew); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int ActivateAs(Guid rclsid, Guid rclsidAs); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int SetHostNames(string lpstrContainerApp, string lpstrContainerObj); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int SetLinkAvailable(int iob, bool fAvailable); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int SetDvaspect(int iob, uint dvaspect); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int HandsOffStorage(int iob); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int SaveCompleted(int iob, IStorage lpstg); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int InPlaceDeactivate(); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int ContextSensitiveHelp(bool fEnterMode); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int GetClipboardData([In, Out] ref CHARRANGE lpchrg, [MarshalAs(UnmanagedType.U4)] GETCLIPBOARDDATAFLAGS reco, out Microsoft.VisualStudio.OLE.Interop.IDataObject lplpdataobj); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int ImportDataObject(Microsoft.VisualStudio.OLE.Interop.IDataObject lpdataobj, int cf, IntPtr hMetaPict); } [StructLayout(LayoutKind.Sequential)] public class REOBJECT { public int cbStruct = Marshal.SizeOf(typeof(REOBJECT)); // Size of structure public int cp; // Character position of object public Guid clsid; // Class ID of object public IOleObject poleobj; // OLE object interface public IStorage pstg; // Associated storage interface public IOleClientSite polesite; // Associated client site interface public Size sizel; // Size of object (may be 0,0) public uint dvAspect; // Display aspect to use public uint dwFlags; // Object status flags public uint dwUser; // Dword for user's use } } |
このなかにGETOBJECTOPTIONSとかGETCLIPBOARDDATAFLAGSがあります。そこで
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
public partial class Form1 : Form { public enum GETOBJECTOPTIONS { REO_GETOBJ_NO_INTERFACES = 0x00000000, REO_GETOBJ_POLEOBJ = 0x00000001, REO_GETOBJ_PSTG = 0x00000002, REO_GETOBJ_POLESITE = 0x00000004, REO_GETOBJ_ALL_INTERFACES = 0x00000007, } [StructLayout(LayoutKind.Sequential)] public struct CHARRANGE { public int cpMin; public int cpMax; } public enum GETCLIPBOARDDATAFLAGS { RECO_PASTE = 0, RECO_DROP = 1, RECO_COPY = 2, RECO_CUT = 3, RECO_DRAG = 4 } [Flags(), ComVisible(false)] public enum REOOBJECTFLAGS : uint { REO_NULL = 0x00000000, // No flags REO_READWRITEMASK = 0x0000003F, // Mask out RO bits REO_DONTNEEDPALETTE = 0x00000020, // Object doesn't need palette REO_BLANK = 0x00000010, // Object is blank REO_DYNAMICSIZE = 0x00000008, // Object defines size always REO_INVERTEDSELECT = 0x00000004, // Object drawn all inverted if sel REO_BELOWBASELINE = 0x00000002, // Object sits below the baseline REO_RESIZABLE = 0x00000001, // Object may be resized REO_LINK = 0x80000000, // Object is a link (RO) REO_STATIC = 0x40000000, // Object is static (RO) REO_SELECTED = 0x08000000, // Object selected (RO) REO_OPEN = 0x04000000, // Object open in its server (RO) REO_INPLACEACTIVE = 0x02000000, // Object in place active (RO) REO_HILITED = 0x01000000, // Object is to be hilited (RO) REO_LINKAVAILABLE = 0x00800000, // Link believed available (RO) REO_GETMETAFILE = 0x00400000 // Object requires metafile (RO) } } |
も必要です。
またAPI関数も使うので以下を記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public partial class Form1 : Form { [DllImport("ole32.dll")] public static extern int CreateILockBytesOnHGlobal(IntPtr hGlobal, [MarshalAs(UnmanagedType.Bool)] bool fDeleteOnRelease, [Out] out ILockBytes ppLkbyt); [DllImport("ole32.dll")] public static extern int StgCreateDocfileOnILockBytes(ILockBytes plkbyt, uint grfMode, uint reserved, out IStorage ppstgOpen); [DllImport("ole32.dll")] public static extern int OleSetContainedObject([MarshalAs(UnmanagedType.IUnknown)] object pUnk, bool fContained); [DllImport("ole32.dll")] public static extern int OleCreateFromFile([In] ref Guid rclsid, [MarshalAs(UnmanagedType.LPWStr)] string lpszFileName, [In] ref Guid riid, uint renderopt, [In] IntPtr pFormatEtc, IOleClientSite pClientSite, IStorage pStg, [MarshalAs(UnmanagedType.IUnknown)] out object ppvObj); [DllImport("User32", CharSet = CharSet.Auto)] public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, out IRichEditOle lParam); } |
まず、IRichEditOleを取得するには
1 2 3 4 5 |
public const int WM_USER = 0x0400; public const int EM_GETOLEINTERFACE = WM_USER + 60; IRichEditOle richEditOle = null; SendMessage(rictTextBox1.Handle, EM_GETOLEINTERFACE, 0, out richEditOle); |
これで取得できます。
IOleClientSiteを取得する方法
IRichEditOleが取得できたらIOleClientSiteを取得します。
1 2 |
IOleClientSite pOleClientSite; int hr = richEditOle.GetClientSite(out pOleClientSite); |
とやればIOleClientSiteも取得できます。
IStorageを取得する方法
またIStorageは
1 2 3 4 5 6 7 8 |
ILockBytes pLockBytes; int hr = CreateILockBytesOnHGlobal(IntPtr.Zero, true, out pLockBytes); int STGM_READWRITE = 0x2; int STGM_CREATE = 0x1000; int STGM_SHARE_EXCLUSIVE = 0x10; hr = StgCreateDocfileOnILockBytes(pLockBytes, (uint)(STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE), 0, out pStorage); |
IOleObjectを取得する方法
IOleObjectはIOleClientSiteとIStorageを利用して
1 2 3 4 5 6 7 |
Guid IID_IOleObject = new Guid("{00000112-0000-0000-C000-000000000046}"); Guid CLSID_NULL = new Guid("{00000000-0000-0000-0000-000000000000}"); object pOleObjectOut; hr = OleCreateFromFile(ref CLSID_NULL, strFilename, ref IID_IOleObject, (uint)OLERENDER.OLERENDER_DRAW, IntPtr.Zero, pOleClientSite, pStorage, out pOleObjectOut); IOleObject OleObject = (IOleObject)pOleObjectOut; |
で取得できます。
ClassIDを取得する方法
ClassIDはIOleObjectを利用して
1 2 |
Guid guid; OleObject.GetUserClassID(out guid); |
仕上げ
あとはこれらをREOBJECTにセットします。
1 2 3 4 5 6 7 8 9 10 11 |
REOBJECT reoObject = new REOBJECT(); reoObject.cp = rictTextBox1.SelectionStart; reoObject.clsid = guid; reoObject.pstg = pStorage; reoObject.poleobj = OleObject; reoObject.polesite = pOleClientSite; reoObject.dvAspect = (uint)(DVASPECT.DVASPECT_CONTENT); reoObject.dwFlags = (uint)(REOOBJECTFLAGS.REO_RESIZABLE | REOOBJECTFLAGS.REO_BELOWBASELINE); reoObject.dwUser = 0; |
そしてInsertObjectを実行します。
1 |
richEditOle.InsertObject(reoObject); |
終わったら後片付け。
1 2 3 4 5 6 |
Marshal.ReleaseComObject(pLockBytes); Marshal.ReleaseComObject(pOleClientSite); Marshal.ReleaseComObject(pStorage); Marshal.ReleaseComObject(OleObject); Marshal.ReleaseComObject(pLockBytes); Marshal.ReleaseComObject(richEditOle); |
よく使うかもしれないのでライブラリ化してもいいかも
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
namespace RichTextBoxOle { public class RichTextBoxOle { [DllImport("User32", CharSet = CharSet.Auto)] public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, out IRichEditOle lParam); [DllImport("ole32.dll")] public static extern int CreateILockBytesOnHGlobal(IntPtr hGlobal, [MarshalAs(UnmanagedType.Bool)] bool fDeleteOnRelease, [Out] out ILockBytes ppLkbyt); [DllImport("ole32.dll")] public static extern int StgCreateDocfileOnILockBytes(ILockBytes plkbyt, uint grfMode, uint reserved, out IStorage ppstgOpen); [DllImport("ole32.dll")] public static extern int OleSetContainedObject([MarshalAs(UnmanagedType.IUnknown)] object pUnk, bool fContained); [DllImport("ole32.dll")] public static extern int OleCreateFromFile([In] ref Guid rclsid, [MarshalAs(UnmanagedType.LPWStr)] string lpszFileName, [In] ref Guid riid, uint renderopt, [In] IntPtr pFormatEtc, IOleClientSite pClientSite, IStorage pStg, [MarshalAs(UnmanagedType.IUnknown)] out object ppvObj); [ComImport(), Guid("00020D00-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IRichEditOle { [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int GetClientSite(out IOleClientSite site); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int GetObjectCount(); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int GetLinkCount(); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int GetObject(int iob, [In, Out] REOBJECT lpreobject, [MarshalAs(UnmanagedType.U4)]GETOBJECTOPTIONS flags); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int InsertObject(REOBJECT lpreobject); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int ConvertObject(int iob, Guid rclsidNew, string lpstrUserTypeNew); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int ActivateAs(Guid rclsid, Guid rclsidAs); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int SetHostNames(string lpstrContainerApp, string lpstrContainerObj); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int SetLinkAvailable(int iob, bool fAvailable); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int SetDvaspect(int iob, uint dvaspect); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int HandsOffStorage(int iob); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int SaveCompleted(int iob, IStorage lpstg); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int InPlaceDeactivate(); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int ContextSensitiveHelp(bool fEnterMode); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int GetClipboardData([In, Out] ref CHARRANGE lpchrg, [MarshalAs(UnmanagedType.U4)] GETCLIPBOARDDATAFLAGS reco, out Microsoft.VisualStudio.OLE.Interop.IDataObject lplpdataobj); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int ImportDataObject(Microsoft.VisualStudio.OLE.Interop.IDataObject lpdataobj, int cf, IntPtr hMetaPict); } [StructLayout(LayoutKind.Sequential)] public class REOBJECT { public int cbStruct = Marshal.SizeOf(typeof(REOBJECT)); // Size of structure public int cp; // Character position of object public Guid clsid; // Class ID of object public IOleObject poleobj; // OLE object interface public IStorage pstg; // Associated storage interface public IOleClientSite polesite; // Associated client site interface public Size sizel; // Size of object (may be 0,0) public uint dvAspect; // Display aspect to use public uint dwFlags; // Object status flags public uint dwUser; // Dword for user's use } public enum GETOBJECTOPTIONS { REO_GETOBJ_NO_INTERFACES = 0x00000000, REO_GETOBJ_POLEOBJ = 0x00000001, REO_GETOBJ_PSTG = 0x00000002, REO_GETOBJ_POLESITE = 0x00000004, REO_GETOBJ_ALL_INTERFACES = 0x00000007, } [StructLayout(LayoutKind.Sequential)] public struct CHARRANGE { public int cpMin; public int cpMax; } public enum GETCLIPBOARDDATAFLAGS { RECO_PASTE = 0, RECO_DROP = 1, RECO_COPY = 2, RECO_CUT = 3, RECO_DRAG = 4 } [Flags(), ComVisible(false)] public enum REOOBJECTFLAGS : uint { REO_NULL = 0x00000000, // No flags REO_READWRITEMASK = 0x0000003F, // Mask out RO bits REO_DONTNEEDPALETTE = 0x00000020, // Object doesn't need palette REO_BLANK = 0x00000010, // Object is blank REO_DYNAMICSIZE = 0x00000008, // Object defines size always REO_INVERTEDSELECT = 0x00000004, // Object drawn all inverted if sel REO_BELOWBASELINE = 0x00000002, // Object sits below the baseline REO_RESIZABLE = 0x00000001, // Object may be resized REO_LINK = 0x80000000, // Object is a link (RO) REO_STATIC = 0x40000000, // Object is static (RO) REO_SELECTED = 0x08000000, // Object selected (RO) REO_OPEN = 0x04000000, // Object open in its server (RO) REO_INPLACEACTIVE = 0x02000000, // Object in place active (RO) REO_HILITED = 0x01000000, // Object is to be hilited (RO) REO_LINKAVAILABLE = 0x00800000, // Link believed available (RO) REO_GETMETAFILE = 0x00400000 // Object requires metafile (RO) } static public void InsertFileBmpIfImage(RichTextBox rich, string filePath, int cp) { try { Image image = Image.FromFile(filePath); string temp = Application.StartupPath + "\\abc.bmp"; image.Save(temp, ImageFormat.Bmp); InsertFile(rich, temp, cp); System.IO.File.Delete(temp); } catch { InsertFile(rich, filePath, cp); } } static public void InsertFile(RichTextBox rich, string filePath, int cp) { int WM_USER = 0x0400; int EM_GETOLEINTERFACE = WM_USER + 60; IRichEditOle richEditOle = null; SendMessage(rich.Handle, EM_GETOLEINTERFACE, 0, out richEditOle); IOleClientSite pOleClientSite; int hr = richEditOle.GetClientSite(out pOleClientSite); ILockBytes pLockBytes; hr = CreateILockBytesOnHGlobal(IntPtr.Zero, true, out pLockBytes); IStorage pStorage; int STGM_READWRITE = 0x2; int STGM_CREATE = 0x1000; int STGM_SHARE_EXCLUSIVE = 0x10; hr = StgCreateDocfileOnILockBytes(pLockBytes, (uint)(STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE), 0, out pStorage); Guid IID_IOleObject = new Guid("{00000112-0000-0000-C000-000000000046}"); Guid CLSID_NULL = new Guid("{00000000-0000-0000-0000-000000000000}"); object pOleObjectOut; hr = OleCreateFromFile(ref CLSID_NULL, filePath, ref IID_IOleObject, (uint)OLERENDER.OLERENDER_DRAW, IntPtr.Zero, pOleClientSite, pStorage, out pOleObjectOut); IOleObject OleObject = (IOleObject)pOleObjectOut; Guid guid; OleObject.GetUserClassID(out guid); REOBJECT reoObject = new REOBJECT(); reoObject.cp = cp; reoObject.clsid = guid; reoObject.pstg = pStorage; reoObject.poleobj = OleObject; reoObject.polesite = pOleClientSite; reoObject.dvAspect = (uint)(DVASPECT.DVASPECT_CONTENT); reoObject.dwFlags = (uint)(REOOBJECTFLAGS.REO_RESIZABLE | REOOBJECTFLAGS.REO_BELOWBASELINE); reoObject.dwUser = 0; richEditOle.InsertObject(reoObject); Marshal.ReleaseComObject(pLockBytes); Marshal.ReleaseComObject(pOleClientSite); Marshal.ReleaseComObject(pStorage); Marshal.ReleaseComObject(OleObject); Marshal.ReleaseComObject(pLockBytes); Marshal.ReleaseComObject(richEditOle); } } } |