在日常使用电脑的过程中,经常需要重复打开相同的文件。为了避免每次都要浏览并重新打开相同的文件,设计了一个名为MRUManager的类,以简化这一过程。
MRUManager使用Windows注册表来存储最近打开的文件路径。如果对注册表不熟悉,可以查看Wikipedia的相关介绍,或者参考Microsoft的文档来了解C#类Microsoft.Win32.Registry的使用方法。
可以立即使用MRUManager类,当然,需要自己承担风险。使用之前,需要满足一些基本要求。
在Visual Studio中,创建一个ToolStripMenuItem,作为最近文件列表的父菜单项。不要在这个菜单项中放置子菜单项,因为MRUManager会移除它们。
创建一个方法,其原型如下:
void myOwnRecentFileGotClicked_handler(object obj, EventArgs evt)
当用户点击最近文件列表中的一个项目时,这个方法将被调用。
创建MRUManager类的实例:
private MRUManager mruManager;
private void Form1_Load(object sender, EventArgs e)
{
this.mruManager = new MRUManager(
// 菜单项,将包含最近文件
this.recentFilesToolStripMenuItem,
// 程序名称
"myProgram",
// 当最近文件被点击时调用的函数
this.myOwn_recentFileGotClicked_handler,
// 用户清除最近文件列表时调用的可选函数
this.myOwn_recentFilesGotCleared_handler);
}
之后,可以调用两个公共方法:
public void AddRecentFile(string fileNameWithFullPath)
public void RemoveRecentFile(string fileNameWithFullPath)
使用示例:
private void openToolStripMenuItem_Click(object obj, EventArgs evt)
{
FileDialog openFileDlg = new OpenFileDialog();
openFileDlg.InitialDirectory = Environment.CurrentDirectory;
if (openFileDlg.ShowDialog() != DialogResult.OK) return;
string openedFile = openFileDlg.FileName;
// 现在将其交给MRUManager
this.mruManager.AddRecentFile(openedFile);
// 在这里处理文件
MessageBox.Show("通过'打开'菜单项,打开了: " + openedFile);
}
如果用户打开(或保存)文件,当用户点击最近文件,但该文件不存在时,MRUManager会进行相应的处理。
以下是类的概览:
public class MRUManager
{
private string NameOfProgram;
private string SubKeyName;
private ToolStripMenuItem ParentMenuItem;
private Action
类中有两个私有方法:
_refreshRecentFilesMenu()
和 _onClearRecentFiles_Click()
。
当创建新的MRUManager对象时,构造函数会检查无效参数。如果有,它会抛出一个新的ArgumentException。然后调用_refreshRecentFilesMenu()来更新列表,以防之前在注册表中存储了任何条目。
类在注册表下存储最近文件的键是"HKEY_CURRENT_USER\SOFTWARE\{提供的程序名称}\MRU"。它将这个字符串存储在私有成员SubKeyName中。
每当调用AddRecentFile()时,它在该键下创建一个新的值。值的名称是数字,从0开始,一直到添加的数量。然后调用_refreshRecentFilesMenu()。
每当调用RemoveRecentFile()时,它在SubKeyName下搜索包含传递的文件名的值,并将其删除。然后调用_refreshRecentFilesMenu()。
_refreshRecentFilesMenu()调用{ToolStripMenuItem提供的}.DropDownItems.Clear(),然后使用注册表中的所有值重新填充它。它添加的每个最近文件菜单项都会传递一个指向提供的函数的EventHandler。然后它添加两个项目:一个分隔符和'清除列表'菜单项,当点击时,会运行私有方法_onClearRecentFiles_Click()。
_onClearRecentFiles_Click()执行三个操作:清除注册表中的最近文件,清除菜单项,并调用用户可能可选指定的函数。
以下是_refreshRecentFilesMenu()和_onClearRecentFiles_Click()的简化版本:
private void _refreshRecentFilesMenu()
{
string s;
ToolStripItem tSI;
RegistryKey rK = Registry.CurrentUser.OpenSubKey(this.SubKeyName, false);
this.ParentMenuItem.DropDownItems.Clear();
string[] valueNames = rK.GetValueNames();
foreach (string valueName in valueNames)
{
s = rK.GetValue(valueName, null) as string;
if (s == null) continue;
tSI = this.ParentMenuItem.DropDownItems.Add(s);
tSI.Click += new EventHandler(this.OnRecentFileClick);
}
if (this.ParentMenuItem.DropDownItems.Count == 0)
{
this.ParentMenuItem.Enabled = false;
return;
}
this.ParentMenuItem.DropDownItems.Add("-");
tSI = this.ParentMenuItem.DropDownItems.Add("Clear list");
tSI.Click += new EventHandler(this._onClearRecentFiles_Click);
this.ParentMenuItem.Enabled = true;
}
private void _onClearRecentFiles_Click_SIMPLIFIED(object obj, EventArgs evt)
{
RegistryKey rK = Registry.CurrentUser.OpenSubKey(this.SubKeyName, true);
if (rK == null) return;
string[] values = rK.GetValueNames();
foreach (string valueName in values)
rK.DeleteValue(valueName, true);
rK.Close();
this.ParentMenuItem.DropDownItems.Clear();
this.ParentMenuItem.Enabled = false;
if (OnClearRecentFilesClick != null)
this.OnClearRecentFilesClick(obj, evt);
}
尽管本文中的MRUManager类是从头开始编写的,但它与原文的实现相似。例如,它仍然使用注册表来存储文件路径,并且它创建的GUI界面与原文非常相似。决定让MRUManager更加简洁,不包括像'maxNumberOfFiles'或'maxDisplayLength'这样的东西,但仍然足够功能强大,可以立即使用。