Click here to Skip to main content
15,897,094 members
Articles / Programming Languages / C#

URLComboBox: A Window Forms Control for Displaying URLs

Rate me:
Please Sign up or sign in to vote.
4.86/5 (14 votes)
25 Feb 2002CPOL2 min read 177.4K   2.2K   60  
A Window Forms control for displaying URLs similar to URL combo in Internet Explorer
using System;
using System.Windows.Forms;
using System.ComponentModel;
using Microsoft.Win32;

namespace CP.Windows.Forms
{
	/// <summary>
	/// A simple enumeration that wraps various auto complete flags of SHAutoComplete.
	/// See documenation of SHAutoComplete for details
	/// </summary>
	[Flags]
	public enum AutoCompleteFlags : int
	{
		/// <summary>
		/// This includes the File System as well as the rest of the shell (Desktop\My Computer\Control Panel\)
		/// </summary>
		FileSystem = 0x00000001,
		/// <summary>
		/// URLs in the User's History
		/// </summary>
		URLHistory = 0x00000002,
		/// <summary>
		/// URLs in the User's Recently Used list.
		/// </summary>
		URLMRU = 0x00000004,
		/// <summary>
		/// Use the tab to move thru the autocomplete possibilities instead of to the next dialog/window control.
		/// </summary>
		UseTab = 0x00000008,
		/// <summary>
		/// This includes the File System
		/// </summary>
		FileSystemOnly = 0x00000010,
		/// <summary>
		/// Same as FileSystemOnly except it only includes directories, UNC servers, and UNC server shares.
		/// </summary>
		FileSystemDirs = 0x00000020,
		/// <summary>
		/// Ignore the registry default and force the auto suggest feature on.
		/// </summary>
		AutoSuggestForceOn = 0x10000000,
		/// <summary>
		/// Ignore the registry default and force the auto suggest feature off
		/// </summary>
		AutoSuggestForceOff = 0x20000000,
		/// <summary>
		/// Ignore the registry default and force the auto append on. 
		/// </summary>
		AutoAppendForceOn = 0x40000000,
		/// <summary>
		/// Ignore the registry default and force auto append off. 
		/// </summary>
		AutoAppendForceOff = -2147483648
	}
	
	/// <summary>
	/// Enumeration for possible types of registry base keys for storing most recntly typed URLs
	/// </summary>
	public enum MRUKeyHive : int
	{
		/// <summary>
		/// Value that indicates HKEY_CURRENT_USER should be used for MRUKey property
		/// </summary>
		CurrentUser = 1,
		/// <summary>
		/// Value that indicates HKEY_LOCAL_MACHINE should be used for MRUKey property
		/// </summary>
		LocalMachine = 2,
	}

	/// <summary>
	/// A control that extends the regular combo box to show URLs.
	/// </summary>
	public class URLComboBox : ComboBox
	{
		/// <summary>
		/// Member variable which stores the autocomplete flags
		/// </summary>
		private AutoCompleteFlags _flags = AutoCompleteFlags.FileSystem | AutoCompleteFlags.URLHistory | AutoCompleteFlags.URLMRU;
		/// <summary>
		/// Member variable which stores the mru key
		/// </summary>
		private string _mruKey = @"Software\Microsoft\Internet Explorer\TypedURLs";
		/// <summary>
		/// Member variable which stores the mru key hive
		/// </summary>
		private MRUKeyHive _mruKeyHive = MRUKeyHive.CurrentUser;

		/// <summary>
		/// Initilaizes a new instance of URLComboBox
		/// </summary>
		public URLComboBox() : base()
		{
		}
		
		/// <summary>
		/// Gets the registry key where MRU URLs are stored
		/// </summary>
		/// <param name="writable">Indicates whether to get the key so that it values written to it</param>
		/// <returns>RegistryKey object for the MRU registry key or null if none exists</returns>
		private RegistryKey GetMRUKey(bool writable)
		{
			if (_mruKey.Length == 0)
				return null;

			RegistryKey ret = null;
			
			switch(_mruKeyHive)
			{
				case MRUKeyHive.LocalMachine:
					ret = Registry.LocalMachine.OpenSubKey(_mruKey, writable);
					break;
				case MRUKeyHive.CurrentUser:
					ret = Registry.CurrentUser.OpenSubKey(_mruKey, writable);
					break;
			}

			return ret;
		}
		
