Importance of Target Size
When designing mouse-optimized user interfaces, one of the most important concepts is target size. It's a simple concept. The bigger the target, the easier it is to hit.
Think about darts. Hitting the bullseye of a dart board from eight feet away is very difficult. Hitting the dartboard itself is much easier.
The same concept applies when it comes to using the mouse to work with a combo box.
Target Size: Combo Box Edition
There are two primary features of a combo box that make it such a versatile and powerful control: autocomplete and displaying a list of choices via a dropdown window.
For autocomplete to work in a combo box with an existing value, the user must first select the entire text within the combo box. Thus, for maximum efficiency, we want to make it as easy as possible for the user to select all of the text within a combo box.
"We want to make it as easy as possible for the user to select all of the text within a combo box."
The down-pointing triangle on the right side of the control is a relatively small target, especially when you contrast it with the much larger text area to the left. If the user clicks on an empty combo box, they will usually want to be able to choose from one of the options in the dropdown. So, we want to make it as easy as possible to trigger a dropdown on an empty combo box.
"We want to make it as easy as possible for the user to show the dropdown for an empty combo box."
Increasing the Target Size: Built-in Approaches
One simple way to increase the target size of a combo box (or any editable control) is to make sure that the control's corresponding label is properly associated with the control.
Labels can never receive the focus themselves. So, if a label is "associated" with an editable control, then clicking on the label will set focus to that associated control. In addition to passing focus to the combo box, clicking on the associated label also selects all of the text within the combo box. As stated above, this is important for streamlining the autocomplete feature.
Clicking on an associated label increases the target size, but only if your users understand that it's an option. Probably the best way to train them is to be consistent with your UI design. Make sure that all labels are associated with their editable control counterparts. While you're in form design view, watch for the green triangle in the upper left corner of your unassociated labels. Follow the steps in the above animated gif to associate them with the appropriate control.
Increasing the Target Size: VBA Approach
Sometimes your combo box won't have an associated label. Not only that, some users will never make the connection between clicking the label and having the focus shift to the combo box's value.
I created a simple function that effectively increases the target size of combo boxes for both autocomplete and dropdown purposes.
When an empty combo box control receives the focus, the function triggers the combo's .Dropdown method.
When you single-click on a combo box that already has a value, the entire contents of the combo box are selected. This lets the user immediately replace the value of the combo box, taking advantage of all the autocomplete goodness that comes with doing that.
If the user double-clicks a word in the combo box, we use the default double-click action. Same goes for the click and drag action.
The Code: EnterCombo()
'Add a call to this function to the OnKeyUp and OnMouseUp events for all combo boxes: ' =EnterCombo([Form].[ActiveControl]) for combo boxes with 1 column only ' =EnterCombo([Form].[ActiveControl],1) for combo boxes with 2 columns (1st hidden) Function EnterCombo(cmb As ComboBox, Optional col As Integer = 0) On Error GoTo Err_EnterCombo If Nz(cmb.Column(col)) = "" Then cmb.Dropdown Else 'we need to check the current selection length, otherwise the control does not work as 'expected when the user clicks directly on the triangular dropdown symbol If cmb.SelLength = 0 And cmb.SelStart > 0 And Nz(cmb.Column(col)) <> "" Then cmb.SelStart = 0 cmb.SelLength = Len(Nz(cmb.Column(col))) End If End If Exit_EnterCombo: Exit Function Err_EnterCombo: 'if there is no record selected an error will be generated '(happens if control is in form header/footer and AllowAdditions is set to false ' and the form is filtered so there are no records) 'there is no need to fill up the error log with these errors, so we won't record it If Err.Number <> 2185 Then 'Replace with your own error logging function: 'LogError Err.Number, Err.Description, "EnterCombo", cmb.Name, False End If Resume Exit_EnterCombo End Function
There are two primary ways to call this function: 1) in code or 2) from the Event tab of the combo box Property Sheet.
To call the function in code:
Private Sub cbExample_KeyUp(KeyCode As Integer, Shift As Integer) EnterCombo Me.cbExample End Sub Private Sub cbExample_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) EnterCombo Me.cbExample End Sub
To call the function from the Property Sheet:
Note that you can only call a public Function from the Property Sheet; you cannot call a public Sub. That is why I declared the routine as a Function, even though it does not return any results.
Oftentimes you will want to call this function from multiple combo boxes on the same form. You can hold down the shift key and click on multiple combo boxes to update the On Mouse Up and On Key Up properties for several combo boxes at once. The problem is that each combo box control will have a different name.
A handy shortcut I use is to pass the ActiveControl property of the Form object to the function. This way I can assign the function call to several controls all at the same time.
Here's an example: