Click here to Skip to main content
Email Password   helpLost your password?
Screenshot - DriveComboBox.jpg

Introduction

Recently, I needed some way of displaying the logical drives on the computer and only the logical drives. I didn't think it would be any problem through the use of either OpenFileDialog or FolderBrowserDialog, but I quickly realized that these didn't do what I wanted them to do.

I, therefore, turned to CodeProject to see if a control existed here that could do the job. I found several (An "Explorer-Style" TreeView Control, DriveComboBox, Drive Box) - but none of them solved my problem to my satisfaction, and therefore I chose to hack my own control.

Using the code

To use the control, include the code and add a standard ComboBox to your form/dialog/control. Next, change the type of the control from "System.Windows.Forms.ComboBox" to "ZinoLib.Windows.Controls.DriveComboBox".

...
private ZinoLib.Windows.Controls.DriveComboBox _cbDrives = 
        new ZinoLib.Windows.Controls.DriveComboBox();
...

If you don't want to use the Designer to add the combo box to the parent control, the following code describes how to create and add the DriveComboBox to a parent control:

public class Form1 : System.Windows.Forms.Form
{
   private ZinoLib.Windows.Controls.DriveComboBox _cbDrives;

   ...

   private void CreateDriveComboBox()
   {
      _cbDrives = new ZinoLib.Windows.Controls.DriveComboBox();
      _cbDrives.Location = new System.Drawing.Point(8, 24);
      _cbDrives.Name = "_cbDrives";
      _cbDrives.Size = new System.Drawing.Size(320, 21);
      _cbDrives.TabIndex = 0;
      this.Controls.Add(this._cbDrives);
   }

   ...

}

The code presented in this article has support for both .NET framework 1.1 and .NET framework 2.0.

Points of interest

The .NET framework has built-in support for retrieving the logical drive letters via calls to System.IO.Directory.GetLogicalDrives() - however, it does not provide an interface to retrieve the volume name or the appropriate icon. By browsing through the source code of MrPJ's "Explorer-Style" TreeView Control and Microsoft article 319350, I figured out how to retrieve these information through the use of SHGetFileInfo located in shell32.dll. By parsing the appropriate flags, SHGetFileInfo can return the display name, icon index, icon handle, and more. I then needed a way to display this information - and thought it would be easy to extend Niels Penneman's excellent ImageCombo control. 10 minutes later, DriveComboBox was finished - and ready to be used.

The retrieval of the drive information is done in the function "BuildDriveList()" which is initially called by the constructor of DriveComboBox. Before SHGetFileInfo can be used to retrieve the actual drive information, we have to tell what information is needed. In the case of DriveComboBox, the following information is needed:

The actual retrieval is quite trivial, as we only have to iterate over the drives returned by System.IO.Directory.GetLogicalDrives() and call SHGetFileInfo for each drive. The information retrieved can then be used to build an ImageList of drive icons and add them to the combobox.

public void BuildDriveList()
{
   base.Items.Clear();

   ShellAPI.SHFILEINFO shInfo = new ShellAPI.SHFILEINFO();
   ShellAPI.SHGFI dwAttribs = 
     ShellAPI.SHGFI.SHGFI_ICON |
     ShellAPI.SHGFI.SHGFI_SMALLICON |
     ShellAPI.SHGFI.SHGFI_SYSICONINDEX |
     ShellAPI.SHGFI.SHGFI_DISPLAYNAME;

   ListDictionary _iconDict = new ListDictionary();            
   foreach( string drive in System.IO.Directory.GetLogicalDrives() )
   {
      IntPtr m_pHandle = ShellAPI.SHGetFileInfo(drive, 
                            ShellAPI.FILE_ATTRIBUTE_NORMAL,
                            ref shInfo,
                            (uint)System.Runtime.InteropServices.Marshal.SizeOf(shInfo),
                            dwAttribs);

      if( m_pHandle.Equals(IntPtr.Zero)==false )                    
      {
         int idxIcon = 0;
         if( _iconDict.Contains(shInfo.iIcon)==false )
         {
            base.ImageList.Images.Add( 
              System.Drawing.Icon.FromHandle(shInfo.hIcon).Clone() 
              as System.Drawing.Icon );

            User32API.DestroyIcon(shInfo.hIcon);

            _iconDict.Add( shInfo.iIcon, _iconDict.Count );
            idxIcon = _iconDict.Count-1;
         }
         else
            idxIcon = Convert.ToInt32( _iconDict[shInfo.iIcon] );


         ImageComboItem item = 
           new ImageComboItem(shInfo.szDisplayName, idxIcon, false);
         item.ItemValue = drive;
         base.Items.Add( item );
      }
   }

   if( base.Items.Count!=0 )
      base.SelectedIndex = 0;
}