		/// <summary>
		/// Writes information about any ignored exception to the trace.
		/// </summary>
		/// <param name="e">The exception which is being ignored</param>
		private void TraceIgnoredError(Exception e)
		{
			//It's ok if there is any error
			System.Diagnostics.Trace.WriteLine(e.Message);
			System.Diagnostics.Trace.WriteLine(e.StackTrace);
		}
		
		/// <summary>
		/// Utility function to fill the combob box most recently typed URLs read from registry.
		/// </summary>
		private void MRUFill()
		{
			if (DesignMode)
				return;

			RegistryKey mruKey = null;

			try
			{
                int i = 1;

				string strFormat = "url{0}";
				object defaultValue = String.Empty;
				object url;
				
				mruKey = GetMRUKey(false);
				
				if (mruKey != null)
				{
					while((url = mruKey.GetValue(String.Format(strFormat, i), defaultValue)) != defaultValue)
					{
						Items.Add(url);
						i++;
					}
				}
			}
			catch(Exception e)
			{
				TraceIgnoredError(e);
			}
			finally
			{
				if (mruKey != null)
					mruKey.Close();
			}
		}

		/// <summary>
		/// Gets or sets the auto complete flags
		/// </summary>
		[Description("Gets or sets the auto complete flags")]
		public AutoCompleteFlags Flags
		{
			get
			{
				return _flags;
			}
			set
			{
				_flags = value;
			}
		}
		
		/// <summary>
		/// Gets or sets the registry key name where the combo box maintains MRU list.
		/// </summary>
		[DescriptionAttribute("The registry key name where the combo box maintains MRU list")]
		public string MRUKey
		{
			get
			{
				return _mruKey;
			}
			set
			{
				_mruKey = value;
			}
		}
		
		/// <summary>
		/// Gets or sets the registry key hive for the MRUKey property.
		/// </summary>
		[DescriptionAttribute("The registry hive where the combo box maintains MRU list")]
		public MRUKeyHive MRUKeyHive
		{
			get
			{
				return _mruKeyHive;
			}
			set
			{
				_mruKeyHive = value;
			}
		}

		/// <summary>
		/// Writes the recntly typed URL to the registry if it is not already there
		/// </summary>
		/// <param name="e"></param>
		protected override void OnValidated(System.EventArgs e)
		{
			if (DesignMode)
				return;

			if ((Text.Length != 0) && (Items.IndexOf(Text) == -1))
			{
				Items.Add(Text);
				
				RegistryKey mruKey = null;

				//Finally add it to the registry
				try
				{
					mruKey = GetMRUKey(true);
					
					if (mruKey != null)
						mruKey.SetValue(String.Format("url{0}", Items.Count), Text); 
				}
				catch(Exception ex)
				{
					TraceIgnoredError(ex);
				}
				finally
				{
					if (mruKey != null)
						mruKey.Close();
				}
			}
	
			base.OnValidated(e);
		}
		
		/// <summary>
		/// Finds the handle to the edit control and calls SHAutoComplete on it.
		/// Also fills the combobox from the values read from the registry
		/// </summary>
		/// <param name="e">Ignored</param>
		protected override void OnHandleCreated(System.EventArgs e)
		{
			base.OnHandleCreated(e);
			
			if (DesignMode)
				return;

			//This is the right place do auto completion
			ComboBoxInfo info = new ComboBoxInfo();
			info.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(info);

			if (UnManagedMethods.GetComboBoxInfo(Handle, ref info))
			{
				UnManagedMethods.SHAutoComplete(info.hwndEdit, (IntPtr)_flags);
			}
			
			MRUFill();
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


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

Comments and Discussions