As any Windows user knows, when you right-click over
the textbox, a helpful menu pops up. Since Windows 95 came out on the
market, there have been a lot of whacky code written on how to get rid of the
context menu. First there were convoluted solutions based on disabling the
textbox in the MouseDown down event. Then the next generation of code used
third-party components such as MessageHook OCX from Mabry to try and catch the
message. Yet other code tries to catch WM_RBUTTONUP, thus disabling
mouse event handling for right button click. Here is how to do the
right way using VB code only. As one may have guessed it involves
subclassing and catching the WM_CONTEXTMENU menu.
Warning: never end programs that use AddressOf operator by pressing the End button on
the VB toolbar. End the program by clicking the X (close) button on the form.
This project is also available as a download
.
| Project Creation Instructions. |
- Createa new
project.
- Add a textbox to
Form1.
- Add 2 command buttons: call the first one btnHook, set
its caption to 'Disable Right Click'. Call the second one btnUnhook and
set its caption to 'Enable Right
Click'
- Add a checkbox - call it chkCustomMenu and set its
caption to 'Show Custom Menu'
- Add a top level menu item called mnuCustom and add to it a bunch of
sub menus.
- Add a module to the project.
| Add the following to a .BAS module |
Option Explicit
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
Private Const GWL_WNDPROC = -4
Private IsHooked As Boolean
Private lpPrevWndProc As Long
Private Const WM_CONTEXTMENU = &H7B
Public ShowCustomMenu As Boolean
Public TextHandle As Long
Public Sub Hook()
If IsHooked Then
MsgBox "You are already hooked for this handle."
Else
'this tells windows to send all the messages that
'are intended for this form to sub WindowProc
lpPrevWndProc = SetWindowLong(TextHandle, GWL_WNDPROC, _
AddressOf WindowProc)
IsHooked = True
End If
End Sub
Public Sub Unhook()
Dim temp As Long
If IsHooked Then
'this tells windows to send all the messages that
'are intended for this form to sub WindowProc
temp = SetWindowLong(TextHandle, GWL_WNDPROC, lpPrevWndProc)
IsHooked = False
End If
End Sub
Function WindowProc(ByVal hw As Long, ByVal uMsg As _
Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = WM_CONTEXTMENU Then
If ShowCustomMenu Then Form1.PopupMenu Form1.mnuCustom
Debug.Print "Default Right click prevented"
Else
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
End If
End Function
| Add the following code to Form1 |
Option Explicit
Private Sub ToggleControls(flag As Boolean)
btnHook.Enabled = flag
btnUnhook.Enabled = Not flag
chkCustomMenu.Enabled = Not flag
End Sub
Private Sub btnHook_Click()
'start subclassing
Hook
ToggleControls False
End Sub
Private Sub btnUnhook_Click()
'end subclassing
Unhook
ToggleControls True
End Sub
Private Sub chkCustomMenu_Click()
ShowCustomMenu = IIf(chkCustomMenu.Value = vbChecked, True, False)
End Sub
Private Sub Form_Load()
'record the name of the textbox we want to manipulate
TextHandle = Me.Text1.hwnd
ToggleControls True
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
'end subclassing
Unhook
End Sub
Now run the project. Click on 'Disable Right-Click'. Try to right-click on the textbox. Now set the Checkbox to on and try to right-click.
P.S. Thanks to Carl Bateman for pointing
out an error in this article.