MruManager.cs
上传用户:sxsgcs
上传日期:2013-10-21
资源大小:110k
文件大小:16k
源码类别:

CAD

开发平台:

C#

  1. #region Using directives
  2. using System;
  3. using System.Windows.Forms;
  4. using System.Diagnostics;
  5. using System.Collections.Generic;
  6. using Microsoft.Win32;
  7. using System.IO;
  8. using System.Text;
  9. using System.Runtime.InteropServices;
  10. using System.Globalization;
  11. using System.Security;
  12. #endregion
  13. namespace DocToolkit
  14. {
  15.     using StringList = List<String>;
  16.     using StringEnumerator = IEnumerator<String>;
  17.     /// <summary>
  18.     /// MRU manager - manages Most Recently Used Files list
  19.     /// for Windows Form application.
  20.     /// </summary>
  21.     public class MruManager
  22.     {
  23.         #region Members
  24.         // Event raised when user selects file from MRU list
  25.         public event MruFileOpenEventHandler MruOpenEvent;
  26.         private Form ownerForm;                 // owner form
  27.         private ToolStripMenuItem menuItemMRU;  // Recent Files menu item
  28.         private ToolStripMenuItem menuItemParent;        // Recent Files menu item parent
  29.         private string registryPath;            // Registry path to keep MRU list
  30.         private int maxNumberOfFiles = 10;      // maximum number of files in MRU list
  31.         private int maxDisplayLength = 40;      // maximum length of file name for display
  32.         private string currentDirectory;        // current directory
  33.         private StringList mruList;              // MRU list (file names)
  34.         private const string regEntryName = "file";  // entry name to keep MRU (file0, file1...)
  35.         #endregion
  36.         #region Windows API
  37.         [DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
  38.         private static extern bool PathCompactPathEx(
  39.             StringBuilder pszOut,
  40.             string pszPath,
  41.             int cchMax,
  42.             int reserved);
  43.         #endregion
  44.         #region Constructor
  45.         public MruManager()
  46.         {
  47.             mruList = new StringList();
  48.         }
  49.         #endregion
  50.         #region Public Properties
  51.         /// <summary>
  52.         /// Maximum length of displayed file name in menu (default is 40).
  53.         /// 
  54.         /// Set this property to change default value (optional).
  55.         /// </summary>
  56.         public int MaxDisplayNameLength
  57.         {
  58.             set
  59.             {
  60.                 maxDisplayLength = value;
  61.                 if (maxDisplayLength < 10)
  62.                     maxDisplayLength = 10;
  63.             }
  64.             get
  65.             {
  66.                 return maxDisplayLength;
  67.             }
  68.         }
  69.         /// <summary>
  70.         /// Maximum length of MRU list (default is 10).
  71.         /// 
  72.         /// Set this property to change default value (optional).
  73.         /// </summary>
  74.         public int MaxMruLength
  75.         {
  76.             set
  77.             {
  78.                 maxNumberOfFiles = value;
  79.                 if (maxNumberOfFiles < 1)
  80.                     maxNumberOfFiles = 1;
  81.                 if (mruList.Count > maxNumberOfFiles)
  82.                     mruList.RemoveRange(maxNumberOfFiles - 1, mruList.Count - maxNumberOfFiles);
  83.             }
  84.             get
  85.             {
  86.                 return maxNumberOfFiles;
  87.             }
  88.         }
  89.         /// <summary>
  90.         /// Set current directory.
  91.         /// 
  92.         /// Default value is program current directory which is set when
  93.         /// Initialize function is called.
  94.         /// 
  95.         /// Set this property to change default value (optional)
  96.         /// after call to Initialize.
  97.         /// </summary>
  98.         public string CurrentDir
  99.         {
  100.             set
  101.             {
  102.                 currentDirectory = value;
  103.             }
  104.             get
  105.             {
  106.                 return currentDirectory;
  107.             }
  108.         }
  109.         #endregion
  110.         #region Public Functions
  111.         /// <summary>
  112.         /// Initialization. Call this function in form Load handler.
  113.         /// </summary>
  114.         /// <param name="owner">Owner form</param>
  115.         /// <param name="mruItem">Recent Files menu item</param>
  116.         /// <param name="regPath">Registry Path to keep MRU list</param>
  117.         public void Initialize(Form owner, ToolStripMenuItem mruItem, ToolStripMenuItem mruItemParent, string regPath)
  118.         {
  119.             // keep reference to owner form
  120.             ownerForm = owner;
  121.             // keep reference to MRU menu item
  122.             menuItemMRU = mruItem;
  123.             // keep reference to MRU menu item parent
  124.             menuItemParent = mruItemParent;
  125.             // keep Registry path adding MRU key to it
  126.             registryPath = regPath;
  127.             if (registryPath.EndsWith("\"))
  128.                 registryPath += "MRU";
  129.             else
  130.                 registryPath += "\MRU";
  131.             // keep current directory in the time of initialization
  132.             currentDirectory = Directory.GetCurrentDirectory();
  133.             // subscribe to MRU parent Popup event
  134.             menuItemParent.DropDownOpening += new EventHandler(this.OnMRUParentPopup);
  135.             // subscribe to owner form Closing event
  136.             ownerForm.Closing += OnOwnerClosing;
  137.             // load MRU list from Registry
  138.             LoadMRU();
  139.         }
  140.         /// <summary>
  141.         /// Add file name to MRU list.
  142.         /// Call this function when file is opened successfully.
  143.         /// If file already exists in the list, it is moved to the first place.
  144.         /// </summary>
  145.         /// <param name="file">File Name</param>
  146.         public void Add(string file)
  147.         {
  148.             Remove(file);
  149.             // if array has maximum length, remove last element
  150.             if (mruList.Count == maxNumberOfFiles)
  151.                 mruList.RemoveAt(maxNumberOfFiles - 1);
  152.             // add new file name to the start of array
  153.             mruList.Insert(0, file);
  154.         }
  155.         /// <summary>
  156.         /// Remove file name from MRU list.
  157.         /// Call this function when File - Open operation failed.
  158.         /// </summary>
  159.         /// <param name="file">File Name</param>
  160.         public void Remove(string file)
  161.         {
  162.             int i = 0;
  163.             StringEnumerator myEnumerator = mruList.GetEnumerator();
  164.             while (myEnumerator.MoveNext())
  165.             {
  166.                 if ((string)myEnumerator.Current == file)
  167.                 {
  168.                     mruList.RemoveAt(i);
  169.                     return;
  170.                 }
  171.                 i++;
  172.             }
  173.         }
  174.         #endregion
  175.         #region Event Handlers
  176.         /// <summary>
  177.         /// Update MRU list when MRU menu item parent is opened
  178.         /// </summary>
  179.         /// <param name="sender"></param>
  180.         /// <param name="e"></param>
  181.         private void OnMRUParentPopup(object sender, EventArgs e)
  182.         {
  183.             // remove all childs
  184.             //if (menuItemMRU.IsParent)
  185.             //{
  186.             menuItemMRU.DropDownItems.Clear();
  187.             //}
  188.             // Disable menu item if MRU list is empty
  189.             if (mruList.Count == 0)
  190.             {
  191.                 menuItemMRU.Enabled = false;
  192.                 return;
  193.             }
  194.             // enable menu item and add child items
  195.             menuItemMRU.Enabled = true;
  196.             ToolStripMenuItem item;
  197.             StringEnumerator myEnumerator = mruList.GetEnumerator();
  198.             int i = 0;
  199.             while (myEnumerator.MoveNext())
  200.             {
  201.                 item = new ToolStripMenuItem();
  202.                 item.Text = GetDisplayName((string)myEnumerator.Current);
  203.                 item.Tag = i++;
  204.                 // subscribe to item's Click event
  205.                 item.Click += OnMRUClicked;
  206.                 menuItemMRU.DropDownItems.Add(item);
  207.             }
  208.         }
  209.         /// <summary>
  210.         /// MRU menu item is clicked - call owner's OpenMRUFile function
  211.         /// </summary>
  212.         /// <param name="sender"></param>
  213.         /// <param name="e"></param>
  214.         private void OnMRUClicked(object sender, EventArgs e)
  215.         {
  216.             string s;
  217.             // cast sender object to MenuItem
  218.             ToolStripMenuItem item = (ToolStripMenuItem)sender;
  219.             if (item != null)
  220.             {
  221.                 // Get file name from list using item index
  222.                 s = (string)mruList[(int)item.Tag];
  223.                 // Raise event to owner and pass file name.
  224.                 // Owner should handle this event and open file.
  225.                 if (s.Length > 0)
  226.                 {
  227.                     if (MruOpenEvent != null)
  228.                     {
  229.                         MruOpenEvent(this, new MruFileOpenEventArgs(s));
  230.                     }
  231.                 }
  232.             }
  233.         }
  234.         /// <summary>
  235.         /// Save MRU list in Registry when owner form is closing
  236.         /// </summary>
  237.         /// <param name="sender"></param>
  238.         /// <param name="e"></param>
  239.         private void OnOwnerClosing(object sender, System.ComponentModel.CancelEventArgs e)
  240.         {
  241.             int i, n;
  242.             try
  243.             {
  244.                 RegistryKey key = Registry.CurrentUser.CreateSubKey(registryPath);
  245.                 if (key != null)
  246.                 {
  247.                     n = mruList.Count;
  248.                     for (i = 0; i < maxNumberOfFiles; i++)
  249.                     {
  250.                         key.DeleteValue(regEntryName +
  251.                             i.ToString(CultureInfo.InvariantCulture), false);
  252.                     }
  253.                     for (i = 0; i < n; i++)
  254.                     {
  255.                         key.SetValue(regEntryName +
  256.                             i.ToString(CultureInfo.InvariantCulture), mruList[i]);
  257.                     }
  258.                 }
  259.             }
  260.             catch (ArgumentNullException ex) { HandleWriteError(ex); }
  261.             catch (SecurityException ex) { HandleWriteError(ex); }
  262.             catch (ArgumentException ex) { HandleWriteError(ex); }
  263.             catch (ObjectDisposedException ex) { HandleWriteError(ex); }
  264.             catch (UnauthorizedAccessException ex) { HandleWriteError(ex); }
  265.         }
  266.         #endregion
  267.         #region Private Functions
  268.         /// <summary>
  269.         /// Load MRU list from Registry.
  270.         /// Called from Initialize.
  271.         /// </summary>
  272.         private void LoadMRU()
  273.         {
  274.             string sKey, s;
  275.             try
  276.             {
  277.                 mruList.Clear();
  278.                 RegistryKey key = Registry.CurrentUser.OpenSubKey(registryPath);
  279.                 if (key != null)
  280.                 {
  281.                     for (int i = 0; i < maxNumberOfFiles; i++)
  282.                     {
  283.                         sKey = regEntryName + i.ToString(CultureInfo.InvariantCulture);
  284.                         s = (string)key.GetValue(sKey, "");
  285.                         if (s.Length == 0)
  286.                             break;
  287.                         mruList.Add(s);
  288.                     }
  289.                 }
  290.             }
  291.             catch (ArgumentNullException ex) { HandleReadError(ex); }
  292.             catch (SecurityException ex) { HandleReadError(ex); }
  293.             catch (ArgumentException ex) { HandleReadError(ex); }
  294.             catch (ObjectDisposedException ex) { HandleReadError(ex); }
  295.             catch (UnauthorizedAccessException ex) { HandleReadError(ex); }
  296.         }
  297.         /// <summary>
  298.         /// Handle error from OnOwnerClosing function
  299.         /// </summary>
  300.         /// <param name="ex"></param>
  301.         private void HandleReadError(Exception ex)
  302.         {
  303.             Trace.WriteLine("Loading MRU from Registry failed: " + ex.Message);
  304.         }
  305.         /// <summary>
  306.         /// Handle error from OnOwnerClosing function
  307.         /// </summary>
  308.         /// <param name="ex"></param>
  309.         private void HandleWriteError(Exception ex)
  310.         {
  311.             Trace.WriteLine("Saving MRU to Registry failed: " + ex.Message);
  312.         }
  313.         /// <summary>
  314.         /// Get display file name from full name.
  315.         /// </summary>
  316.         /// <param name="fullName">Full file name</param>
  317.         /// <returns>Short display name</returns>
  318.         private string GetDisplayName(string fullName)
  319.         {
  320.             // if file is in current directory, show only file name
  321.             FileInfo fileInfo = new FileInfo(fullName);
  322.             if (fileInfo.DirectoryName == currentDirectory)
  323.                 return GetShortDisplayName(fileInfo.Name, maxDisplayLength);
  324.             return GetShortDisplayName(fullName, maxDisplayLength);
  325.         }
  326.         /// <summary>
  327.         /// Truncate a path to fit within a certain number of characters 
  328.         /// by replacing path components with ellipses.
  329.         /// 
  330.         /// This solution is provided by CodeProject and GotDotNet C# expert
  331.         /// Richard Deeming.
  332.         /// 
  333.         /// </summary>
  334.         /// <param name="longName">Long file name</param>
  335.         /// <param name="maxLen">Maximum length</param>
  336.         /// <returns>Truncated file name</returns>
  337.         private string GetShortDisplayName(string longName, int maxLen)
  338.         {
  339.             StringBuilder pszOut = new StringBuilder(maxLen + maxLen + 2);  // for safety
  340.             if (PathCompactPathEx(pszOut, longName, maxLen, 0))
  341.             {
  342.                 return pszOut.ToString();
  343.             }
  344.             else
  345.             {
  346.                 return longName;
  347.             }
  348.         }
  349.         #endregion
  350.     }
  351.     public delegate void MruFileOpenEventHandler(object sender, MruFileOpenEventArgs e);
  352.     public class MruFileOpenEventArgs : System.EventArgs
  353.     {
  354.         private string fileName;
  355.         public MruFileOpenEventArgs(string fileName)
  356.         {
  357.             this.fileName = fileName;
  358.         }
  359.         public string FileName
  360.         {
  361.             get
  362.             {
  363.                 return fileName;
  364.             }
  365.         }
  366.     }
  367. }
  368. #region Using
  369. /*******************************************************************************
  370. NOTE: This class works with new Visual Studio 2005 MenuStrip class.
  371. If owner form has old-style MainMenu, use previous MruManager version.
  372. Using:
  373. 1) Add menu item Recent Files (or any name you want) to main application menu.
  374.    This item is used by MruManager as popup menu for MRU list.
  375. 2) Write function which opens file selected from MRU:
  376.      private void mruManager_MruOpenEvent(object sender, MruFileOpenEventArgs e)
  377.      {
  378.          // open file e.FileName
  379.      }
  380. 3) Add MruManager member to the form class and initialize it:
  381.      private MruManager mruManager;
  382.    Initialize it in the form initialization code:
  383.    
  384.          mruManager = new MruManager();
  385.          mruManager.Initialize(
  386.              this,                              // owner form
  387.              mnuFileMRU,                        // Recent Files menu item (ToolStripMenuItem class)
  388.              mruItemParent,                     // Recent Files menu item parent (ToolStripMenuItem class)
  389.              "Software\MyCompany\MyProgram"); // Registry path to keep MRU list
  390.         mruManager.MruOpenEvent += this.mruManager_MruOpenEvent;
  391.         // Optional. Call these functions to change default values:
  392.         mruManager.CurrentDir = ".....";           // default is current directory
  393.         mruManager.MaxMruLength = ...;             // default is 10
  394.         mruMamager.MaxDisplayNameLength = ...;     // default is 40
  395.      NOTES:
  396.      - If Registry path is, for example, "SoftwareMyCompanyMyProgram",
  397.        MRU list is kept in
  398.        HKEY_CURRENT_USERSoftwareMyCompanyMyProgramMRU Registry entry.
  399.      - CurrentDir is used to show file names in the menu. If file is in
  400.        this directory, only file name is shown.
  401. 4) Call MruManager Add and Remove functions when necessary:
  402.        mruManager.Add(fileName);          // when file is successfully opened
  403.        mruManager.Remove(fileName);       // when Open File operation failed
  404. *******************************************************************************/
  405. // Implementation details:
  406. //
  407. // MruManager loads MRU list from Registry in Initialize function.
  408. // List is saved in Registry when owner form is closed.
  409. //
  410. // MRU list in the menu is updated when parent menu is poped-up.
  411. //
  412. // Owner form OnMRUFileOpen function is called when user selects file
  413. // from MRU list.
  414. #endregion