A combo box is placed within a MSFlexGrid so that when I click on the grid, the dropdown list appears and I can make a selection. For that, I use
Code:
SendMessage cbo.hwnd, CB_SHOWDROPDOWN, 1, 0&
in the grid's Click event for when the first column is clicked, and it works. However, unless I make a selection from the list, I cannot click anywhere else on the grid to cause the list to retract. If I make a selection, the list retracts. If I make no selection, the list retracts only if I click outside the grid. I have tried
Code:
SendMessage cbo.hwnd, CB_SHOWDROPDOWN, 0, 0&
in the LostFocus event of the combo box but clicking somewhere else in the grid does not activate this event and the list keeps appearing. What is wrong?
Here is an image to clarify the situation:
If I click in the column "Description", the combo box remains as it is in the column "Part No.". I have also tried
Code:
SendMessage cbo.hwnd, CB_SHOWDROPDOWN, 0, 0&
in the grid's Click event for when the second column is clicked but it does not work neither.
I need to know how to make the list retract when I click anywhere else in the grid, without any selection made in the combo box. Thanks in advance.
[SendMessage is declared in the General section of the form, as follows:
Code:
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_SHOWDROPDOWN = &H14F
]
Last edited by Phantom1; Nov 22nd, 2011 at 09:10 AM.
In your click event send CB_GETDROPDOWNSTATE, if it returns non-zero (ie it's dropped down) then send the CB_SHOWDROPDOWN , 0&, 0& to close it, otherwise send the CB_SHOWDROPDOWN, 1&, 0& to open it.
That makes it so that the list will disappear when the grid is clicked. Here is a more involved method which closes it when the mouse is pressed down over the grid. The form for this code consists of a MSFlexgrid, a combobox, and a timer.
Code:
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Private Const MK_LBUTTON = &H1
Private Type POINTAPI
x As Long
y As Long
End Type
Private Function isMouseOver(Hwnd As Long) As Boolean
Dim pt As POINTAPI
GetCursorPos pt
isMouseOver = (WindowFromPoint(pt.x, pt.y) = Hwnd)
End Function
Private Sub Combo1_DropDown()
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
If isMouseOver(MSFlexGrid1.Hwnd) = True And GetAsyncKeyState(MK_LBUTTON) = -32768 Then
MSFlexGrid1.SetFocus 'This closes the combo's list and gives the grid focus
Timer1.Enabled = False
End If
End Sub
Last edited by cheesebrother; Nov 21st, 2011 at 07:24 AM.
In your click event send CB_GETDROPDOWNSTATE, if it returns non-zero (ie it's dropped down) then send the CB_SHOWDROPDOWN , 0&, 0& to close it, otherwise send the CB_SHOWDROPDOWN, 1&, 0& to open it.
What is the constant for CB_GETDROPDOWNSTATE? I mean, how to declare it? Like, for CB_SHOWDROPDOWN, it is &H14F.
Originally Posted by cheesebrother
A even simpler way of doing it would be to put this in the grid's click event:
Code:
Private Sub MSFlexGrid1_Click()
MSFlexGrid1.SetFocus
End Sub
Within the same event is the code for determining which combo box to drop down according to which column is clicked. See:
Code:
If grid.Col = 1 Then
cboPart.Visible = True
cboDescription.Visible = False
SendMessage cboPart.hwnd, CB_SHOWDROPDOWN, 1, 0&
ElseIf grid.Col = 2 Then
cboPart.Visible = False
cboDescription.Visible = True
SendMessage cboDescription.hwnd, CB_SHOWDROPDOWN, 1, 0&
End If
I have stepped through the code and I have seen that as long as the list is dropped down (always assuming that no selection is made), the grid's Click event is not activated though I click within the grid. The grid's Click event is never entered while the list is dropped down. Only if I retract the list by clicking on the arrow (still no selection is made) and then I click in the grid, e.g. in the second column, i.e. Description, only then is the grid's Click event entered and the program continues perfectly well.
It looks like while the list is dropped down, the program has all its focus on the combo box and is stuck on it. Clicking somewhere outside the grid retracts the list; but this is not what I want. One must be able to click within the grid and the list should retract even if no selection is made.
I have tried the longer code but it does not work. To what interval should the timer be set?
Last edited by Phantom1; Nov 21st, 2011 at 02:39 PM.
In your click event send CB_GETDROPDOWNSTATE, if it returns non-zero (ie it's dropped down) then send the CB_SHOWDROPDOWN , 0&, 0& to close it, otherwise send the CB_SHOWDROPDOWN, 1&, 0& to open it.
Same logic but the constant I quoted was incorrect. It should be
In the attached project, it is normal that the combo box will retract when you click outside it. Even without the long code, it does. I think the problem has to do with SendMessage being used to force the combo box list to drop down. I found the codes for SendMessage on Microsoft's web page support for this topic, but the code for retracting the dropdown does not seem to make any difference.
I have tried the CB_GETDROPPEDSTATE message but the problem is that there is no event that gets activated when I click outside the combo box (but within the grid and not outside the grid) while the list is dropped down. E.g. list is dropped down; no selection is made; click in grid while lists remains dropped down; grid's Click event is not entered.
Clicking in another grid column while the combo box list is dropped down does not activate the grid's Click event
Ok, sorry for being completely off track. The light is dawning on me . I was thinking click as in raising the grid’s click event. What you’re talking about is ACTUALLY having the grid clicked. It needs to be so that the clicked cell will select and that you can start dragging right? Events such as EnterCell and SelChange must fire as well.
…
I’ve managed to REALLY click the grid another way. Using the api “mouse_event” so everything will fire. Now I don’t need to do “MSFlexGrid1.SetFocus” because when the mouse_event simulates the click the grid is clicked, gets focus, and starts whatever operations it’s supposed to.
The code:
Code:
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Private Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
Private Const MK_LBUTTON = &H1
Private Const MOUSEEVENTF_LEFTDOWN = &H2 ' left button down
Private Type POINTAPI
x As Long
y As Long
End Type
Private Function isMouseOver(Hwnd As Long) As Boolean
Dim pt As POINTAPI
GetCursorPos pt
isMouseOver = (WindowFromPoint(pt.x, pt.y) = Hwnd)
End Function
Private Sub Combo1_DropDown()
Timer1.Enabled = True
End Sub
Private Sub Form_Load()
MSFlexGrid1.RowHeight(1) = Combo1.Height
MSFlexGrid1.ColWidth(1) = Combo1.Width
Combo1.AddItem "One"
Combo1.AddItem "Two"
Combo1.AddItem "Three"
End Sub
Private Sub MSFlexGrid1_Click()
Print "You Clicked Me!"
End Sub
Private Sub MSFlexGrid1_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
Print "MD " & x & "-" & y
End Sub
Private Sub Timer1_Timer()
If isMouseOver(MSFlexGrid1.Hwnd) = True And GetAsyncKeyState(MK_LBUTTON) = -32768 Then
Dim P As POINTAPI
GetCursorPos P
P.x = ScaleX(P.x, vbPixels, vbTwips) - (Me.Left + 60) - MSFlexGrid1.Left - 45
P.y = ScaleY(P.y, vbPixels, vbTwips) - (Me.Top + 450) - MSFlexGrid1.Top - 45
mouse_event MOUSEEVENTF_LEFTDOWN, P.x, P.y, 0, 0
Timer1.Enabled = False
End If
End Sub
If you just paste this into my previous example it should work - all the controls are the same.
I will see the new code in a minute. I have attached your project with a simple modification, relating to the problem: click in a white cell, the combo box drops down. But you cannot click in another white cell to make the combo box appear unless you retract it manually. This is the problem. You first have to retract the list, then click in another white cell, then the combo box will appear in that other cell.
Click in a cell. Combo box drops down automatically. While the dropdown list is visible, try to click in another cell. It does not work. The dropdown list remains where it is. Now, retract the list manually. Click in another cell. Combo box drops down automatically from there.
Fix to my last revision . Even though in the last one you could click another cell while the list was down another thing had been taken away. You couldn't put the list back up manually and click on another cell. This fixes that by doing a mouseup api after the mousedown. All should be in good condition for you.
Re: [RESOLVED] Cannot Retract Combo Box Dropdown List
My previous post disappeared. I was saying, thank you a lot. This is genius work . I have rated up your post. I would not have been able to get a solution if not with your help.
You worked this all by yourself? It requires good technical VB capabilities. I am quite confused about what the codes do exactly. Can you give some indications as to what happens in the timer event and in the grid's MouseUp event?
Last edited by Phantom1; Nov 22nd, 2011 at 10:13 AM.
Re: [RESOLVED] Cannot Retract Combo Box Dropdown List
I am quite confused about what the codes do exactly. Can you give some indications as to what happens in the timer event and in the grid's MouseUp event?
I'll give it a shot.
Step one is finding the correct time to close the combobox's list.
In the timer event i'm constantly checking the mouse state using
Code:
GetAsyncKeyState(MK_LBUTTON).
Another thing that i'm checking for is whether the mouse is over the grid using the isMouseOver function which is
Code:
Private Function isMouseOver(hwnd As Long) As Boolean
Dim pt As POINTAPI
GetCursorPos pt
isMouseOver = (WindowFromPoint(pt.x, pt.y) = hwnd)
End Function
So in my timer when i find that the mouse is down and that the mouse isn't over the combobox but is over the grid i know that i need to close the combo's list properly.
Step two is closing the combobox's list. This is simple accomplished by using the mouse_event api. First we need to find the exact mouse position:
Code:
Dim P As POINTAPI
GetCursorPos P
P.x = P.x - ScaleX((Me.Left + 60) - MSFlexGrid1.Left - 45, vbTwips, vbPixels)
P.y = P.y - ScaleY((Me.Top + 450) - MSFlexGrid1.Top - 45, vbTwips, vbPixels)
Then we fire the mousedown event by doing this:
Code:
mouse_event MOUSEEVENTF_LEFTUP, P.x, P.y, 0, 0
And vwala! Step2 is done.
and in the grid's MouseUp event?
another thing had been taken away. You couldn't put the list back up manually and click on another cell. This fixes that by doing a mouseup api after the mousedown.
As for that i'm as clueless as you, in fact as of this morning i didn't even know about "mouse_event". I've discovered that putting that mouseup firing code in the mouseup event fixes the problem. Without that the following will happen.
You close the combobox manually. You click on another cell, but have to click again to raise the click event.
Putting that code in the mouseup event fixes this. I guess they go in pairs mousedown and mouseup.
Re: [RESOLVED] Cannot Retract Combo Box Dropdown List
Oh and one other thing. I made a pretty bad mistake by not closing the timer when the combobox is actually clicked. It would just keep on running 1000 time a second wasting resources. The attached project has a fix to that (My code had so many errors how can you trust me ).
make it impossible again to click in another cell while the list is dropped down and no selection has been made. It does not disable the timer neither even when you make a selection from the drop down. I have tested by adding "Print Timer1.Enabled" in the combo box's Click event and it always shows True. The solution is to disable the timer in the combo box's Click event instead of adding that piece of code.
Thanks for the indications and again for your great help .
Last edited by Phantom1; Nov 23rd, 2011 at 07:55 AM.
Learning to Program on Earth until I go into Outer Space...