このまえ複数のTreeViewの内容を同期するプログラムを作成しました。
このときは最後にUserControlのなかにTreeViewをいれて隠蔽するプログラムにしましたが、今回は最初から隠蔽してしまいます。
単にふたつのRichTextBoxの内容を同じにするのであれば
1 2 3 4 5 6 7 8 9 10 11 |
private void richTextBox1_TextChanged(object sender, EventArgs e) { if (richTextBox1.Rtf != richTextBox2.Rtf) richTextBox2.Rtf = richTextBox1.Rtf; } private void richTextBox2_TextChanged(object sender, EventArgs e) { if (richTextBox1.Rtf != richTextBox2.Rtf) richTextBox1.Rtf = richTextBox2.Rtf; } |
ところがこれではUndoの処理がうまくできません。アンドゥバッファを共有することができればいいのですが、そのような方法はないみたいです。そこで自分でアンドゥバッファをつくります。
internal class RichTextBoxEx : RichTextBox
ユーザーコントロールを作成して名前はSyncRichTextBoxにします。そのなかにRichTextBoxExを貼り付けます。
そしてSyncRichTextBoxのなかにフィールド変数を作成してこれが同じコントロールの内容が同期されるようにします。
RichDataクラスの内容はこんな感じ。アンドゥバッファの操作や同期対象のコントロールを取得するメソッドで構成されています。
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 |
public class RichData { List<Undobuf> _undobufs = new List<Undobuf>(); List<Undobuf> _redobufs = new List<Undobuf>(); public string Text { set; get; } public string Rtf { set; get; } public long CreateTime { get; set; } public long SaveTime { get; set; } public RichData() { CreateTime = DateTime.Now.Ticks; SaveTime = DateTime.Now.Ticks; } internal void InsertUndobuf(Undobuf buf) { _undobufs.Insert(0, buf); _redobufs.Clear(); } internal void ClearUndobuf(Undobuf buf) { _undobufs.Clear(); _redobufs.Clear(); } internal bool CanUndo() { return _undobufs.Count()>0; } internal bool CanRedo() { return _redobufs.Count() > 0; } internal Undobuf GetUndobuf() { if (CanUndo()) return _undobufs[0]; else return null; } internal Undobuf GetRedobuf() { if (CanRedo()) return _redobufs[0]; else return null; } internal void MoveToUndobufs() { Undobuf buf = _redobufs[0]; _redobufs.RemoveAt(0); _undobufs.Insert(0, buf); } internal void MoveToRedobufs() { Undobuf buf = _undobufs[0]; _undobufs.RemoveAt(0); _redobufs.Insert(0, buf); } internal void SetSyncRichTextBox(SyncRichTextBox rich) { if (!_richTextBoxInfos.Any(x => x.SyncRichTextBox == rich)) { _richTextBoxInfos.Add(new RichTextBoxInfo(rich)); } var info = _richTextBoxInfos.First(x => x.SyncRichTextBox == rich); { info.RichTextBoxEx.SelectionStart = info.SelectionStart; } } internal List<SyncRichTextBox> SyncRichTextBoxes { get { _richTextBoxInfos = _richTextBoxInfos.Where(x => !x.RichTextBoxEx.IsDisposed).ToList(); return _richTextBoxInfos.Select(x=> x.SyncRichTextBox).ToList(); } } internal List<RichTextBoxEx> RichTextBoxExes { get { _richTextBoxInfos = _richTextBoxInfos.Where(x => !x.RichTextBoxEx.IsDisposed).ToList(); return _richTextBoxInfos.Select(x => x.RichTextBoxEx).ToList(); } } internal RichTextBoxInfo GetRichTextBoxInfo(SyncRichTextBox rich) { var ret = _richTextBoxInfos.FirstOrDefault(x => x.SyncRichTextBox == rich); return ret; } } |
RichTextBoxInfoは内容が同期されるリッチテキストボックスに関する情報を格納したクラスです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
internal class RichTextBoxInfo { internal RichTextBoxInfo(SyncRichTextBox rich) { SyncRichTextBox = rich; RichTextBoxEx = rich.richTextBoxEx1; SelectionStart = 0; } internal int SelectionStart { get; set; } = 0; internal SyncRichTextBox SyncRichTextBox { get; } internal RichTextBoxEx RichTextBoxEx { get; } } |
アンドゥバッファのクラスです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class Undobuf { internal string action = ""; internal int removeStart = 0; internal int removeLength = 0; internal int insertStart = 0; internal int insertLength = 0; internal string removeText = ""; internal string removeRtf = ""; internal string insertText = ""; internal string insertRtf = ""; internal int oldSelectionStart = 0; internal int oldSelectionLength = 0; internal int newSelectionStart = 0; internal int newSelectionLength = 0; } |
RichDataの値はプログラムが実行されている最中に変更されることがあります。そこでその場合は古いDataにこれまでの編集データを格納するようにしています。また新しく設定されるDataに紐付けされた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 |
public partial class SyncRichTextBox : UserControl { public RichData _data = null; public RichData Data { get { return _data; } set { if (_data == value) return; if (_data != null) { if (richTextBoxEx1.Modified) _data.SaveTime = DateTime.Now.Ticks; _data.Rtf = richTextBoxEx1.Rtf; _data.Text = richTextBoxEx1.Text; richTextBoxEx1.Modified = false; } if (value != null) { var richs = value.SyncRichTextBoxes.Where(x => x.Data == value).ToList(); if (richs.Count != 0) { if (richs[0].Modified) { value.Rtf = richs[0].richTextBoxEx1.Rtf; value.Text = richs[0].richTextBoxEx1.Text; value.SaveTime = DateTime.Now.Ticks; } foreach (var rich in richs) rich.richTextBoxEx1.Modified = false; } } _data = value; if (value != null) { richTextBoxEx1.Rtf = value.Rtf; richTextBoxEx1.Modified = false; _data.SetSyncRichTextBox(this); } } } public void SaveToMemory() { if (!Modified) return; Data.Rtf = this.richTextBoxEx1.Rtf; Data.Text = this.richTextBoxEx1.Text; foreach (var rich in Data.SyncRichTextBoxes) { rich.Modified = false; } } public void LoadFromMemory() { this.Data = Data; } public void SaveToFile(string filePath) { Data.Rtf = this.richTextBoxEx1.Rtf; Data.Text = this.richTextBoxEx1.Text; this.richTextBoxEx1.SaveFile(filePath); } public void LoadFromFile(string filePath) { RichTextBox r = new RichTextBox(); r.LoadFile(filePath); RichData data = new RichData(); data.Rtf = r.Rtf; data.Text = r.Text; this.Data = data; } public bool Modified { get { return richTextBoxEx1.Modified; } set { richTextBoxEx1.Modified = value; } } } |
それからRichTextBoxExのイベントはSyncRichTextBoxで処理をすることになるので以下を追加。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public partial class SyncRichTextBox : UserControl { public SyncRichTextBox() { InitializeComponent(); richTextBoxEx1.KeyPress += (sender1, e1) => OnKeyPress(e1); richTextBoxEx1.KeyDown += (sender1, e1) => OnKeyDown(e1); richTextBoxEx1.TextChanged += (sender1, e1) => OnTextChanged(e1); richTextBoxEx1.MouseDown += (sender1, e1) => this.OnMouseDown(e1); richTextBoxEx1.MouseUp += (sender1, e1) => this.OnMouseUp(e1); richTextBoxEx1.DragOver += (sender1, e1) => this.OnDragOver(e1); richTextBoxEx1.DragDrop += (sender1, e1) => this.OnDragDrop(e1); richTextBoxEx1.DragLeave += (sender1, e1) => this.OnDragLeave(e1); richTextBoxEx1.Dock = DockStyle.Fill; _data = new RichData(); this.Data = _data; } } |
今回は準備作業で終わってしまいました。次回から本格的に始めます。