メニューの項目[ファイル」の一番下にこれまで開いたファイルのリストを表示させます。またこれをクリックしたらファイルを開くプログラムにします。
まずメニューを動的に追加するには以下のようにします。
1 2 3 4 5 6 7 8 |
void AddFileHistory(string filePath) { ToolStripMenuItem item = new ToolStripMenuItem(); // 追加するアイテムをつくる this.fileToolStripMenuItem.DropDownItems.Add(item); // 作成したアイテムを追加する item.Click += Item_Click; // 追加したアイテムがクリックされたらItem_Clickが呼ばれる。 item.Text = filePath; // 追加されたアイテムに表示するテキスト item.Tag = filePath; // 追加されたアイテムに持たせるデータ } |
問題のItem_Clickメソッドが呼ばれたらどのような処理をすればいいのでしょうか? 引数のsenderを調べれば、どのメニューアイテムがクリックされたかわかります。そしてToolStripMenuItem.Tagを調べればどのアイテムがクリックされたのかがわかります。
1 2 3 4 5 6 7 |
private void Item_Click(object sender, EventArgs e) { ToolStripMenuItem item = (ToolStripMenuItem)sender; string filePath = (string)item.Tag; // 開くべきfilePathは確定した } |
このようにすることでクリックされたアイテムからファイルを開けばいいかわかります。
OpenFile(string filePath)を呼び出せば、ファイルを開くことができます。
なんらかのファイルが開かれたり保存されたら、それを上記の方法で履歴に保存する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void OpenFile(string filePath) { // 正常に処理が終了 AddFileHistory(filePath); } SaveFile() { // 正常に処理が終了 MessageBox.Show("ファイルを保存しました。\n" + curFilePath); AddFileHistory(curFilePath); } |
ところで同じファイルが履歴に複数表示されないようにする必要があります。そこで、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
List<string> GetFileHistry() { List<string> vs = new List<string>(); foreach (var item0 in fileToolStripMenuItem.DropDownItems) { if (item0.GetType() != typeof(ToolStripMenuItem)) continue; ToolStripMenuItem menuItem = (ToolStripMenuItem)item0; string filePath = (string)menuItem.Tag; if (filePath != null && filePath != "") vs.Add(filePath); } return vs; } |
これは保存されているファイルパスのリストを返します。これをつかってすでに格納されているファイルパスを調べて、すでにあるのであれば登録しないようにすればいいですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void AddFileHistory(string filePath) { List<string> filePaths = GetFileHistry(); if(filePaths.Any(x => x == filePath)) return; ToolStripMenuItem item = new ToolStripMenuItem(); item.Tag = filePath; item.Text = filePath; this.fileToolStripMenuItem.DropDownItems.Add(item); item.Click += Item_Click; SaveFileHistry(); } |
ところで二重起動を禁止するプログラムを作りました。これとの整合性も考える必要があります。
以下のように変更します。
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 |
void SaveAsFile() { if (syncTreeViewEx1.IsEmpty) return; SaveToMoromy(); Doc doc = new Doc(); doc.treeNodeExes = syncTreeViewEx1.GetTreeNodeExs(null); XmlSerializer xml = new XmlSerializer(typeof(Doc), types.ToArray()); SaveFileDialog save = new SaveFileDialog(); save.Filter = "trtファイル|*.trt"; if (save.ShowDialog() == DialogResult.OK) { StreamWriter sw = new StreamWriter(save.FileName); xml.Serialize(sw, doc); sw.Close(); curFilePath = save.FileName; if (Program.mutex != null) { Program.mutex.ReleaseMutex(); Program.mutex.Close(); } System.Threading.Mutex mutex; Program.IsDoublestarts(save.FileName, out mutex); AddFileHistory(save.FileName); } } |
さてファイル履歴を保存してもファイルが削除されることがあります。削除されたファイルは開くことはできないので履歴に表示する意味はないと考えられます。
それで以下のメソッドをつかって取り除きます。
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 { private void fileToolStripMenuItem_DropDownOpening(object sender, EventArgs e) { RemoveNotFileItem(); } } void RemoveNotFileItem() { List<ToolStripMenuItem> removeItems = new List<ToolStripMenuItem>(); foreach (object menuItem in this.fileToolStripMenuItem.DropDownItems) { try { ToolStripMenuItem item = (ToolStripMenuItem)menuItem; string filePath = (string)item.Tag; if (filePath != null && filePath != "") { if (! File.Exists(filePath)) { removeItems.Add(item); } } } catch { } } foreach (ToolStripMenuItem menuItem in removeItems) fileToolStripMenuItem.DropDownItems.Remove(menuItem); } |
このメソッドはファイル履歴が表示される直前に呼ばれます。
これでファイルの履歴を保存することができます。しかし、これでは不十分です。アプリを終了して再起動したとき、履歴が表示されないのであればファイル履歴を保存する意味はあまりありません。そこでアプリの終了時にこれを保存する方法を考えます。
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 |
void SaveFileHistry() { List<ToolStripMenuItem> fileHistry = new List<ToolStripMenuItem>(); foreach (object menuItem in this.fileToolStripMenuItem.DropDownItems) { try { ToolStripMenuItem item = (ToolStripMenuItem)menuItem; string filePath = (string)item.Tag; if (filePath != null && filePath != "") { if (File.Exists(filePath)) fileHistry.Add(item); } } catch { } } List<string> vs = new List<string>(); foreach (var fileHistry0 in fileHistry) { vs.Add((string)fileHistry0.Tag); } string path = Application.StartupPath+ "\\FileHistory.comfig"; XmlSerializer xml = new XmlSerializer(typeof(List<string>)); StreamWriter sw = new StreamWriter(path); xml.Serialize(sw, vs); } |
SaveFileHistry()はファイル履歴に変更が加えられたとき、AddFileHistoryが呼ばれたときに行なうことにします。またSaveFileHistry()で保存されたファイルを読み出してファイル履歴を復活させるLoadFileHistryメソッドはアプリが開始されるときにおこないます。
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 |
void AddFileHistory(string filePath) { List<string> filePaths = GetFileHistry(); if(filePaths.Any(x => x == filePath)) return; ToolStripMenuItem item = new ToolStripMenuItem(); item.Tag = filePath; item.Text = filePath; this.fileToolStripMenuItem.DropDownItems.Add(item); item.Click += Item_Click; SaveFileHistry(); } public partial class Form1 : Form { private void Form1_Load(object sender, EventArgs e) { LoadFileHistry(); } } void LoadFileHistry() { if (!File.Exists(Application.StartupPath + "\\FileHistory.comfig")) return; string path = Application.StartupPath + "\\FileHistory.comfig"; XmlSerializer xml = new XmlSerializer(typeof(List<string>)); StreamReader sr = new StreamReader(path); List<string> filePaths =(List<string>)xml.Deserialize(sr); sr.Close(); filePaths = filePaths.Distinct().ToList(); foreach (string path1 in filePaths) AddFileHistory(path1); } |