Light-Weight, Multi-Column, Owner-Drawn ComboBox with AutoCompletion!

Here is one more article on ComboBox. This article presents yet another customized combo-box with the following features:

  • AutoCompletion as you type on; it is similar to the WizardBar in VC++ Developer Studio.
  • Each item can have one more column to supply extra information to the end user. The text (or say comment) is not part of the combobox, and does not participate in the AutoCompletion process. Neither it is shown when the combo-box is not dropped down.
  • It uses owner-drawing. Backed with this, it also supports to change various colors (text, background, and so forth) and the font itself.

Despite all these facts, I made it as lightweight as possible.

The CAutoCombo Class

The class CAutoCombo is inherited, as is obvious, from the MFC CComboBox class. The necessary requirements for using this class are as follows:

  1. You need to sub-class your control by passing its resource ID.
  2. The following properties must be set; otherwise, it will assert:
    • Type must be "DropDown"
    • OwnerDrawing: Fixed
    • "Has Strings" enabled
    • "Sort" should be disabled
  3. After you perform subclassing, you can add items to it and perform other customizations.

Here is a generalized class definition:

class CAutoCombo:public CComboBox {
public:
   void AddString(CString strItem);
   void AddString(CString strText, CString strExtra);
   CAutoCombo();
   CString GetString(int nSel=-1);    // -1 means current selection

   int GetCurSel()const;
   void SetCurSel(int nSelect);
   void DeleteString(int nItem)       // Zero-based position
   void ResetContent();
   int SubclassDlgItem(UINT nID, CWnd* pParent,bool bTabbed=false,
                       int nTabPos=160);

   int GetCount() const;

   void SetColor(COLORREF nColor, AutoComboColor nFor=NormalText);
   void SetFontEx(CString strFace, bool bBold=true);
};

A Bit of Detail on Important Methods

The first thing, as was mentioned, is to subclass the control. To do this, you call the following:

mCombo.SubclassDlgItem(IDC_SAMPLE,this,    // mCombo is of type
                       true,100);          // CAutoCombo

where the first two parameters need no discussion. Third parameter specifies whether or not multi-column mode will be used. The fourth specifies (valid if third param is true), the distance in pixels where should comment (second column) begin. Right now, only left-aligned columns are supported. After doing this, you can add items by using:

mCombo.AddString("Sun","Our global energy!");

where first param is the actual combo-box's string and the second string will be displayed on the right when the combo-box is dropped down. As soon as the user begins typing, it will be dropped down. The class also hides improper usage of CComboBox::AddString by overriding it. The second version can be used to supply comment-text by separating it throught the tab character ("\t"):

mCombo.AddString("Sun\tOur global energy!");

Only this single argumented version be used if multi-column is disabled (the third parameter of SubclassDlgItem is false); otherwise, it will ASSERT.

Changing Fonts

To change the font, you just need to call SetFontEx:

mCombo.SetFontEx("Palatino Linotype");

This sets the specified font. The second parameter of this method (which is, by default, false) expresses whether a bold font should be used. Right now, all items share the same font.

Changing Colors

To change colors, one needs to call a single method, SetColor:

   // Sets color for comments part, when item is selected
   // Sets normaltext color, does not affect selected mode color
mContinents.SetColor(RGB(0,0,128),SelectedComment);
mContinents.SetColor(RGB(0,128,255),NormalText);

Here, the first argument is manifest. The second argument tells "for which" color is to be changed. It can be from:

enum AutoComboColor {
   NormalText, NormalComment,
   SelectedText, SelectedComment,
   Selection
};

Currently, all items share the color property, depending on the selection mode.



Downloads

