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
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, _
      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
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.



PayPal Link
Make payments with PayPal - it's fast, free and secure!


Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy


Hit Counter