The timer would be a simple and cheap solution to achieve this.
You could start your timer in the drop-down event and poll the drop state of the combo box in the timer event until it is closed and then you would perform the required actions and reset the timer again. That would work just fine.
However, there is another method by which you can get notification of the combo box closeup event instead of continuously polling the drop state using a timer. This is done via subclassing as suggested by TheVampire. This method is more compicated and requires quite a bit of hardwork to achieve this.
I give the code here for the comparison of the two methods.
Start a new project. Place two combo boxes on the form and insert the following code.
___
[tt]
Private Sub Form_Load()
Dim N As Long
For N = 1 To 12
Combo1.AddItem MonthName(N)
Next
For N = 1 To 7
Combo2.AddItem WeekdayName(N)
Next
SubClass Me.hwnd
End Sub[/tt]
___
Add a module to the project and insert the following code.
___
[tt]
'module code
Option Explicit
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Const WM_COMMAND = &H111
Const GWL_WNDPROC = -4
Const CBN_CLOSEUP = 8
Dim lpPrevWndFunc As Long
Sub SubClass(hwnd As Long)
lpPrevWndFunc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WndProc)
End Sub
Function WndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = WM_COMMAND Then
If HiWord(wParam) = CBN_CLOSEUP Then
'A combo box is closed.
'But we can't just access the properties of the combo box
'right now. Although the combo box is closed but its other
'properties are still not updated (e.g. the ListIndex and
'the Text properties of the combo box.)
'We need to wait for a while before the pending messages in
'queue are flushed and combo box and its properties are
'updated properly. For this purpose, we set up a timer that
'fires when there is no other message in the message queue
'of the current thread.
'Note that the lParam parameter is passed as the EventId
'parameter which contains the handle of the combo box.
SetTimer hwnd, lParam, 0, AddressOf TimerProc
End If
End If
WndProc = CallWindowProc(lpPrevWndFunc, hwnd, uMsg, wParam, lParam)
End Function
Function HiWord(DWord As Long) As Integer
CopyMemory HiWord, ByVal VarPtr(DWord) + 2, 2
End Function
Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTime As Long)
'kill the timer to prevent further executions
KillTimer hwnd, idEvent
'if we have more than one combo box on the form,
'we need to identify which combo box was closed.
Select Case idEvent 'contains the handle of the combo box.
Case Form1.Combo1.hwnd
'combo1 is dropped-up
MsgBox Form1.Combo1.Text, , "Combo box 1 closed"
Case Form1.Combo2.hwnd
'combo2 is dropped-up
MsgBox Form1.Combo2.Text, , "Combo box 2 closed"
'for other combo boxes on the form
'Case Form1.Combo3.hWnd
'and so on...
End Select
End Sub[/tt]
___
Run the program and experiment with the combo boxes. You will get the message box whenever the combo box is closed.
One thing should be noted that this code will NOT notify you when you change the selection in the combo box from arrow keys or from Home/End/Page Up/Page Down keys WITHOUT dropping it. It will ONLY notify you of the closeup event, which is the main purpose of this discussion.
Keeping in view the comlexities of this method, I suggest you to go with the timer way which is easier to understand and manage.