Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / programming / string

A way to disable auto-select based on partial string match of items in an editable CComboBox upon drop-down

4.50/5 (7 votes)
28 Feb 2010CPOL3 min read 1  
Combo boxes under Windows have a nice feature of automatically selecting an item for the user when the user drops down the list of the combo box. This selection is based on partial string matching by the combo box, namely, it will select the first item in the list -if any- that begins with the...
Combo boxes under Windows have a "nice" feature of automatically selecting an item for the user when the user drops down the list of the combo box. This selection is based on partial string matching by the combo box, namely, it will select the first item in the list -if any- that begins with the same characters that are in the edit field of the combo. For example if the combo box contains the following few items:

apple
pear
pineaple

and the user types "ap" into the edit field, and then clicks the button to display the dropdown list, the combo will select "apple" from its list, and replace the user's "ap" with "apple". This might be a good thing most of the time, but sometimes it might just be annoying, for example if the user only wants to see what items there are in the list without loosing what he already typed into the edit field of the combo box.
I have tried to find an easy solution for this, but google only asured me that i am not the only one in the world who would like this feature turned off time to time. (Of course, i might have been just looking for the wrong terms...)
So here's a possible solution: instead of making the combo box do a partial string match, let's make it do an exact string match, this way, it will only select the item in the list if it exactly matches the user's entry. Why this is good for us? Well, because if the user's entry is in the list, it will be neatly highlighted for him, however, since this string is exactly the same as the user's, it won't delete it (actually, it will replace the string with the one that is inside the list, but since this is the exact same string, the user won't see anything of this).
The method is quite simple. The combo box seems to be using the list's own method of searching strings, when the user drops down the list, the combo sends the LB_FINDSTRING[^] message to the list which searches for an item that begins with the specified substring. If we replace this message with LB_FINDSTRINGEXACT[^] the list will -as the name of the message suggests- search for an exact match. So what we can do is to subclass the list and when we get LB_FINDSTRING, call the original windows proc with LB_FINDSTRINGEXACT.
First, we use GetComboBoxInfo[^] with the combo to get the handle of the list, then we can use for example SetWindowLongPtr[^] with GWL_WNDPROC to make the list use our own procedure in which we "translate" the find-string messages. Here's a semi-pseudo implementatin:

1. - get the handle of the list
COMBOBOXINFO info;
GetComboBoxInfo(handle_to_the_combo, &info);
HWND handleOfList = info.hwndList;

2. - subclass the list
WNDPROC originalListProc;
originalListProc = (WNDPROC)SetWindowLongPtr(handleOfList, GWL_WNDPROC, MyListProc);

3. - implement MyListProc
LRESULT MyListProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  if (msg == LB_FINDSTRING) msg = LB_FINDSTRINGEXACT;
  return CallWindowProc(originalListProc, hWnd, msg, wParam, lParam);
}


This is of course just a barebone implementation, you can take it and form it to your needs, make it easily reusable, or write your own string-search method for example to change the case-sensitivity at needed, and so on...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)