Comments

  • Cursor position problems in your code, i had used your code to fullfil the customer requirement

    Posted by rawoof on 06/28/2010 06:36am

    Your article is very much useful and i had used your article to list the elements based on the typing charecter in editbox of combobox.
    But i am facing one problem with cursor position:
    eg: if i type "abd" then bring the cursor postion to after 'b' charecter then type 'c' at that time the string is "abcd" but the cursor position should be at after 'c', but the cursor is coming to last(after 'd').
    Please let me know the solution for this.
    Like this while deleting from the middle also giving same problem.
    
    hope the above information is clear.

    Reply
  • great!

    Posted by jasion_wa on 03/12/2010 05:32pm

    useful for me. thanks!

    Reply
  • Improvements needed

    Posted by Anon75133 on 01/10/2008 03:24am

    You are missing some important features: Get/SetItemData for the base class (I added these), and ability to have the control sort items.
    
    Further, you should return values from AddString, as the base class does. This is useful for SetItemData, etc.
    
    Also, I fixed a minor bug: the control did not handle multi-column strings with the first column null (i e, string begins with tab).

    Reply
  • How to More Item

    Posted by cuongnq on 03/20/2006 04:27am

    How to more Item on this combo...Please help me

    • Re: How to More Item

      Posted by Ajay Vijay on 03/20/2006 09:00pm

      Well, in that case you need to change the implementation of class. You will need to implement one (or more) overloads for AddString, or combine all them in one AddString (determine columns by tabs in strig). Furthermore, you'll also need to change the ownerdrawing code. You might also provide color change option for 3+ column well...

      Reply
    • Thanks

      Posted by cuongnq on 03/20/2006 07:34pm

      In the example, i can add to list of combobox two col. Now i want to add 3 col or more. Ex: my_combo.addstring(col1,col2,col3); But it's only display 2 col. How to... Thanks in Advanced

      Reply
    • hi

      Posted by Ajay Vijay on 03/20/2006 01:52pm

      Use AddString method, as given in example as well as in article!

      Reply
    Reply
  • Very nice, but mouse pointer vanishes with autocomplete

    Posted by BHayes on 02/16/2006 03:56pm

    When you type in to use autocomplete, and the list is dropped, the mouse-pointer disappears. (I am working on fixing this now, but wanted to know if anyone has already fixed this.)

    • Not exactly what I see at Run (but here is mouse-pointer "fix")

      Posted by BHayes on 02/17/2006 02:03pm

      (Wish I could send a movie of what I see.)  
      At any rate, if you miss the mouse-pointer like I do, it can be kept by:
      
      // after ShowDropDown
      ShowDropDown();
      // add this
      ::SetCursor(::LoadCursor( NULL,MAKEINTRESOURCE(IDC_ARROW ) ) );
      
      (Thanks for the control!)

      Reply
    • It's by design

      Posted by Ajay Vijay on 02/17/2006 08:26am

      This behaviour is by design. Go to Run and type in any path, the mouse pointer will disappear!

      Reply
    Reply
  • Child dialog error assertion in Dialog based and SDI applications:

    Posted by Yenidai on 02/06/2006 04:34am

    If you have dialog based application: put in OnInitDialog() code like this:

    CWnd* pFrameWnd = STATIC_DOWNCAST(CWnd, AfxGetMainWnd());
    your_autocomboboxVar.SubclassDlgItem(IDC_YOUR_CONTROL_ID,pFrameWnd,true,92);
    
    If you have a SDI Application, then in child dialog put code like this:
    CFrameWnd* pMainWnd =	STATIC_DOWNCAST(CFrameWnd, AfxGetMainWnd());
    CFrameWnd* pActivFrm=	pMainWnd->GetActiveFrame();
    your_autocomboboxVar.SubclassDlgItem(IDC_YOUR_CONTROL_ID,pActivFrm, true,60);

    • I've mentioned...

      Posted by Ajay Vijay on 02/06/2006 08:40am

      See these points in the article that I've already mentioned: You need to sub-class your control by passing its resource ID. The following properties must be set; otherwise, it will assert: Type must be "DropDown" OwnerDrawing: Fixed "Has Strings" enabled "Sort" should be disabled After you perform subclassing, you can add items to it and perform other customizations.

      Reply
    Reply
  • very good

    Posted by Alin on 02/14/2005 03:28pm

    very good

    Reply
  • good indeed

    Posted by ovidiucucu on 02/08/2005 08:33am

    My rating: 5 :thumb:

    Reply
  • good job

    Posted by kirants on 01/05/2005 06:35pm

    well written..

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: November 6, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Are you wanting to target two or more platforms such as iOS, Android, and/or Windows? You are not alone. 90% of enterprises today are targeting two or more platforms. Attend this eSeminar to discover how mobile app developers can rely on one IDE to create applications across platforms and approaches (web, native, and/or hybrid), saving time, money, and effort and introducing apps to market faster. You'll learn the trade-offs for gaining long …

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds