VB6 - ComboBox Mouse Event

VB6 - ComboBox Mouse Event

Anonymous
Not applicable
2,788 Views
7 Replies
Message 1 of 8

VB6 - ComboBox Mouse Event

Anonymous
Not applicable
Does anyone know how to get a right click event out of a combobox?

Thanks in advance,

Peter
0 Likes
2,789 Views
7 Replies
Replies (7)
Message 2 of 8

Anonymous
Not applicable
If I'm reading your post correctly your asking about context menus?

Try researching some of these if so...

http://www.oreilly.com/catalog/vbshell/chapter/ch04.html

http://www.vbaccelerator.com/home/VB/Code/Controls/Menus/PopupMenu_-_Context_Menu_Demonstration/article.asp

Good luck,

Bob Coward
CADS, Inc

800-366-0946
bcoward@mindspring.com
0 Likes
Message 3 of 8

Anonymous
Not applicable
Bob,

Thanks for responding. Yes - that is my aim and I was hoping to use the same menu that I use for other controls - just figure out a way to get a mouseclick event when the cursor is on a combobox. If I'm not mistaken - from looking at these articles and searching the internet, it has something to do with retrieving the listbox and textbox sub-components of the combobox. Have you ever tried anything like this?

Regards,

Peter
0 Likes
Message 4 of 8

Anonymous
Not applicable
Peter,

Ok, I think I'm catching on. Tell me if I've got the highlights now.

Are you using VB or AutoCAD VBA, can we use VBs PopUpMenu?

Your asking this because your using a combo box has no Mouse events? Specifically; something like mousedown where your able to tell first which button was clicked and the X.Y of the event?

Of course if your using a list box you would have your mouse events that will allow you to use something simple like sending the LB_ITEMFROMPOINT message using SendMessage API. This is after you have used something like GetCursorPos and ScreenToClient.

With a combo box you will either have to implement your own type mouse event or find a work around...thus your question.

As I see this you could subclass and grab messages sent to the combo box. If you subclass you would use this function.

Public Function WindowProc(ByVal hwnd As Long, _
ByVal uMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

When using this your combo box is hwnd. The message (uMsg) you could look for might either be WM_CONTEXTMENU where you'd cancel the combo box context menu. You'd then cast your own popup either via API or VB PopUpMenu. If subclassing you could also look for the WM_LBUTTONDOWN message while hwnd is your combo box.

Without subclassing you have what I consider a greatly reduced pallet of tricks with a combo box versus list box. These I believe will be your last options:

GetComboBoxInfo function utilizing ComboBoxInfo structure might be useful for edit box handles if needed.

You could use the SendMessage API w/ CB_GETITEMDATA to verify you have a valid combo box item which could be used since mouse events not.

You could use ScreenToClient to determine if your mouse coordinates or mouse click are within the X and Y of PointAPI.

The issue I believe regardless of your solution is that your still going to have to push somthing that acts as a context menu. So a shell context menu generated with ScreenToClient while over a combo box is you you'd go.

Like to hear other opinions.

Regards,

Bob Coward
CADS, Inc

800-366-0946
bcoward@mindspring.com
0 Likes
Message 5 of 8

Anonymous
Not applicable
Bob,

Yes - that is precisely the case. I have VB6, am using a VB popup menu for listboxes and textboxes and up until now have been relying on keypress events to call the menu for the comboboxes. So - based on the start that you gave me I have patched together this code:

In Form:

Private Sub Form_Load()

Dim i As Integer
Dim cbi As COMBOBOXINFO

cbi.cbSize = Len(cbi)

Call GetComboBoxInfo(Me.Combo1.hwnd, cbi)

'gHW = cbi.hwndList
gHW = Combo1.hwnd

For i = 0 To 100
Me.Combo1.AddItem i
Next i

Hook

End Sub

Private Sub Form_Unload(Cancel As Integer)
Unhook
End Sub


in Modul:

Public Type RECT
left As Long
top As Long
right As Long
bottom As Long
End Type

Public Type COMBOBOXINFO
cbSize As Long
rcItem As RECT
rcButton As RECT
stateButton As Long
hwndCombo As Long
hwndEdit As Long
hwndList As Long
End Type

Public Declare Function GetComboBoxInfo Lib "user32.dll" (ByVal hwndCombo As Long, ByRef CBInfo As COMBOBOXINFO) As Long

Declare Function CallWindowProc Lib "user32" Alias _
"CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long

Declare Function SetWindowLong Lib "user32" Alias _
"SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Public Const GWL_WNDPROC = -4
Public Const WM_RBUTTONUP = &H205
Public IsHooked As Boolean

Global lpPrevWndProc As Long
Global gHW As Long


Public Sub Hook()
If IsHooked Then = False Then
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc)
IsHooked = True
End If
End Sub

Public Sub Unhook()
Dim temp As Long

