Click here to Skip to main content
Click here to Skip to main content

Image ComboBox Control

By , 7 Jul 2005
 

Introduction

ImageComboBox is an extension of the standard Windows ComboBox control, with support for displaying icons or images along with the item text. If you take a look at the Windows interface, you can see the Windows Explorer, Internet Explorer, File Open/Save/Print Dialogs, all using a combobox which can show icons and different levels of indentation.

A standard combobox does not support displaying graphic images, in the Normal DrawMode. But it can display icons or images when it is OwnerDrawn. Still there is something missing. The images can be drawn in the list portion, but when you select an item, its image is not displayed in the textbox except when the dropdown style is set to DropDownList. The combobox does not support editing when the dropdown style is DropDownList. The editable modes are Simple and DropDown. So I wanted the image to be drawn in the textbox, in all three DropDownStyles. This ImageComboBox is able to draw items along with the corresponding images in the list portion and text portion in all three DropDownStyles.

Apart from that this ImageComboBox also supports multiple levels of indentation for individual items. Indenting individual items enhances visual representation by grouping items and showing hierarchical relationships. The individual items can have their own font and size specified, when the DrawMode is set to OwnerDrawVariable. So an item in the combobox has several properties and all these properties need to be manipulated during design time or dynamically at runtime. Therefore the items are no longer simple strings, instead they are distinct ImageComboBoxItem objects. So the Items is a collection of ImageComboBoxItem objects.

ImageComboBoxItem

The ImageComboBoxItem has the following properties:

  • Image

    The image to be displayed along with the combobox item. The Image property exposes a dropdown window which shows the images taken from the ImageList.

  • Font

    The font to be used for the combobox item text, when the DrawMode is set to OwnerDrawVariable. The Font property exposes a font editor to select the desired font.

  • IndentLevel

    The level of indentation needed for an item. The ImageComboBox supports up to four levels of indentation, i.e., 0 -5.

  • Text

    The text of the combobox item.

The ImageComboBox also needs two new properties, an ImageList to hold the icons/images from which the user can select images associated with an item, and an Indent property to let the user specify the amount of indentation. The Items property is changed so that the items are of type ImageComboBoxItemCollection. A collection editor is provided to the user so that the properties of individual items can be added/removed/modified at design time.

ImageComboBox

Following properties are newly added to the ImageComboBox:

  • ImageList

    Holds the collection of images to be drawn with the items.

  • Items (changed property)

    The items of ImageComboBox. The items are of type ImageComboBoxItemCollection. The Items property exposes a new collection editor to add/remove/edit combobox items.

  • Indent

    The amount of indentation needed in pixels.

How to draw an image in the Edit portion of the ComboBox?

Displaying images in the combobox dropdown portion is fairly straightforward, and can be done by making the combobox owner drawn and drawing each item with an added image. On the other hand, displaying an image in the edit portion of the combobox when the DropDownStyle is set to DropDown or Simple is a difficult task. It requires getting the handle of the edit box, drawing the image, and setting a margin to the editbox so that the text displayed will be indented properly.

The good old Windows API calls do the trick.

  1. Get the handle of the Edit Box. The ComboBox is a combination of a TextBox and a ListBox. The GetComboBoxInfo(IntPtr hwndCombo, ref ComboBoxInfo info) method retrieves the handles and the coordinates of the TextBox and ListBox.
          [DllImport("user32")] 
    
          private static extern bool GetComboBoxInfo(IntPtr hwndCombo, 
                                               ref ComboBoxInfo info); 
    
          [StructLayout(LayoutKind.Sequential)] 
    
          private struct ComboBoxInfo 
          {
                public int cbSize;
                public RECT rcItem;
                public RECT rcButton;
                public IntPtr stateButton;
                public IntPtr hwndCombo;
                public IntPtr hwndEdit;
                public IntPtr hwndList; 
          }
  2. Set margin to the TextBox.
          [DllImport("user32", CharSet=CharSet.Auto)] 
    
          private extern static int SendMessage(IntPtr hwnd, 
                  int wMsg, int wParam, int lParam);
          private const int EC_LEFTMARGIN = 0x1; 
          private const int EC_RIGHTMARGIN = 0x2; 
    
          private const int EM_SETMARGINS = 0xD3;

    Set the margins using the SendMessage method. The combobox supports displaying items either left-to-right, or right-to-left. Depending on this setting, the margin has to be set. RightMargin needs to be in the hi-word, so multiply by 65536.

     SendMessage(ComboBox.Handle, EM_SETMARGINS, 
                       EC_RIGHTMARGIN, Margin * 65536);
     SendMessage(ComboBox.Handle, EM_SETMARGINS, EC_LEFTMARGIN, Margin);
  3. Drawing the image onto the text box.

    To achieve this, a class derived from NativeWindow is required. To this class we assign the handle of the TextBox so that we get access to the message stream directed to the TextBox. Then override the WndProc method and repaint the TextBox manually.

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case WM_PAINT:
            base.WndProc(ref m);
            DrawImage();
            break;
        
        case WM_LBUTTONDOWN:
            base.WndProc(ref m);
            DrawImage();
            break;
        case WM_KEYDOWN:
            base.WndProc(ref m);
            DrawImage();
            break;
        case WM_KEYUP:
            base.WndProc(ref m);
            DrawImage();
            break;
        case WM_CHAR:
            base.WndProc(ref m);
            DrawImage();
            break;
        case WM_GETTEXTLENGTH:
            base.WndProc(ref m);
            DrawImage();
            break;
        case WM_GETTEXT:
            base.WndProc(ref m);
            DrawImage();
            break;
        default:
            base.WndProc(ref m);
            break;
    }
}

public void DrawImage()
{
    if((CurrentIcon!=null))
    {    
        // Gets a GDI drawing surface from the textbox.
        gfx = Graphics.FromHwnd (this.Handle);
        bool rightToLeft = false;
        if(Owner.RightToLeft == RightToLeft.Inherit)
        {
            if(Owner.Parent.RightToLeft == RightToLeft.Yes)
                rightToLeft =  true;

        }
        if(Owner.RightToLeft == RightToLeft.Yes || rightToLeft)
        {
            gfx.DrawImage(CurrentIcon, 
              gfx.VisibleClipBounds.Width - CurrentIcon.Width,0);
        }
        else if(Owner.RightToLeft == RightToLeft.No || rightToLeft)
            gfx.DrawImage(CurrentIcon,0,0);
        
        gfx.Flush();
        gfx.Dispose();
    }
}

Using the ImageComboBox

Copy the ImageComoBox.dll from the bin\Release directory to your project directory. Open the Solution Explorer, right click the project name, and choose Add Reference. Click Browse button, locate the ImageComoBox.dll and select it. To display the control in Toolbox, right click on the toolbox, click Add/Remove Items. From the Customize Toolbox window, select the ImageComoBox.dll.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

About the Author

