很早时候就注意到Application的AddMessageFilter,苦于自己基础差,测试不出好结果来。今天看贴,有人想屏蔽Form上凡TextBox的右键消息,于是重新看了看这个话题。只是还是没有得出什么好效果来,只能将就着实现。
Application.AddMessageFilter主要的功能是添加消息筛选器以便在向目标传送 Windows 消息时监视这些消息。
(哎,本来想按自己的理解说这些含义的,怕误人了,受骂也多了,汲取教训,还是照贴MSDN的原字吧。可怜的我,本来就不是专业人士,也只能是入俗,僧不僧俗不俗的,乡巴佬戴领带入城,可怜哪。)
注意:向应用程序的消息泵添加消息筛选器会降低性能。(警告之类的我是一般不管的,有用就用,管它)
使用Application.AddMessageFilter与一般的方法调用不一样,它的参数Message有这样的要求:若要防止调度某消息,传递给该方法的 value 参数实例必须用处理该消息的代码重写 PreFilterMessage 方法。该方法必须返回 false。
以屏蔽Form上凡TextBox的右键消息为例,下面交待一下主要做法。
一、实现ImessageFilter接口。如下。
为什么做了个传递Form的属性,只要是用来判断当前控件是不是TextBox用的。这种效果并不理想,需要改进。本来是不需要引进这个属性的,用Message.GetLParam方法就可以得知当前消息的对象是不是TextBox,可怜我不知道那个Structure该如何写,若是你给我贴出来补正,小人感激不尽。
Public Class TextBoxRButtonMessageFilter
Implements System.Windows.Forms.IMessageFilter
Const WM_RBUTTONDOWN As Integer = &H204
Const WM_RBUTTONUP As Integer = &H205
Private m_Form As System.Windows.Forms.Form
Public WriteOnly Property [Form]() As System.Windows.Forms.Form
Set(ByVal Value As System.Windows.Forms.Form)
m_Form = Value
End Set
End Property
Public Function RButtonFilterMessage(ByRef m As System.Windows.Forms.Message)
As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
If (m.Msg = WM_RBUTTONDOWN OrElse m.Msg = WM_RBUTTONUP) AndAlso m_Form.ActiveControl.GetType.Name.Equals("TextBox") Then
Return True
Else
Return False
End If
End Function
End Class
二、向应用程序的消息泵添加消息筛选器。
#Region " Windows 窗体设计器生成的代码 "
Public Sub New()
MyBase.New()
'该调用是 Windows 窗体设计器所必需的。
InitializeComponent()
'在 InitializeComponent() 调用之后添加任何初始化
mMsgFilter.Form = Me
System.Windows.Forms.Application.AddMessageFilter(mMsgFilter)
End Sub
……
#End Region
Private mMsgFilter As New TextBoxRButtonMessageFilter
就这么简单。问题是怎么使用Message.GetLParam的,请指教。
三、以下用Handle来代替ActiveControl
#Region " Windows 窗体设计器生成的代码 "
Public Sub New()
MyBase.New()
'该调用是 Windows 窗体设计器所必需的。
InitializeComponent()
'在 InitializeComponent() 调用之后添加任何初始化
MsgFilterInit()
End Sub
.......
#End Region
Private mMsgFilter As New TextBoxRButtonMessageFilter
Private Sub MsgFilterInit()
Dim ctr As System.Windows.Forms.Control
For Each ctr In Me.Controls
If TypeOf ctr Is TextBox Then
mMsgFilter.SetFilterHandles(ctr.Handle)
End If
Next
System.Windows.Forms.Application.AddMessageFilter(mMsgFilter)
End Sub
End Class
Public Class TextBoxRButtonMessageFilter
Implements System.Windows.Forms.IMessageFilter
Const WM_RBUTTONDOWN As Integer = &H204
Const WM_RBUTTONUP As Integer = &H205
Private m_HWnds As New Hashtable
Public Sub SetFilterHandles(ByVal mHWnd As IntPtr)
m_HWnds.Add(mHWnd, Nothing)
End Sub
Public Function RButtonFilterMessage(ByRef m As System.Windows.Forms.Message) _
As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
If (m.Msg = WM_RBUTTONDOWN OrElse m.Msg = WM_RBUTTONUP) AndAlso m_HWnds.Contains(m.HWnd) Then
Return True
Else
Return False
End If
End Function
End Class