Click here to Skip to main content
15,887,027 members
Articles / Desktop Programming / Windows Forms
Article

Most Recently Used (MRU) Component

Rate me:
Please Sign up or sign in to vote.
4.38/5 (4 votes)
5 Nov 20045 min read 110.7K   658   52   14
A Most Recently Used component written in C#.

Sample Image - MRUHandler1.jpg

Introduction

In an effort to learn C#, I started to redevelop an application program that I had written in Java. I quickly realized, like many others, that there was no Most Recently Used functionality built into the .NET framework.

The MRUHandler component displays a most recently used (MRU) menu list. Multiple MRUHanlder components can be used in the same application without colliding. For example, the image above depicts the demo program supporting an MRU history for files and a MRU history for viewed URLs. As well, it will work within the context of a Multiple Document Interface (MDI) application.

Background

After searching CodeProject, I found two reference articles: Joe Woodury's Most Recently Used (MRU) Menu class in C# and Alex Farber's Add Most Recently Used Files (MRU) List to Windows Applications. Unfortunately, neither of these appealed to me, as I was looking for an approach that would allow me to "plug-in" the MRU functionality. After reading Philip Davis’ article Extended Interface for Status Message, I decided to try developing this functionality as a custom Component.

MRUHandler Overview

Properties

The properties can only be set from the Designer or during the framework initialization. I was unsuccessful in finding a way to serialize the properties from the designer into the runtime, as you were able to do in Visual Basic 6.0. What I ended up doing was implementing the ISupportInitialize interface. This interface allows the MRUHandler to trap the start and end of the initialization and set an initializing flag. If anyone knows how to get the framework to do this, I would sure appreciate the input.

C#
public void BeginInit() {_isInitializing = true;}
public void EndInit() {
    _isInitializing = false;
    if (!DesignMode) {
        if (_mruItem == null) {
            throw new Exception("The property 'MruItem' item cannot be set to null");
        }
        RebuildMenu();
    }
}

Each of the properties then throws an exception if the _isInitializing flag is not set or the component is not in Design mode.

C#
public MenuItem MruItem {
    get{ return _mruItem;  }
    set{ 
        if (!DesignMode && !_isInitializing) {
            throw new Exception("The 'MruItem' can be only set in Design Mode");
        }
        _mruItem = value; 
    }
}

Available Properties

  • DisplayLength: The maximum length of the MRU entry file name when displayed.
  • MaxFiles: The maximum number of files to be maintained in the MRU History.
  • MRUItem: The menu item that is the place holder for the history list (when the style is Inline) or the parent menu item (when the style is Popup).
  • MRUStyle: Enumerated type to indicate if the MRU history should be displayed inline or as a popup menu.
  • ShowShortItem: Boolean value to indicate whether the display name should be compressed. If this is false, then the DisplayLength property is ignored.
  • StorageName: Provides a name for the file or registry key that is used to persist the MRU history. If the StorageType property is File or IsolatedStorage, the complete file name is generated using the product name (Application.ProductName) and this property, and the extension of the file is .mru. If the StorageType is Registry, this property is used to create a subkey under the application user data registry (Application.UserAppDataRegistry).
  • StorageStyle: Enumerated property to determine the location of the persistent storage used to save the MRU history information. Values are:
    • IsolatedStorage: The MRU history is stored using the .NET Isolated Storage facilities.
    • File: The MRU history is stored on the file system in the executable path (Application.ExecutablePath).
    • Registry: The MRU history is stored using the Win32 Registry. The values are added to the key specified by the StorageName property.

Public Methods

  • AddRecentlyUsedFile:
    The maximum length of the MRU entry file name when displayed.

Events

  • MRUItemClicked: The maximum length of the MRU entry file name when displayed.

Using the MRUHandler Component

Once the MRUHandler is installed in Visual Studio, adding MRU support to your application is as simple as dragging the component on to the main window and choosing which menu item is to be used as the MRU history placeholder. It is a good idea to have named this menu item something meaningful in order to assist in finding it in the list.

Image 2

Once you have chosen the menu item, then create the MRUItemClicked handler.

C#
private void OnMRUItemClicked(object sender, 
        MostRecentlyUsedHandler.MRUItemClickedEventArgs e) {
    DoFileOpen(e.File);
}

The MRUItemClickedEventArgs has a property File that contains the path name of the file that corresponds to be opened from the MRU history. In the demo program, DoFileOpen reads the file and opens the child window to display the contents.

The last step is to provide the mechanism that allows the application to tell the MRUHandler which file paths to keep track of and display. This is done by calling the AddRecentlyUsedFile method and passing the file path name that was just opened.

C#
private void DoFileOpen(string fileName) {
    FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
    Child form = new Child(fs);
    form.MdiParent = this;
    form.Show();
    mruHandler1.AddRecentlyUsedFile(fileName);
}

Points of Interest

Setting the modifier of the DataSet

When persisting the MRU to the file system, I had used a DataSet object to define an XML schema and do the actual transfer of information between the file system and the MRUHandler. I found that the default implementation provided by Visual Studio sets the access modifier of the generated class to public. The result was that MRUListFile would show up on the Toolbar as a component. It took a while, but I was able to change the access modifier of the generated class by going to the class view and selecting the properties of MRUListFile.xsd. I was then able to change the modifier to internal, which effectively hid this class in the designer.

Image 3

Build Versioning

I found that each time I rebuilt the application that contains the MRUHandler, the MRU history would be reset to empty when I was using a StorageType with a value of Registry. It turns out that the Application.UserAppDataRegistry refers to an application subkey that contains the Visual Studio generated version number. If this is a problem, it would be quite simple to modify the code to remove the version number from the key.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionWork with ToolStripMenuItems? Pin
CJMUK25-Nov-09 1:07
CJMUK25-Nov-09 1:07 
Generallast file open Pin
mr_view28-Mar-09 11:32
mr_view28-Mar-09 11:32 
QuestionCan I Get Just the Most Recently Used Files? Pin
jasmarc17-Mar-09 9:30
jasmarc17-Mar-09 9:30 
GeneralFile not found - Storing to file Pin
pk_fox15-Feb-06 2:58
pk_fox15-Feb-06 2:58 
GeneralRe: File not found - Storing to file [modified] Pin
mad-matt30-Apr-09 9:32
mad-matt30-Apr-09 9:32 
Questionupdate for .NET 2.0 menuStrip control? Pin
hungpvtn17-Jan-06 1:12
hungpvtn17-Jan-06 1:12 
AnswerRe: update for .NET 2.0 menuStrip control? [modified] Pin
George Birbilis23-Feb-07 2:30
George Birbilis23-Feb-07 2:30 
<br />
/*<br />
 * Last edit at 23Feb2007 by George Birbilis (birbilis@kagi.com)<br />
 *<br />
 * 23Feb2007:<br />
 * - Birb: changed to work with MenuStrip (.NET2.0) instead of MenuBar (.NET1.x)<br />
 * - Birb: renamed all MenuItem to ToolStripMenuItem<br />
 * - Birb: see various bug fixes below by searching for "Birb:"<br />
 * - Birb: added "AutoSeparators" property<br />
 */<br />