smn-12
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberpcs041414 Dec '12 - 21:12 
helpful,thanks
GeneralMy vote of 5mvpKanasz Robert27 Sep '12 - 10:50 
Good article
Generalabout imagecomboboxmemberBeiDaJadeBird21 Aug '12 - 6:55 
Exactly what i need,thx! jadebird
Answer16 pixel icon issuemembersidn0214 May '12 - 8:50 
To fit a 16 pixels icon without resampling set the ItemHeight property of combobox to 17. Awesome control
QuestionERRORmembermfelis30 Nov '11 - 2:47 
The control invoke a memory broke:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
GeneralNot working! :( [modified]membergeekman9229 Apr '11 - 19:15 
Hi im using VS 2010 and i have added the dll to the references and to the tools toolbox but everytime i try and create a combo box it comes up with this error:   Type universe cannot resolve assembly: System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d0a3a.  ...
GeneralMy vote of 5memberPamodh3 Sep '10 - 6:38 
Great control! Just what I needed for implementing a combo box to select folders.
GeneralMy vote of 5memberScruffyDuck4 Aug '10 - 1:12 
Does just what I need
GeneralDropDownStylememberIan W25 Mar '10 - 3:15 
This is quite a nice tutorial, but what would be good is if you emphasised this is for when dealing with DropDownStyle apart from the DropDownList. I wasn't aware that I could display icons and didn't read the article closely (just looked at the code). For me (and I imagine a few others) it...
GeneralA thank to the author [modified]memberfilipo260630 Aug '09 - 16:11 
This article is very useful for me. Thanks so much. Let me ask you a question about ....   KHong phai modified dau
GeneralLicensememberaldo hexosa6 Jul '09 - 15:58 
I'm so interested with your Image ComboBox. May i use your control in a commercial application? thanks
GeneralWebapplicationmemberRamkiran Hota6 Nov '08 - 19:30 
Hello   Nice article and control. But i have one requirement, i need this control in website. can i do that? when i tried to map the control dll into visual studio 2005 toolbox its not showing the control after adding?   what might be the problem...can u help
GeneralThanks!memberder_picknicker4 Aug '08 - 14:45 
This DLL helpted me much! Thank you!
QuestionLicence Terms [modified]memberjsp_116 Nov '07 - 2:34 
Can you clarify the licence terms for this Control, i.e. personal/commercial use   Jamie   -- modified at 12:08 Friday 16th November, 2007
GeneralComboBoxClear Function [modified]memberpablleaf8 May '07 - 6:47 
Just a little FYI. I noticed that when you call the comboboxclear function, it removed the items without a problem, but it left the selected items icon in the combobox edit section.   This problem can easily be corrected by adding the following line to the comboboxclear source code. ...
QuestionHow to set size the width of images in image Comboboxmemberman nhi26 Mar '07 - 22:28 
i set width of images to 100 in ListImage but it can't display the width i set. help me
AnswerRe: How to set size the width of images in image ComboboxmemberGIS_Developer21 Sep '08 - 22:25 
cbx.ItemHeight = 32;
AnswerRe: How to set size the width of images in image Comboboxmemberaaaadd13 Aug '10 - 8:59 
Ultimately this control sucks, square images only
Generalbindingsource suportmemberRagged8 Feb '07 - 3:06 
does it support bindingsource? i mean your images comes from database is some kind of stream format   Ragged
Questiontext changed but image can't change???memberkill11023 Oct '06 - 17:40 
when user change text but image can't changed,how can i do???   protected override void OnTextChanged(EventArgs e) { base.OnTextChanged(e); ???? ???? ???? EditBox.SetImageToDraw(); // the image on the textbox has to...
GeneralChange to allow clearing the selectionmemberdan neely11 Oct '06 - 4:11 
On a standard combobox you can clear the selection by setting the SelectedIndex property to -1. This change will allow the ImageCombobox to do the same.   protected override void OnSelectedIndexChanged(EventArgs e) { base.OnSelectedIndexChanged (e);   object selectedItem; if...
QuestionCould you set bottom and top margins?membercsepulveda20 Sep '06 - 22:42 
I would like know if you can set bottom and top margins as left and right margins. Thanks
QuestionHelp, plsmembercitpo15 Sep '06 - 6:58 
Hi i have a problem with this control.   If i create a MDI-form that open open 2 differnt child forms, each of these childforms has a ImageComboBox and an ImageList with some Images. I have the ImageComboBoxes set to "DropDownStyle: DropDownList", and the imagelist to the imagelist on...
GeneralVery nice, but little problem [modified]memberSteven Roebert11 Aug '06 - 4:00 
I really like your control, great work.   Only a little problem, when you are typing in the ComboBox, the image which is showing get's an increasing little black line around it, at least that's what happened when I used it. To prevent this, you should not only repaint the image, but the...
QuestionIs this control free?memberiLoveM8 Aug '06 - 20:04 
this control is very good, i want to use it in my program, can i use it?   Just relax

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 8 Jul 2005
Article Copyright 2005 by smn-12
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid