Windows是以消息驱动的操作系统,Windows 消息提供了应用程序与应用程序以及应用程序和Windows系统之间进行通讯的手段。在VB中的控件已经对Windows的消息做了很好的封装,可以很方便的进行系统的消息处理,比如对Button按钮的鼠标单击消息只要在相应的Click事件中添加处理代码即可。可是VB中也存在一些没有封装的消息,比如在Text控件的右键单击消息,默认的在Text控件的右键单击会出来一个系统的菜单,如何能屏蔽掉系统的那个菜单,而换成自己定义的菜单呢?这就需要拦截并修改系统的消息。
  拦截并修改系统的消息的原理:要先取得原先Window Procedure所在的地址,将之记录下来,接着设定所有的消息都先转到我们自己处理的消息处理过程上来,我们过滤传过来的消息,寻找特定的消息进行处理。下面就以修改Text控件的右键单击消息为例介绍具体的程序设计。
  在VB中创建一个新的工程,给窗体命名为Msgfrm,并在窗体中添加TextBox控件Msgtxt,此时运行工程,在Msgtxt中点击鼠标右键,会弹出一个系统菜单,如右图。如果需要在Msgtxt中点击鼠标右键时不出现系统的菜单,而是出现开发者自己定义的菜单如左图。这是就需要用代码屏蔽系统的消息,并修改为自己可以控制代码的消息事件。具体实现如下:   
在工程中添加模块Msgmdl,并在模块中定义常量和函数如下:Public Const GWL_WNDPROC = (-4) '
Public Const WM_RBUTTONDOWN = &H204
Public Const WM_LBUTTONDOWN = &H201
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 GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex 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 prevWndProc As Long
Public rightbutton As Integer定义Window Procedure函数处理过程,截取鼠标右键单击的消息,并修改系统消息为鼠标左键单击的消息,并以rightbutton=2作为标记。
Function WndProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
On Error Resume Next
If Msg = WM_RBUTTONDOWN Then
rightbutton = 2
Msg = WM_LBUTTONDOWN
End If
WndProc = CallWindowProc(prevWndProc, hWnd, Msg, wParam, lParam)
End Function
在窗体Msgfrm的Load事件中添加代码
prevWndProc = GetWindowLong(Msgtxt.hWnd, GWL_WNDPROC)
SetWindowLong Msgtxt.hWnd, GWL_WNDPROC, AddressOf WndProc
取得原先Window Procedure所在的地址,将之记录下来,接着设定所有的消息都先转到我们自己处理的消息处理过程上来。
在窗体Msgfrm中定义菜单msgmen,包含背景、字体、全选、删除、取消。背景子菜单中代码:Dim color As Double
CommonDialog1.Flags = 0
On Error Resume Next
Err.Clear
CommonDialog1.ShowColor
Msgtxt.BackColor = CommonDialog1.color
字体子菜单中代码:CommonDialog1.ShowFont
If CommonDialog1.FontName <> "" Then
Msgtxt.FontName = CommonDialog1.FontName
End If
Msgtxt.FontSize = CommonDialog1.FontSize
全选子菜单中代码:Msgtxt.SelStart = 0
Msgtxt.SelLength = Len(Msgtxt)
删除子菜单中代码:Msgtxt.Text = ""
取消子菜单中代码:Exit Sub最后在Msgtxt的MouseDown事件中添加代码:
If rightbutton = 2 Then
PopupMenu msgmen
End If
处理修改来的消息的菜单弹出。