|
|
![]() |
|
||
|
|
|||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||
| Visual Basic Subclassing Routines WM_CONTEXTMENU: Kill the Default Combo Box Context Menu |
||
| Posted: | Tuesday December 19, 2000 | |
| Updated: | Monday December 26, 2011 | |
| Applies to: | VB5, VB6 | |
| Developed with: | VB6, Windows 2000 | |
| OS restrictions: | None | |
| Author: | VBnet - Randy Birch | |
| Related: | WM_CONTEXTMENU: Kill the Default Text Box Context Menu SendMessage: Make a Style-0 Combo Edit Read-Only FindWindowEx: Obtain Combo Box Edit Window Handle GetComboBoxInfo: Obtain Combo Box Edit and List Handles on Win98/NT5 |
|
| Prerequisites |
| VB5 or VB6. |
|
|
Here
is the technique for suppressing the default context menu of a style-0 combo box, or for showing a user-defined menu in its place.
For this to work we have to borrow from the combo method that deals with retrieving the handle to the edit portion of the control (see related topics above). The edit handle is stored, where it is compared to the hWnd passed by the WindowProc procedure. If the handle is that of the edit control, the message passed is checked for WM_CONTEXTMENU, and if present, the function either eats the message or displays an alternate PopupMenu in its place. |
| BAS Module Code |
|
|
| Place the following code into the general declarations area of a bas module: |
|
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Const GWL_WNDPROC As Long = -4
Public Const WM_CONTEXTMENU As Long = &H7B
Public defWndProc As Long
'used to hold the handle to the combo's edit window
Public hwndEdit As Long
Public 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
Public Declare Function SetWindowLong Lib "user32" _
Alias "SetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Public Declare Function FindWindowEx Lib "user32" _
Alias "FindWindowExA" _
(ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
Public Sub Hook(hwnd As Long)
If defWndProc = 0 Then
defWndProc = SetWindowLong(hwnd, _
GWL_WNDPROC, _
AddressOf WindowProc)
End If
End Sub
Public Sub UnHook(hwnd As Long)
If defWndProc > 0 Then
Call SetWindowLong(hwnd, GWL_WNDPROC, defWndProc)
defWndProc = 0
End If
End Sub
Public Function WindowProc(ByVal hwnd As Long, _
ByVal uMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
'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
'eat the message -- no popup menu appears
WindowProc = 0
'alternatively, comment out the above, and
'uncomment below to show your own menu (make
'sure the correct menu name is specified)
' Form1.PopupMenu Form1.mnuPopup
' WindowProc = 0
Case Else
'not the message of interest,
'so process normally
WindowProc = CallWindowProc(defWndProc, _
hwnd, _
uMsg, _
wParam, _
lParam)
End Select
End If
End Function |
| Form Code |
|
|
| To a form add three command buttons in a control array to
the form (Command1(0) - Command1(2)), along with a combo box (Combo1).
To test the user-defined PopupMenu in place of the default menu, add a top level menu (mnuPopup) with any number of submenu items under it (using any names). Finally, add the following code: |
|
|
Option Explicit
Private Sub Form_Load()
With Combo1
.AddItem "Item A"
.AddItem "Item B"
.AddItem "Item C"
End With
'enable button to hook
Command1(0).Enabled = True
Command1(1).Enabled = False
Command1(0).Caption = "Hook"
Command1(1).Caption = "UnHook"
Command1(2).Caption = "End"
Combo1.Text = "Edit is Unhooked"
End Sub
Private Sub Form_Unload(Cancel As Integer)
'just in case, call the unhook method
Call UnHook(hwndEdit)
End Sub
Private Sub Command1_Click(Index As Integer)
Select Case Index
Case 0:
'get the handle to the edit portion
'of the combo control
hwndEdit = FindWindowEx(Combo1.hwnd, 0&, vbNullString, vbNullString)
If hwndEdit <> 0 Then
'show that the handle was obtained and hook
Combo1.Text = "Hooked: edit handle is " & CStr(hwndEdit)
Call Hook(hwndEdit)
'disable button so can't hook again
Command1(0).Enabled = False
Command1(1).Enabled = True
End If
Case 1:
If hwndEdit <> 0 Then
Call UnHook(hwndEdit)
Combo1.Text = "Edit is Unhooked"
'enable button to hook
Command1(0).Enabled = True
Command1(1).Enabled = False
End If
Case 2: Unload Me
End Select
End Sub |
| Comments |
| Save then run the project. Running using the Full Compile
option is recommended when creating or changing the form, as once the form becomes subclassed you can't edit the code should an error occur.
Once running, right-click the combo. If the Hook button has not been pressed, you will see the default edit context menu. After pressing Hook the default menu is suppressed (no menu appears), and, if you defined a PopupMenu and uncommented the code above, the defined menu appears in its place. |
|
|
|
|
|
|||||
|
|||||
|
|
|||||
|
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |
![]() |