<br />
using System;<br />
using System.ComponentModel;<br />
using System.Collections;<br />
using System.Data;<br />
using System.Drawing;<br />
using System.Diagnostics;<br />
using System.Windows.Forms;<br />
using System.IO;<br />
using System.IO.IsolatedStorage;<br />
using System.Runtime.InteropServices;<br />
using System.Runtime.Serialization;<br />
using System.Runtime.Serialization.Formatters.Binary;<br />
using System.Text;<br />
using Microsoft.Win32;<br />
<br />
namespace MostRecentlyUsedHandler {<br />
    #region Enumerated Type Definitions<br />
    /// <summary><br />
    /// Enumerated type for the MRUStyle property<br />
    /// <list type="bullet"><br />
    /// <item><br />
    /// <term>Popup</term><br />
    /// <description>The Most Recently Used list is shown as a pop up menu.</description><br />
    /// </item><br />
    /// <item><br />
    /// <term>Inline</term><br />
    /// <description>The Most Recenly Used list is included in the menu where the desginated item would go.</description><br />
    /// </item><br />
    /// </list><br />
    /// </summary><br />
    public enum MRUStyle { Popup, Inline };<br />
<br />
    /// <summary><br />
    /// Enumerated type for the defining the persistent storage location of the Most Recently Used history<br />
    /// <list type="bullet"><br />
    /// <item><br />
    /// <term>File</term><br />
    /// <description>The Most Recently Used list persisted to the local file system.</description><br />
    /// </item><br />
    /// <item><br />
    /// <term>Registry</term><br />
    /// <description>The Most Recenly Used list is stored in the win32 registry.</description><br />
    /// </item><br />
    /// <item><br />
    /// <term>IsolatedStorage</term><br />
    /// <description>The Most Recenly Used list persisted in the .Net Isolated Storage.</description><br />
    /// </item><br />
    /// </list><br />
    /// </summary><br />
    public enum StorageStyle { File, Registry, IsolatedStorage };<br />
    #endregion<br />
<br />
    #region Most Recently Used menu click event definitions<br />
    /// <summary><br />
    /// The event arguments for the generated Most Recently Used menu click event<br />
    /// </summary><br />
    public class MRUItemClickedEventArgs : EventArgs {<br />
        private string _file;<br />
        public MRUItemClickedEventArgs(string file) { _file = file; }<br />
<br />
        public string File { get { return _file; } }<br />
    }<br />
<br />
    /// <summary><br />
    /// The delegate definition for the Most Recently Used menu click event<br />
    /// </summary><br />
    public delegate void MRUItemClickedHandler(object sender, MRUItemClickedEventArgs e);<br />
    #endregion<br />
<br />
    /// <summary><br />
    /// Summary description for MRUHandler.<br />
    /// </summary><br />
    [ToolboxBitmap(typeof(MRUHandler), "MRUHandler.bmp")]<br />
    public class MRUHandler : Component, ISupportInitialize {<br />
<br />
        #region private static definitions<br />
        /// <summary><br />
        /// Defines the Most Recently Used file definition<br />
        /// </summary><br />
        private static readonly string MRU_EXTENSION = ".mru";<br />
        /// <summary><br />
        /// Defines the registry key base name that is used to generate the key for each mru entry<br />
        /// </summary><br />
        private static readonly string REGISTRY_VALUE_NAME_BASE = "mru_entry_";<br />
        #endregion<br />
<br />
        public event MRUItemClickedHandler MRUItemClicked;<br />
<br />
        #region Constructors<br />
        public MRUHandler(System.ComponentModel.IContainer container) {<br />
            container.Add(this);<br />
        }<br />
<br />
        public MRUHandler() { }<br />
        #endregion<br />
<br />
        #region property field definitions<br />
        private ToolStripMenuItem _mruItem;<br />
        private MRUStyle _style;<br />
        private StorageStyle _storageStyle = StorageStyle.IsolatedStorage;<br />
        private int _maxFiles = 10;<br />
        private int _displayLength = 40;<br />
        private string _fileName = "mru";<br />
        private bool _showShortItem;<br />
        private bool _autoSeparators; //Birb (default value is "False" to maintain backwards compatibility)<br />
        #endregion<br />
<br />
        #region internal field definitions<br />
        private Hashtable _itemMap = new Hashtable();<br />
        private bool _mruIsDirty;<br />
        private ArrayList _mru;<br />
        private bool _isInitializing = false;<br />
<br />
        [DllImport("shlwapi.dll", CharSet = CharSet.Auto)]<br />
        private static extern bool PathCompactPathEx(StringBuilder pszOut, string pszPath, int cchMax, int reserved);<br />
        #endregion<br />
<br />
        /// <summary><br />
        /// Is the internal menu click handler for all of the Most Recently Used menu items.  Based on the menuitem<br />
        /// the file name is retrieved from the Hashtable.  The display text of the item will not be a usable file name.<br />
        /// For instance it has a number in front and the text could have been compressed by the 'ShowShortItem' property<br />
        /// </summary><br />
        /// <param name="sender">Object that raised the event</param><br />
        /// <param name="e">Event information</param><br />
        protected void onMenuItemClick(Object sender, EventArgs e) {<br />
            ToolStripMenuItem item = (ToolStripMenuItem)sender;<br />
            if (MRUItemClicked != null) {<br />
                string fileName = (string)_itemMap[item];<br />
                MRUItemClicked(this, new MRUItemClickedEventArgs(fileName));<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Add a file path name to the Most Recently Used history<br />
        /// </summary><br />
        /// <param name="fileName">path to be added</param><br />
        public void AddRecentlyUsedFile(string fileName) {<br />
            MRUList().Remove(fileName);<br />
            MRUList().Insert(0, fileName);<br />
            for (int i = _mru.Count; i > _maxFiles; ) {<br />
                _mru.RemoveAt(--i);<br />
            }<br />
            _mruIsDirty = true;<br />
            RebuildMenu();<br />
        }<br />
<br />
        #region properties<br />
<br />
        /// <summary><br />
        /// Property to determine the menuitem that becomes the place holder for the <br />
        /// Most Recently Used Menu items.<br />
        /// </summary><br />
        [Description("Specifies the menu item that is used as the MRU list parent.")]<br />
        public ToolStripMenuItem MruItem {<br />
            get { return _mruItem; }<br />
            set {<br />
                if (!DesignMode && !_isInitializing) {<br />
                    throw new Exception("The 'MruItem' can be only set in Design Mode");<br />
                }<br />
                _mruItem = value;<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Property that specifies what name is used in the storage of the MRU history<br />
        /// </summary><br />
        [Description("Specifies the name to be used to generate the file name for persistence.")]<br />
        public string StorageName {<br />
            get { return _fileName; }<br />
            set {<br />
                if (!DesignMode && !_isInitializing) {<br />
                    throw new Exception("The 'StorageName' can be only set in Design Mode");<br />
                }<br />
                _fileName = value;<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Property that determins the style of the MRU list at runtime<br />
        /// </summary><br />
        [Description("Specifies the style of the MRU list."),<br />
         DefaultValue(MRUStyle.Popup)]<br />
        public MRUStyle MRUStyle {<br />
            get { return _style; }<br />
            set {<br />
                if (!DesignMode && !_isInitializing) {<br />
                    throw new Exception("The 'MRUStyle' can be only set in Design Mode");<br />
                }<br />
                _style = value;<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Property to determine if the MRU menu item will show the truncated text.<br />
        /// </summary><br />
        [Description("Specifies whether the file name in the MRU entry should be truncated."),<br />
         DefaultValue(false)]<br />
        public bool ShowShortItem {<br />
            get { return _showShortItem; }<br />
            set {<br />
                if (!DesignMode && !_isInitializing) {<br />
                    throw new Exception("The 'ShowShortItem' can be only set in Design Mode");<br />
                }<br />
                _showShortItem = value;<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Property to determine if separators will be automatically placed arround inline MRU entries when necessery.<br />
        /// </summary><br />
        [Description("Specifies whether separators will be automatically placed arround inline MRU entries when necessery."),<br />
        DefaultValue(false)] //default value is "False" to maintain backwards compatibility<br />
        public bool AutoSeparators //Birb: added<br />
        {<br />
            get { return _autoSeparators; }<br />
            set {<br />
                if (!DesignMode && !_isInitializing) {<br />
                    throw new Exception("The 'AutoSeparators' can be only set in Design Mode");<br />
                }<br />
                _autoSeparators = value;<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Property to determine the type of persistent storage that should be used to store the MRU history.<br />
        /// </summary><br />
        [Description("Specifies the type of persistent storage to use to store the MRU history."),<br />
         DefaultValue(StorageStyle.IsolatedStorage)]<br />
        public StorageStyle StorageStyle {<br />
            get { return _storageStyle; }<br />
            set {<br />
                if (!DesignMode && !_isInitializing) {<br />
                    throw new Exception("The 'StorageStyle' can be only set in Design Mode");<br />
                }<br />
                _storageStyle = value;<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Property to determine the length of the MRU history.<br />
        /// </summary><br />
        [Description("Specifies the length of the MRU history file."),<br />
        DefaultValue(10)]<br />
        public int MaxFiles {<br />
            get { return _maxFiles; }<br />
            set {<br />
                if (!DesignMode && !_isInitializing) {<br />
                    throw new Exception("The 'MaxFiles' can be only set in Design Mode");<br />
                }<br />
                _maxFiles = value;<br />
                if (_mru != null) //Birb: added this check to bypass null pointer exception case, described at http://www.codeproject.com/cs/menu/MRUHandler.asp?forumid=124432&select=1114259&df=100#xx1114259xx<br />
                {<br />
                    _mru.Capacity = _maxFiles;<br />
                }<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Property to determine the length of text to be shown if the ShowShortItem property is set to true.<br />
        /// </summary><br />
        [Description("Specifies the length of the MRU menu text when the ShowShortItem property is true."),<br />
        DefaultValue(40)]<br />
        public int DisplayLength {<br />
            get { return _displayLength; }<br />
            set {<br />
                if (!DesignMode && !_isInitializing) {<br />
                    throw new Exception("The 'DisplayLength' can be only set in Design Mode");<br />
                }<br />
                _displayLength = value;<br />
            }<br />
        }<br />
        #endregion<br />
<br />
        #region Component overrides<br />
        /// <summary><br />
        /// Clean up any resources being used.<br />
        /// </summary><br />
        protected override void Dispose(bool disposing) {<br />
            if (_mruIsDirty) {<br />
                switch (_storageStyle) {<br />
                    case StorageStyle.File:<br />
                        saveToFile();<br />
                        break;<br />
                    case StorageStyle.Registry:<br />
                        saveToRegistry();<br />
                        break;<br />
                    default:<br />
                        saveToStorage();<br />
                        break;<br />
                }<br />
                _mruIsDirty = false;<br />
            }<br />
            base.Dispose(disposing);<br />
        }<br />
<br />
        #endregion<br />
<br />
        #region Access MRU in a file in Isolated Storage<br />
        private ArrayList loadFromStorage() {<br />
            IsolatedStorageFile isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null);<br />
            //							isoStore.DeleteFile(MRUFile());<br />
            if (isoStore.GetFileNames(MRUFile()).Length == 0) {<br />
                // File not exists. Create an empty file<br />
                return new ArrayList();<br />
            }<br />
<br />
            // Read the stream from Isolated Storage.<br />
            Stream stream = new IsolatedStorageFileStream(MRUFile(), FileMode.OpenOrCreate, isoStore);<br />
            if (stream != null) {<br />
                try {<br />
                    // DeSerialize the Hashtable from stream.<br />
                    IFormatter formatter = new BinaryFormatter();<br />
                    ArrayList appData = (ArrayList)formatter.Deserialize(stream);<br />
                    return appData;<br />
                }<br />
                finally {<br />
                    // We are done with it.<br />
                    stream.Close();<br />
                }<br />
            }<br />
            else {<br />
                return new ArrayList();<br />
            }<br />
        }<br />
        private void saveToStorage() {<br />
            // Open the stream from the IsolatedStorage.<br />
            IsolatedStorageFile isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null);<br />
            Stream stream = new IsolatedStorageFileStream(MRUFile(), FileMode.Create, isoStore);<br />
<br />
            if (stream != null) {<br />
                try {<br />
                    // Serialize the Hashtable into the IsolatedStorage.<br />
                    IFormatter formatter = new BinaryFormatter();<br />
                    formatter.Serialize(stream, MRUList());<br />
                }<br />
                finally {<br />
                    stream.Close();<br />
                }<br />
            }<br />
        }<br />
        #endregion<br />
<br />
        #region Access MRU in a file on the file system<br />
        private ArrayList loadFromFile() {<br />
            _mruIsDirty = false;<br />
            MRUListFile mruLF = new MRUListFile();<br />
            FileInfo fi = new FileInfo(Application.ExecutablePath);<br />
<br />
            mruLF.ReadXml(fi.DirectoryName + '\\' + MRUFile(), System.Data.XmlReadMode.IgnoreSchema);<br />
            ArrayList mru = new ArrayList(mruLF.MRUList.Rows.Count);<br />
<br />
            foreach (MRUListFile.MRUListRow row in mruLF.MRUList.Rows) {<br />
                mru.Add(row.mruentry);<br />
            }<br />
<br />
            return mru;<br />
        }<br />
<br />
        private void saveToFile() {<br />
            MRUListFile mruLF = new MRUListFile();<br />
            foreach (String str in MRUList()) {<br />
                mruLF.MRUList.AddMRUListRow(str);<br />
            }<br />
            FileInfo fi = new FileInfo(Application.ExecutablePath);<br />
<br />
            /*---------------*/<br />
            //Birb: changed to address the issue mentioned at http://www.codeproject.com/cs/menu/MRUHandler.asp?forumid=124432&select=1371902&df=100#xx1371902xx<br />
            String filename = (fi.DirectoryName + '\\' + MRUFile());<br />
            if (!System.IO.File.Exists(filename)) { System.IO.File.Create(filename); }<br />
            mruLF.WriteXml(filename, XmlWriteMode.IgnoreSchema);<br />
            /*---------------*/<br />
        }<br />
        #endregion<br />
<br />
        #region Access MRU stored in the registry<br />
        private ArrayList loadFromRegistry() {<br />
            RegistryKey key = Application.UserAppDataRegistry;<br />
            RegistryKey mruKey = key.OpenSubKey(_fileName, true);<br />
            if (mruKey != null) {							//	does it exist, if so load the values<br />
                object mruCount = mruKey.GetValue("mru_count");<br />
                int mruSize = (int)mruCount;<br />
                ArrayList mru = new ArrayList(mruSize);<br />
                for (int i = 0; i < mruSize; i++) {<br />
                    StringBuilder sb = new StringBuilder(REGISTRY_VALUE_NAME_BASE.Length + 10);<br />
                    sb.Append(REGISTRY_VALUE_NAME_BASE).Append(i);<br />
                    mru.Add(mruKey.GetValue(sb.ToString()));<br />
                }<br />
<br />
                return mru;<br />
            }<br />
            else {<br />
                return new ArrayList();<br />
            }<br />
        }<br />
<br />
        private void saveToRegistry() {<br />
            /*-------------*/<br />
            //Birb: changed as advised at http://www.codeproject.com/cs/menu/MRUHandler.asp?forumid=124432&select=975936&df=100#xx975936xx<br />
            RegistryKey key = Application.UserAppDataRegistry;<br />
<br />
            // no child keys anyway but also say don't throw<br />
            key.DeleteSubKey(_fileName, false); // so we can replace all the duplicates<br />
<br />
            RegistryKey mruKey = key.CreateSubKey(_fileName);<br />
            /*-------------*/<br />
<br />
            int counter = 0;<br />
            mruKey.SetValue("mru_count", MRUList().Count);<br />
            foreach (String str in MRUList()) {<br />
                StringBuilder sb = new StringBuilder(REGISTRY_VALUE_NAME_BASE.Length + 10);<br />
                sb.Append(REGISTRY_VALUE_NAME_BASE).Append(counter++);<br />
                mruKey.SetValue(sb.ToString(), str);<br />
            }<br />
        }<br />
        #endregion<br />
<br />
        #region menu item builder functions<br />
        /// <summary><br />
        /// Rebuilds the Most Rcently Used menu base on the value of the MRUStyle property<br />
        /// </summary><br />
        private void RebuildMenu() {<br />
            if (_style == MRUStyle.Popup) {<br />
                RebuildPopupMenu(); //Birb: moved code to "RebuildPopupMenu"<br />
            }<br />
            else {<br />
                RebuildInlineMenu();<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Rebuild the popup version of the most recently used list<br />
        /// </summary><br />
        private void RebuildPopupMenu() //Birb: added for better code readability (since original code already had a separate "RebuildInlineMenu")<br />
        {<br />
            _mruItem.DropDownItems.Clear(); //Birb: renamed MenuItems to DropDownItems<br />
            _itemMap.Clear();<br />
            _mruItem.Enabled = MRUList().Count > 0;<br />
            int counter = 1;<br />
            foreach (string str in MRUList()) {<br />
                ToolStripMenuItem item = buildMenuItem(counter++, str);<br />
                _itemMap.Add(item, str);<br />
                _mruItem.DropDownItems.Add(item); //Birb: renamed MenuItems to DropDownItems<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Rebuild the inline version of the most recently used list<br />
        /// </summary><br />
        private void RebuildInlineMenu() {<br />
            foreach (ToolStripMenuItem item in _itemMap.Keys) {		//	dispose all the existing menu items<br />
                item.Dispose();<br />
            }<br />
<br />
            _itemMap.Clear();								//	Now that the menuitems are disposed, clear the table<br />
<br />
            if (MRUList().Count > 0) {						//	if no mru list then leave the place holder visible<br />
                _mruItem.Visible = false;					//	force the place holder item to inert<br />
            }<br />
            _mruItem.Enabled = false;<br />
<br />
            int offset = 1;<br />
            ToolStripMenuItem parentMenu = (ToolStripMenuItem)_mruItem.OwnerItem;//	get our parent //Birb: renamed Parent to OwnerItem<br />
            ToolStripItemCollection parentItems = parentMenu.DropDownItems; //Birb: used instead of parentMenu.MenuItems<br />
            int MRUMenuIndex = /*_mruItem.Index*/ parentItems.IndexOf(_mruItem); //	where are we in the chain //Birb: changed the code to find the _mruItem index inside its parent since there's no Index property at ToolStripItem<br />
<br />
            if (_autoSeparators && (MRUList().Count > 0)) { //Birb<br />
<br />
                //Birb: "prepend" separator to mru item if not first item and not existing already<br />
                if ((MRUMenuIndex != 0) && !(parentItems[MRUMenuIndex - 1] is ToolStripSeparator)) {<br />
                    parentMenu.DropDownItems.Insert(MRUMenuIndex, new ToolStripSeparator());<br />
                    MRUMenuIndex += 1; //update the mru item index since we prepended a separator<br />
                }<br />
<br />
                //Birb: "append" separator to mru item if not last item and not existing already<br />
                if ((MRUMenuIndex != parentItems.Count - 1) && !(parentItems[MRUMenuIndex + 1] is ToolStripSeparator)) {<br />
                    parentMenu.DropDownItems.Insert(MRUMenuIndex + 1, new ToolStripSeparator());<br />
                    //don't update the mru item index, we appended something (didn't prepend anything)<br />
                }<br />
<br />
            }<br />
<br />
            foreach (string str in MRUList()) {<br />
                ToolStripMenuItem item = buildMenuItem(offset, str);<br />
                _itemMap.Add(item, str);<br />
                parentItems.Insert(MRUMenuIndex + offset, item); //Birb: renamed parentMenu.MenuItems to parentItems, renamed Add to Insert<br />
                offset++;<br />
            }<br />
        }<br />
<br />
        /// <summary><br />
        /// Builds a menu item for the path entry<br />
        /// </summary><br />
        /// <param name="position">Position in list</param><br />
        /// <param name="text">path</param><br />
        /// <returns></returns><br />
        private ToolStripMenuItem buildMenuItem(int position, string text) {<br />
            StringBuilder sb = new StringBuilder(text.Length + 10);<br />
            if (position < 10) {							//	only put ampersands on the first 9, otherwise<br />
                sb.Append('&');								//	we can't tell the difference between 1 & 10<br />
            }<br />
            sb.Append(position).Append(' ');<br />
            sb.Append(!_showShortItem ? text : GetShortDisplayName(text, _displayLength));<br />
<br />
            ToolStripMenuItem item = new ToolStripMenuItem(sb.ToString());<br />
<br />
            if (_style == MRUStyle.Inline) {<br />
                item.MergeIndex = _mruItem.MergeIndex; //Birb: renamed MergeOrder to MergeIndex<br />
                item.MergeAction = _mruItem.MergeAction; //Birb: renamed MergeType to MergeAction<br />
            }<br />
<br />
            item.Click += new System.EventHandler(onMenuItemClick);<br />
<br />
            return item;<br />
        }<br />
<br />
        /// <summary><br />
        /// Truncate a path to fit within a certain number of characters<br />
        /// by replacing path components with ellipses.<br />
        ///<br />
        /// This solution is provided by CodeProject and GotDotNet C# expert<br />
        /// Richard Deeming.<br />
        ///<br />
        /// </summary><br />
        /// <param name="longName">Long file name</param><br />
        /// <param name="maxLen">Maximum length</param><br />
        /// <returns>Truncated file name</returns><br />
        private string GetShortDisplayName(string longName, int maxLen) {<br />
            StringBuilder pszOut = new StringBuilder(maxLen + maxLen + 2);  // for safety<br />
            if (PathCompactPathEx(pszOut, longName, maxLen, 0)) {<br />
                return pszOut.ToString();<br />
            }<br />
            else {<br />
                return longName;<br />
            }<br />
        }<br />
<br />
        #endregion<br />
<br />
        #region internal helper functions<br />
        /// <summary><br />
        /// Generates a standard file name to be used to persist the mru history.<br />
        /// The formation is product name_file name property.mru<br />
        /// </summary><br />
        /// <returns>A string representing the file name to be used to store the mru history/returns><br />
        private string MRUFile() {<br />
            StringBuilder sb = new StringBuilder(256);<br />
            sb.Append(Application.ProductName).Append('_').Append(_fileName).Append(MRU_EXTENSION);<br />
            return sb.ToString();<br />
        }<br />
<br />
        /// <summary><br />
        /// Loads the mru history from the defined storage location.<br />
        /// </summary><br />
        /// <returns>An array containing the MRU history</returns><br />
        private ArrayList MRUList() {<br />
            if (_mru == null) {<br />
                switch (_storageStyle) {<br />
                    case StorageStyle.File:<br />
                        _mru = loadFromFile();<br />
                        break;<br />
                    case StorageStyle.Registry:<br />
                        _mru = loadFromRegistry();<br />
                        break;<br />
                    default:<br />
                        _mru = loadFromStorage();<br />
                        break;<br />
                }<br />
                _mruIsDirty = false;<br />
                for (int i = _mru.Count; i > _maxFiles; ) {<br />
                    _mru.RemoveAt(--i);<br />
                }<br />
            }<br />
<br />
            return _mru;<br />
        }<br />
        #endregion<br />
<br />
        #region ISupportInitialize Implementation<br />
        /// <summary><br />
        /// Implementation of the BeginInit Method.  Set a flag so that we are initializing the<br />
        /// component by the framework.  This will bypass all the run time error check on setting<br />
        /// the parameters.<br />
        /// </summary><br />
        public void BeginInit() { _isInitializing = true; }<br />
<br />
        /// <summary><br />
        /// Implementation of the EndInit Method.  When we this method is called, the framework <br />
        /// has completed initializing the component with the values that were set in the designer.<br />
        /// We now set the flag so that run time parameter setting is basically disabled.<br />
        /// </summary><br />
        public void EndInit() {<br />
            _isInitializing = false;<br />
            if (!DesignMode) {<br />
                if (_mruItem == null) {<br />
                    throw new Exception("The property 'MruItem' item cannot be set to null");<br />
                }<br />
                RebuildMenu();<br />
            }<br />
        }<br />
        #endregion<br />
    }<br />
}<br />



-- modified at 10:11 Friday 23rd February, 2007

Microsoft MVP J# 2004-2007
Borland "Spirit of Delphi"
QuickTime, ActiveX, VCL, .NET, Robotics
http://www.kagi.com/birbilis
http://birbilis.spaces.live.com

GeneralBug with MRU File storage Pin
attrixx22-May-05 23:41
attrixx22-May-05 23:41 
GeneralFile not found Pin
TJO119-Nov-04 16:23
TJO119-Nov-04 16:23 
GeneralRe: File not found Pin
Tim Almdal19-Nov-04 17:27
Tim Almdal19-Nov-04 17:27 
GeneralRe: File not found Pin
codegalaxy11-Mar-05 9:14
codegalaxy11-Mar-05 9:14 
Generalcode change in saveToRegistry() Pin
hans_nl11-Nov-04 23:52
hans_nl11-Nov-04 23:52 
GeneralRe: code change in saveToRegistry() Pin
Tim Almdal12-Nov-04 19:01
Tim Almdal12-Nov-04 19:01 
GeneralRe: code change in saveToRegistry() Pin
mchumph18-Nov-04 1:46
mchumph18-Nov-04 1:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.