temp = SetWindowLong(gHWText, GWL_WNDPROC, lpPrevWndProc)
IsHooked = False
End Sub

Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case uMsg
Case WM_RBUTTONUP
MsgBox "Popup"
End Select

WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)

End Function

And amazingly, it works (though I haven't actually tried it in my project yet...)

At this point my question is - it seems that I can "Hook" a single component (see Form_Load above - setting the handle of the combobox allows for right clicks when collapsed, and setting the handle of the list (hwndList ) allows when expanded - I have my lists set to Style 2 - Dropdown List so I'm not interested in the textbox portion of the combobox). How do I hook both the combobox and the combobox's list?

Additionally, the comboboxes are indexed in a control array - I'll have to test to see if I need to hook and unhook each instance, do you know if this is necessary.

At any rate, thanks for your help - I've been searching the web and haven't found all of this info together in any one place - which seems surprising given the limitations of the combobox as shipped with VB6. It seems that with .net that the combobox does have mouse events but I'm sticking it out with VB6 for now.

Regards,

Peter
0 Likes
Message 6 of 8

Anonymous
Not applicable
Peter,

I didn't know if I could go down this road while you followed. To see your able to progress is why I post these messages and I'm glad it helped.

"At this point my question is - it seems that I can "Hook" a single component"

Actualy; you can subclass the whole puppy, the entire VB world if you may. What you've done with subclassing is use a unary operator (AddressOf) that causes the address of the procedure it precedes to be passed to an API procedure that expects a function pointer at that position in the argument list.

In this case it was a combo box and from the memory address you've captured messages before they were delivered or acted on by the component.

"I have my lists set to Style 2 - Dropdown List so I'm not interested in the textbox portion of the combobox). How do I hook both the combobox and the combobox's list?"

Oh, so you've noticed that you have a text portion of your combo box and an edit portion. By setting to style 2, and subclassing, are you aware of what is happening on the message end for style and edit? Let alone the fact that everything we are talking about can be impacted by using a combo box or using you own custom drawn control...messages cast differently between these pups also.

The reason I ask is that you've now gotten to where I think I'll leave you. The reason is that you need to look at the different messages you want to work with.

i.e.: Your catching WM_RBUTTONUP which is a mouse input or user input message. This does not directly relate to a message implicit to your combo box. If you use messages that are only going to be cast when working with a combo box you might get better results.

Messages from combo boxes are stored in the high word of the wParam parameter, which you've noticed. CBN_DROPDOWN message is sent when the list box of the combo box is about to be made visible and this notification message is only sent if the combo box has the CBS_DROPDOWN or CBS_DROPDOWNLIST style which you have. Or you could go for CB_GETITEMDATA if your context menu must relate to a specific combo box index item. Or better yet , since you want a popup similar to a context menu, cancel the default combo box context menu, eat the windows process, and post your own popup.

Try this....

Post this in your declaration section

Public Const WM_CONTEXTMENU As Long = &H7B
Public hwndEdit As Long

Change your Select Case uMsg to allow for:

and oh yeah..."How do I hook both the combobox and the combobox's list?" We'll answer that one here also.

'only if the handle is that of the edit control in the Combo...

If hwnd = hwndEdit Then

'watch for the context menu message
Select Case uMsg
Case WM_CONTEXTMENU

' Push your own context popup
Form1.PopupMenu Form1.mnuPopup
'eat the message
' WindowProc = 0

Case Else

'not the message of interest,
'so process normally
WindowProc = CallWindowProc(defWndProc, _
hwnd, _
uMsg, _
wParam, _
lParam)
End Select

End If

I hope you can see why I'm going to leave you hanging here. I believe it is now time to go forth and study everything that relates to message broadcasts via WM_COMMAND.

I hope this helps though, researching this did help me answer how to circumvent an option button click event which has bugged me for a couple years.....thanks in turn.

Regards,

Bob Coward
CADS, Inc

800-366-0946
bcoward@mindspring.com
0 Likes
Message 7 of 8

Anonymous
Not applicable
Bob,

Why are there no simple answers for difficult questions? I guess that dealing with a program's idiosyncrasies will ultimately push you to the next level of knowledge - and I gotta make that push now. Thank you for both your help and the limit that you set on providing easy answers -
I'll keep any progress posted.

Peter
0 Likes
Message 8 of 8

Anonymous
Not applicable
Peter,

"Why are there no simple answers for difficult questions?"

That's VB and VBA. Just think event driven and you know there's something missing.

If you've taken time to understand a real language like C++ or other then the toys we use everyday can become easy to interpret. I've learned more about what VB could be by starting my reference for an API or structure with the C++ header files. There are many APIs and other goodies not disclosed by the VB API Viewer and translating the header files has been invaluable, not to mention the undocumented features your able to uncover. I've also found this is an easier way to identify what structures and constants I "could" be using to make life simple without searching MSDN until dawn.

Good luck,

Bob
0 Likes