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