License

You are free to use this code in any way you wish - both in freeware and commercial programs - free of charge. A small link in an About box etc. will be appreciated - but it is not required.

Acknowledgement

Most of the credit must go to Niels Penneman for his ImageCombo control which does most of the magic in the DriveComboBox control, and MrPJ for his "Explorer-Style" TreeView Control which gave me the idea to use SHGetFileInfo.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Generalnice
xtcradio
18:42 10 Mar '10  
thanks...
homer simpson....hahaha
GeneralInteresting, but I wonder...
Johnny J.
22:28 14 May '07  
It reads the drives when it is constructed. What happens when you connect or disconnect an external harddrive?

Cheers,
Johnny J.
GeneralRe: Interesting, but I wonder...
eisernWolf
23:06 14 May '07  
Nothing Smile
GeneralRe: Interesting, but I wonder...
Johnny J.
23:11 14 May '07  
Meaning what? That the box is updated to reflect the changes - or that it is NOT updated to reflect the changes?

Smile

Johnny J.
AnswerRe: Interesting, but I wonder...
Michael B. Hansen
23:46 14 May '07  
As it enumerates the drives in the constructor, then it will not discover that a drive has been unmounted.

One could instead have put the enumeration in an "Initialize"-method - which could be called by the user - and as such be able to update itself.

However, it does not contain any means on how to discover mounting and unmounting of drives automatically.


/Michael
GeneralRe: Interesting, but I wonder...
vodzurk
14:14 30 Aug '07  
Quick-fix...

Add a MouseDown event to the combo, which calls cmbDriveList.BuildDriveList()

---
I'm thinking of a song or two, a boy a girl and a rendezvous.

GeneralBUG - Identical items - Design-time
eisernWolf
22:02 14 May '07  
Hey guy, you have one funny bug. If using via designer... It serializes the items and after start-up the items are added once more. Simply hide the Items prop from the designer (DesignerSerializationVisiblityAttribute) and make it Browsable(false) cause no sense to edit the collection at all.
GeneralRe: BUG - Identical items - Design-time
Michael B. Hansen
23:48 14 May '07  
God catch.

I almost never use the designer - I haven't discovered the bug myself.


I'll update the code ASAP.


/Michael
AnswerRe: BUG - Identical items - Design-time
Michael B. Hansen
0:07 15 May '07  
Based on your comment and Johnny J's question - the code has been updated.


/Michael
GeneralNice But ...
Hamed_ji
1:56 13 May '07  
it's nice work but microsoft did it before

http://msdn2.microsoft.com/en-us/library/microsoft.visualbasic.compatibility.vb6.drivelistbox.aspx[^]

Hamed JI

GeneralRe: Nice But ...
Michael B. Hansen
8:02 14 May '07  
Well, yes and no.

The control you point to is first of all specific for .NET 3.0 - and second it requires the VisualBasic .NET DLL which i personally don't like to include in my assemblies.

But if it works for you.....


Personally the control you point to isn't an option for me.


/Michael
GeneralNice..
merlin981
12:11 8 May '07  
Very nice... but please provide some code examples next time.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I get my developer tools from Merlin A.I. Soft
I get my news and jokes from Daily Roundup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

AnswerRe: Nice..
Michael B. Hansen
12:18 8 May '07  
> please provide some code examples next time

I thought about it - but came to the conclusion that there isn't anything more to it than to change the ComboBox objects type from System.Windows.Forms.ComboBox to DriveComboBox.

But - point taken - I will update the article with a more descriptive example.


/Michael


Last Updated 23 May 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010