前回はクリップボードの履歴から文字列をペーストするアプリケーションを作成しました。
履歴のなかにはいらないものもあるはずです。そこでいらないものを削除したり、よく使うものをメニューの上位に表示させるといった工夫をしてみることにします。
デザイナで以下のようなフォームを作ります。
まず履歴のなかからいらないものを削除する機能を追加します。[削除]をクリックするとチェックボックスにチェックがついたものを削除します。
GetCheckedItemIndexesメソッドはリストボックスのチェックがつけられている項目のインデックスのリストを返します。
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 |
public partial class Form1 : Form { private void ButtonRemove_Click(object sender, EventArgs e) { List<int> indexes = GetCheckedItemIndexes(); if(indexes.Count == 0) { MessageBox.Show("削除したい項目にチェックをいれてください", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } indexes = indexes.OrderByDescending(x => x).ToList(); foreach(int i in indexes) { CopiedStrings.RemoveAt(i); checkedListBox1.Items.RemoveAt(i); } } List<int> GetCheckedItemIndexes() { List<int> ret = new List<int>(); int count = checkedListBox1.Items.Count; for(int i = 0; i < count; i++) { if(checkedListBox1.GetItemChecked(i)) ret.Add(i); } return ret; } } |
[全部削除]をクリックするとすべての項目を削除します。
1 2 3 4 5 6 7 8 |
public partial class Form1 : Form { private void ButtonRemoveAll_Click(object sender, EventArgs e) { CopiedStrings.Clear(); checkedListBox1.Items.Clear(); } } |
[一番上に]をクリックするとチェックをいれた項目を一番上に移動させます。
GetMenuText(string str)メソッドはクリップボード内の文字列からメニューの項目として表示するための文字列を返します。
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 |
public partial class Form1 : Form { private void ButtonMoveFirst_Click(object sender, EventArgs e) { List<int> indexes = GetCheckedItemIndexes(); indexes = indexes.OrderByDescending(x => x).ToList(); List<string> vs = new List<string>(); foreach(int i in indexes) { vs.Add(CopiedStrings[i]); CopiedStrings.RemoveAt(i); checkedListBox1.Items.RemoveAt(i); } foreach(string str in vs) { CopiedStrings.Insert(0, str); checkedListBox1.Items.Insert(0, GetMenuText(str)); } } string GetMenuText(string str) { // 改行は文字列"[改行]"に変換 str = str.Replace("\r\n", "[改行]"); // タブ文字は 半角スペースに変換 str = str.Replace("\t", " "); // 連続するスペースは1つの半角スペースに変換 str = str.Replace(" ", " "); string old; do { old = str; str = str.Replace(" ", " "); } while(old != str); if(str.Length > 100) str = str.Substring(0, 100); return str; } } |
[内容確認]をクリックすると以下のような新しいフォームが表示され、クリップボードの履歴の文字列を確認することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public partial class Form1 : Form { private void ButtonShowText_Click(object sender, EventArgs e) { int index = checkedListBox1.SelectedIndex; if(index == -1) { MessageBox.Show("リストボックスの項目が選択されていません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } Form2 form2 = new Form2(CopiedStrings[index]); form2.Show(); } } |
それからリストボックスの項目をドラッグ&ドロップで移動できるようにしてみましょう。
コンストラクタ内で自作メソッド InitCheckedListBox()を呼び出してチェックボックス付きリストボックスの初期化に関する処理をおこないます。
まずドラッグ&ドロップを許可するとともにマウスが移動したときのイベントに対応できるようにします。
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 |
public partial class Form1 : Form { KeyboardHook keyboardHook = new KeyboardHook(); public Form1() { InitializeComponent(); AddClipboardFormatListener(Handle); keyboardHook.KeyDownEvent += KeyboardHook_KeyDownEvent; keyboardHook.Hook(); // チェックボックス付きリストボックスの初期化に関する処理 InitCheckedListBox(); } void InitCheckedListBox() { checkedListBox1.AllowDrop = true; checkedListBox1.MouseDown += CheckedListBox1_MouseDown; checkedListBox1.MouseUp += CheckedListBox1_MouseUp; checkedListBox1.MouseMove += CheckedListBox1_MouseMove; checkedListBox1.DragOver += CheckedListBox1_DragOver; checkedListBox1.DragDrop += CheckedListBox1_DragDrop; } } |
まずマウスボタンが押されているときにマウスが移動したら、それはドラッグの始まりです。ドラッグが開始されたらマウスポインタがある位置にある項目を取得します。そしてDoDragDropメソッドを呼び出します。
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 |
public partial class Form1 : Form { bool isMouseDown = true; private void CheckedListBox1_MouseDown(object sender, MouseEventArgs e) { isMouseDown = true; } private void CheckedListBox1_MouseUp(object sender, MouseEventArgs e) { isMouseDown = false; } private void CheckedListBox1_MouseMove(object sender, MouseEventArgs e) { if(isMouseDown) { isMouseDown = false; int index = checkedListBox1.IndexFromPoint(new Point(e.X, e.Y)); if(index == -1) return; DoDragDrop(index, DragDropEffects.All); } } } |
ドラッグされているときに他の項目の上にマウスがある場合は移動可能です。e.EffectをDragDropEffects.Moveに設定します。そうでないときは移動することはできないということなのでDragDropEffects.Noneを設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public partial class Form1 : Form { private void CheckedListBox1_DragOver(object sender, DragEventArgs e) { if(e.Data.GetDataPresent(typeof(int))) { int index = (int)e.Data.GetData(typeof(int)); { Point point = checkedListBox1.PointToClient(new Point(e.X, e.Y)); int targetIndex = checkedListBox1.IndexFromPoint(point); if(targetIndex == -1) { e.Effect = DragDropEffects.None; return; } if(targetIndex == index || targetIndex - 1 == index) e.Effect = DragDropEffects.None; else e.Effect = DragDropEffects.Move; } } } } |
ドロップされたら移動可能であれば移動させます。
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 |
public partial class Form1 : Form { private void CheckedListBox1_DragDrop(object sender, DragEventArgs e) { if(e.Data.GetDataPresent(typeof(int))) { int index = (int)e.Data.GetData(typeof(int)); { Point point = checkedListBox1.PointToClient(new Point(e.X, e.Y)); int targetIndex = checkedListBox1.IndexFromPoint(point); if(targetIndex == -1) return; if(targetIndex == index || targetIndex - 1 == index) return; else if(targetIndex > index) { string str = CopiedStrings[index]; CopiedStrings.RemoveAt(index); checkedListBox1.Items.RemoveAt(index); CopiedStrings.Insert(targetIndex - 1, str); checkedListBox1.Items.Insert(targetIndex - 1, GetMenuText(str)); } else { string str = CopiedStrings[index]; CopiedStrings.RemoveAt(index); checkedListBox1.Items.RemoveAt(index); CopiedStrings.Insert(targetIndex, str); checkedListBox1.Items.Insert(targetIndex, GetMenuText(str)); } } } } } |
最後にこのアプリは基本的に常駐させたいので使わないときはタスクトレイに表示させます。そこでNotifyIconを使います。
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 |
public partial class Form1 : Form { NotifyIcon NotifyIcon = new NotifyIcon(); public Form1() { InitializeComponent(); AddClipboardFormatListener(Handle); keyboardHook.KeyDownEvent += KeyboardHook_KeyDownEvent; keyboardHook.Hook(); InitNotifyIcon(); InitCheckedListBox(); } void InitNotifyIcon() { NotifyIcon.Icon = Properties.Resources.Icon1; NotifyIcon.Visible = true; NotifyIcon.Text = Application.ProductName + " Ver." + Application.ProductVersion; NotifyIcon.MouseDown += NotifyIcon_MouseDown; } private void NotifyIcon_MouseDown(object sender, MouseEventArgs e) { this.Visible = true; this.TopMost = true; this.TopMost = false; } } |
×ボタンをクリックしても終了しないでタスクトレイのなかで動き続けます。また本当に終了させたいときの処理も追加します。
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 |
public partial class Form1 : Form { protected override void OnFormClosing(FormClosingEventArgs e) { if(!isEnd) { this.Visible = false; e.Cancel = true; return; } keyboardHook.UnHook(); RemoveClipboardFormatListener(Handle); } private void EndMenuItem_Click(object sender, EventArgs e) { isEnd = true; Application.Exit(); } protected override void OnFormClosed(FormClosedEventArgs e) { NotifyIcon.Visible = false; base.OnFormClosed(e); } } |