Virtual Developer Workshop: Containerized Development with Docker

Some were of the drop-down style where a list of predefined entries is displayed but the user may also add a new entry if the one he wants is not there.

MFC provides good functionality for both of these styles. The drop-list style also has basic type ahead functionality. If the user presses a key and an item beginning with that letter is in the list, it will be automatically highlighted. However the drop-down style does not have this functionality at all. What I wanted for my drop-down combo box is the kind of type ahead functionality found in Microsoft Excell.

When the user presses a key in the combo box the first item beginning with that letter is highlighted. However as the user continues to type, a string is formed, upon each key press, this string is checked against existing entires in the combo box and if one begings with the string then it is highlighted. What will happen is that if the user starts to type an entry that already exists, only a few key presses will be required to select it. If he types to the point where the string typed no longer matching an existing entry, a new one is automatically created.

How I did It

I'm sure there are several ways to do this kind of thing with MFC but I opted for the window subclassing method (probably because I'd just learnt about subclassing!). Subclassing allows the programmer to modify one of the Windows controls to provide the required functionality. A bit like inheritance really.

Subclassing An Ordinary Control

Lets say you wanted to subclass an ordinary control such as an edit box. I did this to create an edit box that would only allows numbers, the '.', delete and backspace keys. I used this for the input of monetary values. To subclass an edit control you create a new class derived from CEdit and create a control of this new class in your application. Assuming it is on a dialog box, you would add the following line to your dialog class' declaration:
	CNumericEdit	m_xAmount;
And in the OnInitDialog() function:
	m_xAmount.SubclassDlgItem(IDC_AMOUNT, this);
Where IDC_AMOUNT is the ID of the control you placed on the dialog form in the resource editor.

Subclassing a Combo Box

Subclassing a simple control is fairly straightforward. Unfortunately a combo box is made up of a list box and an edit box. To change the way the edit portion works, we need to actually subclass the edit portion of the combo box.

I've created a class called CTypeAheadCombo derived from CComboBox and a class called CComboEdit derived from CEdit. It's the edit class that does all the work. The only reason we need to subclass the combo box itself is to allow us to use the subclassed edit control in place of the ordinary one.

In the subclassed combo, we made a member variable of our subclassed edit control:

	CComboEdit	m_xEdit;
And then we override PreSubclassWindow() as follows:
	void CTypeAheadCombo::PreSubclassWindow() 
		m_xEdit.SubclassDlgItem(1001, this);	
Notice the 1001 used in place of a resource ID. Luckily for us, the edit portion of a combo box is always allocated the resource ID of 1001 which is quite handy.

Now onto the edit control itself...

The most obvious function to override is OnChar(). By trapping the characters types I can build up a search string to use when searching through the list of entries. I've used a CString for my search string and I've made it a member variable. In this way as long as the control is in existence (which will be for the life of the dialog) I can muck about with the search string to my hearts content but it gets reset when the combo box is recreated.

The basics of what I wanted to do it to trap the key that the user pressed, add it to the search string and then do a FindString() on the combo box to see if an entry exists. To get to the combo control I've just used a pointer to the parent of the edit control.


The basic building up of a search string and finding it within the list of entries was quite easy. What was not so easy was handling other keys. For example, if the user used the cursor keys to step back through his selection and type something, OnChar would only trap the new character typed but of course this character has now been placed into a different part of the string.

When the user presses backspace, parts of the string are deleted. the problem here is that I need to allow the user to delete his selection if required. The way I've done this is to say that if the user presses backspace or delete while a selection is currently highlighted, to unhighlight the selection and blank out the edit box.

OnKeyDown was needed to trap the cursor keys and the delete keys.

Other problems I encountered were with the caret. If I trapped the delete and cursor keys I had to ensure that the base class was called to actually process the key. My problem was with positioning the caret in the correct place. I had to set up a few bool variables to keep track of the original caret position, whether the delete or backspace keys were pressed and if a selection was highlighted.

