複数のRichTextBoxを同期する Cut、Copy、Paste編です。今回は簡単です。Pasteは別の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 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 |
public partial class SyncRichTextBox : UserControl { // Pasteメソッドで使用する public string SelectedRtf { get { return this.richTextBoxEx1.SelectedRtf; } } public void SetSelectedRtf(string rtf, string action) { foreach (var sync in Data.SyncRichTextBoxes) { var info = Data.GetRichTextBoxInfo(sync); if (info != null) { info.SelectionStart = sync.richTextBoxEx1.SelectionStart; } } Undobuf buf = new Undobuf(); buf.removeStart = richTextBoxEx1.SelectionStart; buf.removeLength = richTextBoxEx1.SelectionLength; buf.removeText = richTextBoxEx1.SelectedText; buf.removeRtf = richTextBoxEx1.SelectedRtf; buf.oldSelectionStart = richTextBoxEx1.SelectionStart; buf.oldSelectionLength = richTextBoxEx1.SelectionLength; buf.insertStart = richTextBoxEx1.SelectionStart; buf.insertRtf = rtf; var r = new RichTextBox(); r.SelectAll(); r.SelectedRtf = rtf; r.SelectAll(); buf.insertText = r.SelectedText; r.Dispose(); buf.insertLength = buf.insertText.Length; buf.newSelectionStart = richTextBoxEx1.SelectionStart + buf.insertText.Length; buf.newSelectionLength = 0; buf.action = action; OnTextChanging(buf); if (buf.IsCancel) return; foreach (var sync in Data.SyncRichTextBoxes) { var info = Data.GetRichTextBoxInfo(sync); int oldStart = info.SelectionStart; sync.richTextBoxEx1.Select(buf.removeStart, buf.removeLength); if (sync.Data == this.Data && sync != this) { sync.richTextBoxEx1.SelectedRtf = buf.insertRtf; int i = GetPositionAfterRemove(oldStart, buf.removeStart, buf.removeLength); i = GetPositionAfterInsert(i, buf.insertStart, buf.insertLength); sync.richTextBoxEx1.Select(i, 0); } else if (sync.Data == this.Data && sync == this) { sync.richTextBoxEx1.SelectedRtf = buf.insertRtf; } else if (sync.Data != this.Data) { int start = info.SelectionStart; int i = GetPositionAfterRemove(start, buf.removeStart, buf.removeLength); i = GetPositionAfterInsert(i, buf.insertStart, buf.insertLength); info.SelectionStart = i; } } Data.InsertUndobuf(buf); } public void Paste() { RichTextBox rich = new RichTextBox(); rich.Paste(); rich.SelectAll(); if (rich.SelectedText != "") { SetSelectedRtf(rich.SelectedRtf, "Paste"); } rich.Dispose(); } public void Copy() { if(richTextBoxEx1.SelectionLength > 0) richTextBoxEx1.Copy(); } public void Cut() { if (richTextBoxEx1.SelectionLength > 0) { richTextBoxEx1.Copy(); SetSelectedText("", "Cut"); } } protected override void OnKeyDown(KeyEventArgs e) { if ((e.KeyCode == Keys.V && e.Control) || (e.KeyCode == Keys.Insert && e.Shift)) { e.Handled = true; Paste(); return; } if (e.KeyCode == Keys.C && e.Control) { e.Handled = true; Copy(); return; } if (e.KeyCode == Keys.X && e.Control) { e.Handled = true; Cut(); return; } if (e.Control) { e.Handled = true; return; } base.OnKeyDown(e); } } |
これで完成!と言いたいところなのですが、画像ファイルをペーストするとファイルがロックされるという問題が発覚しました。ファイルをペーストする処理は別に考えたほうがいいのかな。
そこで・・・
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 |
public partial class SyncRichTextBox : UserControl { public void Paste() { if (Clipboard.ContainsFileDropList()) { var list = Clipboard.GetFileDropList(); OnFilePaste(list); return; } RichTextBox rich = new RichTextBox(); rich.Paste(); rich.SelectAll(); if (rich.SelectedText != "") { SetSelectedRtf(rich.SelectedRtf, "Paste"); } rich.Dispose(); } protected virtual void OnFilePaste(System.Collections.Specialized.StringCollection list) { // 自分で考える } } |
OnFilePasteの内容として
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 |
protected virtual void OnFilePaste(System.Collections.Specialized.StringCollection list) { string filePath = list[0]; RichTextBox rich = new RichTextBox(); var backup = Clipboard.GetDataObject(); try { Image img = Image.FromFile(filePath); Clipboard.SetImage(img); rich.Paste(); img.Dispose(); Clipboard.SetDataObject(backup, false); } catch { rich.Clear(); rich.Paste(); } rich.SelectAll(); if (rich.SelectedText != "") { SelectedRtf = rich.SelectedRtf; Data.GetUndobuf().action = "PasteFile"; } rich.Dispose(); } |
クリップボードにあるファイルが画像ファイルの場合、Image.FromFileでImageを取得、これをクリップボードに転送してペースト処理をしています。これだとファイルはロックされません。終わったらクリップボードの内容を元に戻します。
できればClipboard.SetDataObject(backup, false)ではなくClipboard.SetDataObject(backup, true)としたいのですが、これだとアプリがフリーズしてしまいます。
以前やった
のRichTextBoxOle.InsertFileBmpIfImageメソッドを使って
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
protected virtual void OnFilePaste(System.Collections.Specialized.StringCollection list) { string filePath = list[0]; this.SelectionLength = 0; RichTextBox rich = new RichTextBox(); RichTextBoxOle.RichTextBoxOle.InsertFileBmpIfImage(rich, filePath, 0); rich.SelectAll(); if (rich.SelectedText != "") { SetSelectedRtf(rich.SelectedRtf, "PasteFile"); } rich.Dispose(); } |
とするか・・・うーん。