You try to build various conveniences into your interfaces to make life easier for your users, and some of the functionality can be quite complex. But even a small enhancement can pay off in terms of efficiency and ease of use. A good example is the combo box control. Why make your users type an entire word or scroll through a long list of items to select an entry? You can use a little trick to make the item appear as soon as they start typing a word that’s listed in the combo box.
This article will show you how to use theSendMessage API function to give your combo box controls this capability. As an additional refinement, we’ll set the control so that it adjusts its width to accommodate whatever item it’s displaying.
A look at the API
The SendMessage function is used to send a message to a window (control) by directly calling the Windows function for that window. The window’s function does not return until it has finished executing and can pass a value to the calling routine. The meaning of this value depends on the message. The SendMessage function must be used in situations where you want to send a message that returns a value.
The SendMessage function accepts four parameters—a window handle, message number, wParam, and lParam—and it returns a long value. Since SendMessage calls a window function directly, the window function can return a value that appears as the result of the SendMessage function.
Table A provides details on the parameters.
Table A
|
A SendMessage API VB declaration looks like this:
Private Declare Function SendMessage Lib “user32” Alias “SendMessageA”
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
The function can be used with Windows NT/2000/XP (Windows NT 3.1 and later) and Windows 95/98/Me (Windows 95 and later).
Putting SendMessage to work
Let’s create a simple VB project to show how you can use the SendMessage API to implement smart searches in your combo box controls.
First, fire up VB, start a new project, and set the ScaleMode property of the form to 4 – Character.
Next, add two labels to your form and set their Caption property to Select Profession and Select City. Add two combo boxes to your form and call them cboProfession and cboCity. Set their Style property to Dropdown Combo and make the width of both combo boxes small. At this point, your screen should resemble Figure A.
Figure A |
Sample combo box |
Now, add the following code to the declaration section of the form:
Option Explicit
Private Declare Function SendMessage Lib “user32” Alias “SendMessageA”
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const CB_ERR = (-1)
Private Const CB_FINDSTRING = &H14C
Add the following code to the Form_Load() event:
Private Sub Form_Load()
Call FillCities ‘fill combo box cboCity
Call FillProfessions ‘fill combo box cboProfession
End Sub
Add the following code to the cboCity_KeyPress() event:
Private Sub cboCity_KeyPress(KeyAscii As Integer)
Call SelectItem(cboCity, KeyAscii)
End Sub
Add the following code to the cboProfession_KeyPress() event:
Private Sub cboProfession_KeyPress(KeyAscii As Integer)
Call SelectItem(cboProfession, KeyAscii)
End Sub
Add these three procedures to the code:
Private Sub SelectItem(cbo As ComboBox, KeyAscii As Integer)
Private Sub FillProfessions()
Private Sub FillCities()
Add the code shown in Listing A to SelectItem, add the code shown in Listing B to FillProfessions, and add the code shown in Listing C to FillCities.
When you press [Ctrl][F5] to run the project, your screen should look something like Figure B.
Figure B |
Example output |
SendMessage in action
To test the functionality, click on the top combo box and type b. You should see the entry Banker appear in the combo box. Go back to the beginning of the line and type c. The entry CEO should appear. The same trick will work for the second combo box. Type n, and the entry New Orleans will appear—but continue typing New y, and New York will show up in the combo box.
In this sample, we used a SendMessage API to help users select items from the combo boxes, making a dynamic width adjustment to ensure that no item is cut off.
To achieve this functionality, we used a KeyPress event to implement the smart search feature, checking whether the ASCII value of the character that is typed in is alphanumeric and preventing users from entering other characters such as a dollar sign, plus or minus sign, percent symbol, and so on.
We save the characters the user types in sFindString and call the SendMessage API function to search the combo box control for an item matching what the user has entered. If the item is found, CB_FINDSTRING returns the number of the matching item, and we set the combo box control to display the item.
We also specified the form’s ScaleMode property (a property that allows setting a value that indicates the unit of measurement for the object) as Character to make sure that the width of the combo boxes on the form will be measured in characters not twips. Then, we just figured out the character length of the longest item in each combo box and used that value to specify the Width property of the controls.