Community Pick: Many members of our community have endorsed this article.
Editor's Choice: This article has been selected by our editors as an exceptional contribution.

Do you Double-click on Combo Boxes?

Published:
Updated:
I do… Ever since I discovered the short-cut in Access 2.0, notably in the property sheets, I double click on all sorts of combo boxes — or their labels — to select the next item in the list.

This was a smart interface choice by the Access development team: you almost never need to double-click on a word in a combo box to select it, for example, and the feature is especially useful for combo boxes with short lists: “Yes/no”, “not indexed / indexed (with duplicates) / indexed (without duplicates)”, etc. It speeds up design and avoids having to create check boxes for properties that are really just flags.

To implement the same feature in your own applications, one line of code is enough (or three here, for readability).
Private Sub MyCombo_DblClick(Cancel As Integer)
                          With MyCombo
                              .Value = .ItemData((.ListIndex + 1) Mod .ListCount)
                          End With
                      End Sub

Open in new window

This sets the combo to the next item (list index plus one), wrapping to zero after the last item (modulo list count). The event can also be cancelled, but that is rarely useful.

It's not much code, but I use it so often that I normally create this function in the module dealing with the user interface:
Function ComboNextItem(cbo As ComboBox, Optional OrNull As Boolean)
                      ' Selects the next item in the passed combo box.
                      ' Set 'OrNull' to True (or 1) to select Null after the last item.
                      
                          If OrNull Then
                              ' let Null happen by overflow of list index
                              With cbo
                                  .Value = .ItemData(.ListIndex + 1)
                              End With
                          Else
                              ' wrap list index to list count
                              With cbo
                                  .Value = .ItemData((.ListIndex + 1) Mod .ListCount)
                              End With
                          End If
                          
                      End Function

Open in new window

Each combo box in my application then gets the following “On Dbl Click” property:

    = ComboNextItem(MyCombo)

or, in the rare cases where Null makes sense,

    = ComboNextItem(MyCombo,1)

This reduces the clutter in the form modules: no need for highly redundant event handlers for each and every combo on the form.


I hope you will find this trick useful!

Markus G Fischer
(°v°)

¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
This article is part of the EE-book unrestricted Access.
6
6,108 Views

Comments (5)

Author

Commented:
I just had a chat about one-liners (it's a hobby). As I did announce one in the article but didn't deliver, I might as well show it here, complete with the option flag...

(^v°)

Function ComboNextItem(cbo As ComboBox, Optional OrNull As Boolean)
With cbo: .Value = .ItemData((.ListIndex + 1) Mod (.ListCount - OrNull)): End With
End Function

Open in new window

DatabaseMX (Joe Anderson - Former Microsoft Access MVP)Database Architect / Application Developer
CERTIFIED EXPERT
Top Expert 2007

Commented:
"you almost never need to double-click on a word in a combo box to select it"
Well, that may be, but ... that is ... standard Windows operation ... double click in a 'text' box to highlight and select, and I have found that users 'expect' that to happen.

So, I recommend that you incorporate Shift (or Control) + DoubleClick to Increment ... AND maybe ... Alt + DoubleClick to Decrement ... which would be handy if the list has more than a few items, say 10 or more ...  and you happen to go one past the intended selection. Just Alt+Double Click to backup one.

mx

Author

Commented:
To incorporate the keyboard shift state isn't entirely trivial. You can't just trap the keyboard events for the control because the user might press Shift in another control and then double-click on your combo's label. A WinAPI call (GetKeyState) would do the trick, though.

Another idea would be to restrict the feature to the label of the combo box. This requires to examine the mouse position, exposed in the low-level mouse events. If you need to trap two events, it's probably best to do so via a class module, much heavier than a simple function call.

Anyway, I just took the habit to double-click, most of the time on the label. If the combo box displays a long text, long enough that a user might want to copy-paste portions of it elsewhere, then the double-click should not be activated, I suppose. Have you ever encountered a situation like this?

(°v°)
DatabaseMX (Joe Anderson - Former Microsoft Access MVP)Database Architect / Application Developer
CERTIFIED EXPERT
Top Expert 2007

Commented:
"I suppose. Have you ever encountered a situation like this?"
Well, not specifically.  Usually ... it would be a Text box.  But I was mainly ... just saying ....

"A WinAPI call (GetKeyState) would do the trick, though."
That's what I used for years.  I have that function in my mda library. Pretty simple really.

'Return the state of keyboard key requested....
Declare Function adiSWA_GetKeyState Lib "user32.dll" Alias "GetKeyState" (ByVal nKey%) As Integer

Public Function SWA_GetKeyState(argKeyName)
'Actions:Determine via Windows API call if specified key was depressed.
'             The argKeyName passed must be one on the Global keycode Constants
'------------------------------------------------------------------------------------------
    If adiSWA_GetKeyState(argKeyName) < 0 Then
        SWA_GetKeyState = True
    Else
        SWA_GetKeyState = False
    End If
End Function

Example usage:
If SWA_GetKeyState(vbKeyShift) = True Then    ' whatever

So, the GetKeyState could also be in the module that contains your ComboNextItem() function ... all self contained.

mx

Author

Commented:
Thank you MX

Your comments are a good addition to the article. This makes is simple to hook the “select next item” function to Ctrl+double-click (or Alt+click for that matter) and also a “select previous item” function to another combination, as you suggested.

Select previous, change line 8:
            .Value = .ItemData(.ListIndex - 1)

Open in new window

and line 13:
            .Value = .ItemData((.ListCount + .ListIndex - 1) Mod .ListCount)

Open in new window

This is with wrapping, which somehow seems less intuitive in this case, but would still be correct for simple Yes/No combos or similar.

(°v°)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.