Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to detect if combobox is expanded? 5

Status
Not open for further replies.

EwS

Programmer
Dec 30, 2002
398
US
I have a combobox with Style set to Dropdown List. I perform UpdateFlds (in Click event) after a selection has been made in the combobox. Right now, UpdateFlds is called when I press the arrows while the combobox is dropped. However, I want to call UpdateFlds only when the user presses "Enter" or when the combobox is "closed" (after a selection has been made). I was thinking I could do ExitSub in UpdateFlds if the combobox is expanded (dropped)? How do I detect it?

Thank you.
 
How about something like this:

Private Sub DoComboStuff()
MsgBox "I've been clicked"
End Sub
Private Sub Combo1_KeyPress(KeyAscii As Integer)
Dim i As Long
If KeyAscii = 13 Then
DoComboStuff
End If
End Sub
Private Sub Combo1_LostFocus()
DoComboStuff
End Sub
 
How about when the .Dropdown event is fired.

Thanks and Good Luck!

zemp
 
DrJavaJoe -
Yes, I'm detecting the Enter key pressed in the KeyPress event, but I can't use LostFocus event because I want to perform UpdateFlds as soon as the combobox is "closed" after a selection has been made (for instance, using a mouse), when the focus is still on the combobox.

zemp -
I don't see how I could use the Dropdown event. When it's fired I could set a flag indicating that the dropdown is down, therefore skip UpdateFlds, but I need another event in which I could reset the flag. I wished there was Dropup event or something like that.

I thought I saw some code for checking if the combobox is expanded, but I can't find it now. Does anyone know how to do it?
 
You can get the dropup event, but you would have to subclass the combo box to do it.

Go to this thread for a previous discussion on this.

thread222-384501
 
You can send the CB_GETDROPPEDSTATE message to get the drop state of a combo box.
Something like this...
___
Const CB_GETDROPPEDSTATE = &H157
DropState = SendMessage(Combo1.hwnd, CB_GETDROPPEDSTATE, 0, ByVal 0&)
 
I found this on
"
Const CB_GETDROPPEDSTATE = &H157
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd
As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

lDropped = SendMessage(cmbList.hWnd, CB_GETDROPPEDSTATE, 0, 0)

If lDropped = 0, the list is not visible, otherwise, it's visible.
"
 
Hello Hypetia,

Am I correct in my assumption that you would implement your code using a timer? Thanks!

Have a great day!

j2consulting@yahoo.com
 
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.
 
Hypetia,

Maybe I'm a glutton for punishment but I am really interested in the type of code you posted above. Where do you find and learn that kind of stuff? All I have ever seen are one page summaries (eg Are there books which explain this stuff in detail similarly to say the XXX Developers series that Ken Getz and Paul Litwin have done for Access, VB, VBA, etc?

Thanks again for taking the time to post a working example!

Have a great day!

j2consulting@yahoo.com
 
I've found Dan Appleman's "VB Programmers guide to the Win32 API" to be a good source.

Robert
 
Unfortunately I don't have an API book for consultation.

Most of the time, I go with the Microsoft's "Win32 Programmer's Reference" for API consultation. Infact, I make use of it so extensively that I have integrated this reference manual in my VBIDE by writing an Add-In.

It does not provide working examples in general, but still has comprehensive documentation which is sufficient to write working code.

I have got quite an old version of it, but still very very useful, atleast for me.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top