自作フォトビューアーに登録したファイルにコメントをつけることができるようにします。
まずDataクラスのなかにコメントを格納するフィールド変数をつくります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Data { public Data(){} public Data(string filePath, bool isChecked) { FilePath = filePath; IsChecked = isChecked; } public string FilePath = ""; public bool IsChecked = false; // コメントを保存用のフィールド変数を追加 public string Comment = ""; } |
それからウィンドウのサイズが変更されてもテキストボックスをうまく表示されるようにtextBox1のAnchorプロパティを設定します。またツリービューコントロールでBeforeSelectイベントを処理する必要があるのでイベントハンドラTreeView1_BeforeSelectを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); // コンストラクタに以下を追加 // それ以外は前回と同じ textBox1.Anchor = AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right; } void InitTreeView() { // これを追加。それ以外は前回と同じ treeView1.BeforeSelect += TreeView1_BeforeSelect; treeView1.AfterCheck += TreeView1_AfterCheck; } } |
これまではファイルパスがあれば画像を表示させることが可能でした。ファイル名はTreeNode.Textをそのまま使っていました。そしてXMLファイルに保存するときだけDataオブジェクトを生成して、これをシリアル化していました。これからはDataオブジェクトをTreeNode.Tagプロパティにセットする方法に変更します。
これに伴い変更する必要があるのは・・・
ツリービューコントロールにファイルがドロップされて新しいTreeNodeが追加されるときの処理
private void TreeView1_DragDrop(object sender, DragEventArgs e)
選択されているTreeNodeが変化した後の処理
private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e)
ファイルを保存するときの処理
void SaveFile(string filePath)
ファイルを開くときの処理
void OpenFile(string filePath)
です(実はもうひとつあった)。
それから新しく定義しないといけないイベントハンドラは
選択されているTreeNodeのチェックボックスの状態が変化した後の処理
private void TreeView1_AfterCheck(object sender, TreeViewEventArgs e)
選択されているTreeNodeが変化する前の処理
private void TreeView1_BeforeSelect(object sender, TreeViewCancelEventArgs e)
です。
まずファイルをドラッグアンドドロップしたときにTreeNodeが追加されますが、このときの処理を変更しました。新しいTreeNodeを追加したらそのときにDataオブジェクトを作成してTreeNode.Tagにセットしてしまいます。
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 |
public partial class Form1 : Form { private void TreeView1_DragDrop(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); Point point = treeView1.PointToClient(new Point(e.X, e.Y)); if (treeView1.SelectedNode == null) { files = files.OrderBy(x => x).ToArray(); treeView1.BeginUpdate(); foreach (var path in files) { if (IsImageFile(path)) { //treeView1.Nodes.Add(path); // やめる TreeNode node = new TreeNode(); node.Text = path; node.Tag = new Data(path, false); treeView1.Nodes.Add(node); } } treeView1.EndUpdate(); } else { int index = treeView1.Nodes.IndexOf(treeView1.SelectedNode); files = files.OrderByDescending(x => x).ToArray(); treeView1.BeginUpdate(); foreach (var path in files) { if (IsImageFile(path)) { // treeView1.Nodes.Insert(index + 1, path); // やめる TreeNode node = new TreeNode(); node.Text = path; node.Tag = new Data(path, false); treeView1.Nodes.Insert(index + 1, node); } } treeView1.EndUpdate(); } } if (e.Data.GetDataPresent(typeof(TreeNode))) { Point point = treeView1.PointToClient(new Point(e.X, e.Y)); TreeNode targetNode = treeView1.GetNodeAt(point); int targetIndex = treeView1.Nodes.IndexOf(targetNode); TreeNode sourceNode = (TreeNode)e.Data.GetData(typeof(TreeNode)); treeView1.BeginUpdate(); treeView1.Nodes.Remove(sourceNode); treeView1.Nodes.Insert(targetIndex, sourceNode); treeView1.SelectedNode = sourceNode; treeView1.EndUpdate(); } } } |
それからTreeNodeのチェックボックスの状態が変化した場合、すぐにData.IsCheckedを変更させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class Form1 : Form { // TreeNodeのチェックボックスがOnOffされたらそれをData.IsCheckedを変更する private void TreeView1_AfterCheck(object sender, TreeViewEventArgs e) { if (e.Node == null) return; TreeNode node = e.Node; Data data = (Data)node.Tag; if (node.Checked) data.IsChecked = true; else data.IsChecked = false; } } |
ファイルを開く、保存するときの動作も若干変更になります。
ファイルを開くときはDataオブジェクトからTreeNodeを生成し、このDataオブジェクトをTreeNode.Tagにセットしてしまいます。保存するときはTreeNode.TagからDataオブジェクトを取得することができるので、これをそのままシリアル化します。
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 |
public partial class Form1 : Form { void OpenFile(string filePath) { if (!File.Exists(filePath)) return; XmlSerializer xml = new XmlSerializer(typeof(Doc)); StreamReader sr = new StreamReader(filePath); Doc doc = (Doc)xml.Deserialize(sr); sr.Close(); treeView1.BeginUpdate(); treeView1.Nodes.Clear(); foreach (Data data in doc.Datas) { // ここでDataオブジェクトからTreeNodeを生成してtreeView1.Nodesに追加する TreeNode node = new TreeNode(); node.Tag = data; node.Text = data.FilePath; node.Checked = data.IsChecked; treeView1.Nodes.Add(node); } treeView1.EndUpdate(); // ファイルを読み込んだら一番上のTreeNodeを選択する // TreeNodeが存在しない場合は何も表示しない。(前のファイルが表示していた内容を消す) if (treeView1.Nodes.Count > 0) treeView1.SelectedNode = treeView1.Nodes[0]; else { treeView1.SelectedNode = null; pictureBox1.Image = null; textBox1.Text = null; } } void SaveFile(string filePath) { List<Data> datas = new List<Data>(); foreach (TreeNode node in treeView1.Nodes) { //datas.Add(new Data(node.Text, node.Checked)); // やめる datas.Add((Data)node.Tag); } Doc doc = new Doc(); doc.Datas = datas; XmlSerializer xml = new XmlSerializer(typeof(Doc)); StreamWriter sw = new StreamWriter(filePath); xml.Serialize(sw, doc); sw.Close(); } } |
TreeNodeが選択されたらこれまで選択されていたTreeNodeに相当するDataオブジェクトにコメントを格納し、新たに選択されたTreeNodeに相当するDataオブジェクトからコメントを取得してテキストボックスに表示させます。
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 |
public partial class Form1 : Form { private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e) { if (e.Node == null) { if (pictureBox1.Image != null) pictureBox1.Image.Dispose(); pictureBox1.Image = null; labelFilePath.Text = "未選択"; return; } Data data = (Data)e.Node.Tag; textBox1.Text = data.Comment; string path = data.FilePath; if (!IsImageFile(path)) { if (pictureBox1.Image != null) pictureBox1.Image.Dispose(); pictureBox1.Image = null; labelFilePath.Text = path + " は存在しないか画像ファイルではありません"; return; } Image image = Image.FromFile(path); Bitmap bitmap = new Bitmap(image); image.Dispose(); bool b1 = pictureBox1.Size.Width > bitmap.Width; bool b2 = pictureBox1.Size.Height > bitmap.Height; if (b1 && b2) pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage; else pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; if (pictureBox1.Image != null) pictureBox1.Image.Dispose(); pictureBox1.Image = bitmap; labelFilePath.Text = path; } private void TreeView1_BeforeSelect(object sender, TreeViewCancelEventArgs e) { if (treeView1.SelectedNode == null) return; Data data = (Data)treeView1.SelectedNode.Tag; data.Comment = textBox1.Text; } } |
これで画像にコメントをつけることができました。
それからもうひとつ変更する場所がありました。サムネイルを表示させるダイアログから戻ってきたときにTreeViewの再構築がおこなわれますが、ここでもTreeNode.TagにDataオブジェクトをセットすることをわすれてはいけません。
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 |
public partial class Form1 : Form { private void MenuItemThumbnail_Click(object sender, EventArgs e) { // コメントを保存する TreeNode oldNode = treeView1.SelectedNode; Data oldData = null; if (oldNode != null) { Data data = (Data)oldNode.Tag; oldData = data; data.Comment = textBox1.Text; treeView1.SelectedNode = null; } List<Data> datas = new List<Data>(); foreach (TreeNode node in treeView1.Nodes) datas.Add((Data)node.Tag); // 変更箇所 FormThumbnail form2 = new FormThumbnail(); form2.Datas = datas; form2.ShowDialog(); treeView1.BeginUpdate(); treeView1.Nodes.Clear(); TreeNode newNode = null; foreach (Data data in form2.Datas) { TreeNode node = new TreeNode(); node.Text = data.FilePath; node.Checked = data.IsChecked; node.Tag = data; // 変更箇所 treeView1.Nodes.Add(node); // oldDataと同じDataを持つTreeNodeはあるか? if (oldData != null && oldData == data) newNode = node; } treeView1.EndUpdate(); // 最初に選択されていたノードに相当するものを選択する treeView1.SelectedNode = newNode; } } |
それからサムネイルを表示しているときもコメントを編集できるようにしたいものです。そこでFormThumbnailクラスを修正します。
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 |
public partial class FormThumbnail : Form { protected override void OnLoad(EventArgs e) { int left = 0; int top = 0; numericUpDown1.Value = 100; foreach (Data data in Datas) { UserControlEx controlEx = new UserControlEx(); controlEx.WidthEx = 100; controlEx.Location = new Point(left, top); controlEx.SetImage(data.FilePath); controlEx.SetChecked(data.IsChecked); controlEx.Tag = data; // これを追加 left += controlEx.WidthEx + 10; if (panel1.Width < left + controlEx.Size.Width) { left = 0; top += controlEx.Size.Height + 10; } controlEx.Parent = panel1; userControlIces.Add(controlEx); controlEx.AllowDrop = true; controlEx.MouseDownEx += ControlEx_MouseDownEx; ; controlEx.DragOver += ControlEx_DragOver; controlEx.DragDrop += ControlEx_DragDrop; controlEx.MouseMoveEx += ControlEx_MouseMoveEx; } base.OnLoad(e); } private void FormThumbnail_FormClosed(object sender, FormClosedEventArgs e) { Datas.Clear(); foreach (UserControlEx ctrl in userControlIces) { //Datas.Add(new Data(ctrl.GetPath(), ctrl.IsChecked())); // やめる Data data = (Data)ctrl.Tag; data.IsChecked = ctrl.IsChecked(); Datas.Add(data); } } } |
左クリックされたら順番を入れ替えるためのドラッグの開始とみなします。そして右クリックならダイアログを表示してコメントを編集できるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class FormThumbnail : Form { private void ControlEx_MouseDownEx(UserControlEx sender, EventArgs e) { if(Control.MouseButtons == MouseButtons.Left) DoDragDrop(sender, DragDropEffects.Move); if (Control.MouseButtons == MouseButtons.Right) { // コメント編集用のダイアログを表示 Data data = (Data)sender.Tag; FormComment form = new FormComment(); form.Comment = data.Comment; form.FilePath = data.FilePath; // ダイアログでOKボタンが押されたら変更を反映させる if (form.ShowDialog() == DialogResult.OK) { data.Comment = form.Comment; } form.Dispose(); } } } |
これはコメント編集用のダイアログです。
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 FormComment : Form { public string Comment = ""; public string FilePath = ""; public FormComment() { InitializeComponent(); button1.DialogResult = DialogResult.OK; button1.Click += Button1_Click; } private void FormComment_Load(object sender, EventArgs e) { textBox1.Text = Comment; label1.Text = FilePath + " のコメントを編集しています"; } private void Button1_Click(object sender, EventArgs e) { Comment = textBox1.Text; } } |
これで画像にコメントを残すことができました。次回はコメントのなかのキーワードを検索してその結果を表示できるように改良することにします。