Jul 27, 2012

Create Drive combo box in C#

2 comments
While browsing at some places on internet we may seen the Drive combo box as shown below,

How to create/populate combo box like this in WinForms using C#.Net?

The drive information can be retrieved using DriveInfo.GetDrives() method.  And for getting the corresponding icons for drive letters, I am using the SHGetFileInfo WIN32 API call.


Implementation details are as follows,

private void btnGetDrives_Click(object sender, EventArgs e)
        {
            cboDrives.DrawMode = DrawMode.OwnerDrawFixed;
            cboDrives.DropDownStyle = ComboBoxStyle.DropDownList;
            cboDrives.DrawItem += new DrawItemEventHandler(CboDrives_DrawItem);

            DriveInfo[] drives = DriveInfo.GetDrives();
            cboDrives.Items.AddRange(drives);
        }


Draw the combobox items with drive icon using DrawItem() event.


private void CboDrives_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index == -1)
                return;

            e.DrawBackground();
            Icon icon = GetIcon(cboDrives.Items[e.Index].ToString());
            e.Graphics.DrawIcon(icon, 3, e.Bounds.Top);
            e.Graphics.DrawString(cboDrives.Items[e.Index].ToString(),
                cboDrives.Font, Brushes.Black, icon.Width + 2, e.Bounds.Top);
            e.DrawFocusRectangle();
        }

here is the GetIcon method and API declaration

        private const uint SHGFI_ICON = 0x100;
        private const uint SHGFI_LARGEICON = 0x0;
        private const uint SHGFI_SMALLICON = 0x1;

        private const int HWND_TOPMOST = -1;
        private const int SWP_NOMOVE = 0x0002;
        private const int SWP_NOSIZE = 0x0001; 

        [DllImport("shell32.dll")]
        private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
        
        private Icon GetIcon(string fileName)
        {   
            SHFILEINFO shinfo = new SHFILEINFO();
            IntPtr hImgSmall = SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_SMALLICON);
            return Icon.FromHandle(shinfo.hIcon);
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct SHFILEINFO
        {
            public IntPtr hIcon; public IntPtr iIcon; public uint dwAttributes;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
        };


Done.

If you feel this is helpful or you like it, Please share this using share buttons available on page.

2 comments :