The code itself is well-commented I think and should be enough to step you through how it's done.

If you have any comments, criticisms, suggestions etc then please e-mail me!
Caroline Price

Download file


  • Problem in writing text after shifting the caret to specific position

    Posted by Legacy on 05/23/2002 07:00am

    Originally posted by: Jamil Anwar

    I am developing an editor type application and the problem that I am facing is that, I insert an HTML tag like <B></B> in my rich edit control by clicking a button having caption B in the toolbar, I save the caret position after the insertion of first costant string "<B>" and after inserting the second "</B>" the caret position is on the end of "</B>" but I want to set the caret position after <B>, I use the RichEditCtrl method "SetCaretPos()" to set the caret after <B>, it works but when I start writing at the saved caret postion, it moves at the end of </B> and inserts text after </B>, i.e I want to write at <B>|(here)</B>, but control shifts at the end i.e, <B></B>|(here), although, if I move the caret using left key and start writng, it works that is not required, I am much confused please some one help me

    Special Thanks
    JAMIL -_0_-

  • Giai thich

    Posted by Legacy on 03/14/2002 08:00am

    Originally posted by: Nguyen huy thai

    Trung tam tin hoc NBINH

  • wess�

    Posted by Legacy on 01/17/2002 08:00am

    Originally posted by: wess�

    It is just great ...=)

  • What About Sample Project

    Posted by Legacy on 07/20/1999 07:00am

    Originally posted by: Viktor

    This code can be improved, I also agree with the author of comment "A simpler solution". It'll be nice to present a sample project using the subclassed control. In any case a distribution should be self-sufficient (both component and sample if present). We are competent enough to make it for You but somebody can be too lazy.
    And some notes about window subclassing. I knew some situations where it's not a panacea. When You subclass a control in the CDialog::OnInitDialog() override some initialization stages are already passed through the standard message route. So in general case to provide more universal behavior (and change background brush conjointly, for instance) we should register an own window class for it (RegisterClass or AfxRegisterWndClass). In this case a dialog can operate simpler when using Your control. For convenience data exchange support should be implemented.

  • Doesn't look too good?!

    Posted by Legacy on 05/11/1999 07:00am

    Originally posted by: George

    Unless something wrong with my winzip7.0 and Windows Commander 3.53 I have the following complains:

    1) The download file does not contain the project, but only 4 files, which are part of the project, it cause 2
    2) The files are including the headers are missing,
    3) The zip is eating the long filenames, so I need to restore them manually!!!
    4) Cannot build anyway, because CCombEdit and CTypeAheadCombo can't see each other,
    5) It doesn't do what is expected, eg. the selection should not be for the full text, but for the part not typed yet,

    Summary: Good article, bad download...

    Nothing personal, but next time please try to download the thing back from the site after posting and then use it...

    Best Regards

  • A simpler solution

    Posted by Legacy on 03/24/1999 08:00am

    Originally posted by: Christian Tratz

    I checked out the code and found it a bit confusing at the first look. So i tried to rewrite it an d finally
    found a much simpler solution without all those status flags.

    Here it goes (Just changed the CComboEdit):

    void CComboEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

    CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
    CSearchBox* pParent = (CSearchBox*) GetParent();

    if(nChar == VK_RETURN)
    CString str;


    void CComboEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
    CEdit::OnChar(nChar, nRepCnt, nFlags);

    int index, len;
    CString str;
    CSearchBox* pParent = (CSearchBox*) GetParent();

    if(nChar != VK_BACK)
    len = str.GetLength();

    index = pParent->FindString(-1,str);

    if(index != -1) //found something

  • Auto-completion ComboBox (2)

    Posted by Legacy on 10/22/1998 07:00am

    Originally posted by: Andrew Guryanov

    For sucker - it is a piece of satisfactory code
    but it is a "codeguru" site!
    you should review submissions.

    I have checked my old program - it took me
    20 lines of code to implement similar functionality,
    6 of them are a sort of

  • You must have javascript enabled in order to post comments.

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

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date