OLEオブジェクトのサイズを変更するプログラムです。
以前のプログラムに以下を書き加えます。
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 |
public class RichTextBoxOle { [DllImport("OLE32.DLL")] public extern static int OleLoad(IStorage pStg, [In()] ref Guid riid, IOleClientSite pClientSite, [MarshalAs(UnmanagedType.IUnknown)] out object ppvObj); static public bool SetSizeFromCharIndex(RichTextBox rich, int charIndex, Size sizel) { if (!(rich.SelectionType == RichTextBoxSelectionTypes.Object && rich.SelectionLength == 1)) return false; int start = rich.SelectionStart; int len = rich.SelectionLength; rich.Select(charIndex, 1); RichTextBox r = new RichTextBox(); r.SelectedRtf = rich.SelectedRtf; IOleClientSite oleClientSite; REOBJECT reo = new REOBJECT(); IRichEditOle richEditOle = GetRichEditOle(r); if (richEditOle.GetObjectCount() == 0) { if (richEditOle != null) Marshal.ReleaseComObject(richEditOle); return false; } richEditOle.GetClientSite(out oleClientSite); richEditOle.GetObject(0, reo, GETOBJECTOPTIONS.REO_GETOBJ_ALL_INTERFACES); object ppvObjj; Guid IID_IOleObject = new Guid("{00000112-0000-0000-C000-000000000046}"); int ret = OleLoad(reo.pstg, ref IID_IOleObject, oleClientSite, out ppvObjj); IOleObject oleObject = (IOleObject)ppvObjj; REOBJECT newReo = new REOBJECT(); newReo.clsid = reo.clsid; newReo.cp = 0; newReo.dvAspect = reo.dvAspect; newReo.dwFlags = reo.dwFlags; newReo.dwUser = reo.dwUser; newReo.poleobj = oleObject; newReo.polesite = oleClientSite; newReo.pstg = reo.pstg; newReo.sizel = sizel; richEditOle.InsertObject(newReo); r.Select(0, 1); rich.Select(charIndex, 1); rich.SelectedRtf = r.SelectedRtf; if (reo.pstg != null) Marshal.ReleaseComObject(reo.pstg); if (reo.polesite != null) Marshal.ReleaseComObject(reo.polesite); if (reo.poleobj != null) Marshal.ReleaseComObject(reo.poleobj); if (richEditOle != null) Marshal.ReleaseComObject(richEditOle); r.Dispose(); rich.Select(start, len); return true; } static public Size GetOleObjectSize(RichTextBox rich, int cp) { IRichEditOle richEditOle = GetRichEditOle(rich); int count = richEditOle.GetObjectCount(); int i = 0; REOBJECT reo = null; for (i = 0; i < count; i++) { reo = new REOBJECT(); richEditOle.GetObject(i, reo, GETOBJECTOPTIONS.REO_GETOBJ_NO_INTERFACES); if (reo.cp == cp) break; reo = null; } if (reo != null) { return reo.sizel; } return new Size(0, 0); } } |
これでOLEオブジェクトのみが選択されているときに
1 2 3 4 |
Size size = RichTextBoxOle.RichTextBoxOle.GetOleObjectSize(richTextBox1, richTextBox1.SelectionStart); size.Width /= 2; size.Height /= 2; RichTextBoxOle.RichTextBoxOle.SetSizeFromCharIndex(richTextBox1, richTextBox1.SelectionStart, size); |
を実行するとサイズが1/2になります。OLEオブジェクトが選択されていないとき、それ以外の文字も選択されている場合は何も起きません。
それからマウス操作でOLEオブジェクトのサイズを変更されたときに他のRichTextBoxにも反映されるようにしておきましょう。
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 |
public partial class SyncRichTextBox : UserControl { string oleObject = ""; private void RichTextBoxEx1_MouseDown(object sender, MouseEventArgs e) { if (richTextBoxEx1.SelectionType == RichTextBoxSelectionTypes.Object && richTextBoxEx1.SelectionLength == 1) oleObject = richTextBoxEx1.SelectedRtf; else oleObject = ""; } private void RichTextBoxEx1_MouseUp(object sender, MouseEventArgs e) { if (richTextBoxEx1.SelectionType == RichTextBoxSelectionTypes.Object && richTextBoxEx1.SelectionLength == 1) { string newOleObject = richTextBoxEx1.SelectedRtf; if (GetOleObjectSizeText(oleObject) != GetOleObjectSizeText(newOleObject)) { BeginControlUpdate(); // 後述 int oldStart = richTextBoxEx1.SelectionStart; richTextBoxEx1.SelectedRtf = oleObject; richTextBoxEx1.Select(oldStart, 1); if (SetSelectedRtf(newOleObject, "OleObjectSizeChanged")) { Data.GetUndobuf().newSelectionStart = oldStart; Data.GetUndobuf().newSelectionLength = 1; richTextBoxEx1.Select(oldStart, 1); } EndControlUpdate(); // 後述 } } oleObject = ""; } string GetOleObjectSizeText(string oleRtfData) { int a = oleRtfData.IndexOf("\\picw"); if (a == -1) return ""; int b = oleRtfData.IndexOf("\n", a); string sub = oleRtfData.Substring(a, b - a); return sub; } } |
マウスボタンが押されたときと離されたときにSelectedRtfを比較して異なっていれば変更するというプログラムでいけるのかと思ったらそうではなかったらしく、保存するたびにデータが変更されるようです。そこでRtfの内容をしらべてオブジェクトの表示サイズを取得しています(GetOleObjectSizeTextメソッド)。
オブジェクトの表示サイズが異なっていれば、SetSelectedRtfメソッドを利用して内容を同期させています。
ところでこの処理をするときにオブジェクトのサイズが一瞬、大きくなったり小さくなったりするのでBeginControlUpdate、EndControlUpdateメソッドを自作しました。再描画を一時停止することでオブジェクトの表示サイズを変更するときの違和感を減らしています。