关于IMessageFilter,控件或窗体消息

时间:2021-01-01 18:25:01
控件或窗体消息

有关IMessageFilter的文档说明:

IMessageFilter 接口 
定义消息筛选器接口。

命名空间:  System.Windows.Forms
程序集:  System.Windows.Forms(在 System.Windows.Forms.dll 中)

此接口允许应用程序在消息被调度到控件或窗体之前捕获它。

IMessageFilter.PreFilterMessage 方法 
使用 PreFilterMessage 在消息被调度到控件或窗体之前将其筛选出来
如果筛选消息并禁止消息被调度,则为 true;如果允许消息继续到达下一个筛选器或控件,则为 false。


可以将实现 IMessageFilter 接口的类添加到应用程序的消息泵中,以在消息被调度到控件或窗体之前将它筛选出来或执行其他操作。若要将消息筛选器添加到应用程序的消息泵中,请使用 Application 类中的 AddMessageFilter 方法;当您不再需要在调度 Windows 消息之前捕获这些消息时,可以使用RemoveMessageFilter方法移除消息筛选器。

代码下载: RAR文件,2005

43 个解决方案

#1



可以不用关心“筛选”两字,只利用PreFilterMessage监视窗体消息,对消息进行分析。
这些消息局限于当前程序域内。

如要获取非当前程序域窗体消息,需要实现有关Windows钩子.

#2



对窗体消息Message,
Dim m As Message
m.HWnd为窗体句柄。

通过
Dim Ctr As Control = Control.FromHandle(m.HWnd)
取得句柄窗体或控件实例。

#3



如果对消息感兴趣,不妨简化一下IMessageFilter的实现过程。

IFilterAction.vb
Namespace LzmTW.MessageFilter
    Public Interface IFilterAction
        Sub Add()
        Sub Remove()
    End Interface
End Namespace


FilterAction.vb
Namespace LzmTW.MessageFilter

    Friend Class FilterAction
        Implements IMessageFilter, IFilterAction

        Private Action As MessageFilterAction

        Friend Sub New()
        End Sub

        Friend Sub Add(ByVal action As MessageFilterAction)
            Me.Action = action
        End Sub

        Private Function PreFilterMessage(ByRef m As Message) As Boolean _
        Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
            Return Me.Action.Invoke(m)
        End Function

        Public Sub Add() Implements IFilterAction.Add
            Application.AddMessageFilter(Me)
        End Sub

        Public Sub Remove() Implements IFilterAction.Remove
            Application.RemoveMessageFilter(Me)
        End Sub

        Public Shared Function Instance(ByVal acton As MessageFilterAction) As IFilterAction
            Dim filter As New FilterAction
            filter.Add(acton)

            Return filter
        End Function
    End Class

End Namespace

注意这个类的定义修饰,为Friend.


简单的使用方法:
FilterHelper.vb
Namespace LzmTW.MessageFilter
    Public Class FilterHelper
        Private Sub New()
        End Sub

        Public Shared Function Instance(ByVal acton As MessageFilterAction) As IFilterAction
            Return FilterAction.Instance(acton)
        End Function

    End Class

End Namespace

#4


本帖最后由 lzmtw 于 2008-04-21 10:29:45 编辑
MessageFilterAction的定义

Delegate.vb
Namespace LzmTW.MessageFilter
    Public Delegate Function MessageFilterAction(ByVal m As Message) As Boolean
End Namespace

#5



示例一:

Public Class Form1

    Private gFilter As LzmTW.MessageFilter.IFilterAction

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If Not gFilter Is Nothing Then Return

        gFilter = LzmTW.MessageFilter.FilterHelper.Instance(AddressOf MessageWatcher)

        gFilter.Add() '添加到Application并发生作用
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        gFilter.Remove() '从Application中移除
    End Sub

    Private Function MessageWatcher(ByVal m As Message) As Boolean
        Console.WriteLine(m.ToString)

        Return False '对消息不筛选。如为Return Ture,那么所有的窗体消息都筛选掉,窗体不作任何反应,"死"了。
    End Function
End Class

#6



修改MessageWatcher,当你移动鼠标或按Tab键时,下面会提示出消息所捕获的当前控件(Form也是控件,控件就是窗体).
    Private Function MessageWatcher(ByVal m As Message) As Boolean
        Dim ctr As Control = Control.FromHandle(m.HWnd)

        If ctr Is Nothing Then Return False

        Console.WriteLine(ctr.ToString)

        Return False 
    End Function

#7



窗体消息有很多,可以通过m.Msg进行筛选.
    Private Const WM_KEYUP As Integer = &H101
    Private Const WM_MOUSEHOVER As Integer = &H2A1

    Private Function MessageWatcher(ByVal m As Message) As Boolean
        Select Case m.Msg

            Case WM_KEYUP, WM_MOUSEHOVER
                Dim ctr As Control = Control.FromHandle(m.HWnd)

                If ctr Is Nothing Then Return False

                Console.WriteLine(ctr.ToString)
            Case Else

        End Select

        Return False
    End Function

#8


说真的,水兄。这个。不知道你在说什么。我想。你如果可能,最好先说明类的功能,我耐心的读完了帖子。知道你是封装了一个类,简化了实现IMessageFilter的。

#9



整理一下示例一:当移动鼠标或选择控件时,即时显示当前鼠标下面或当前控件的名称

Public Class Form1

    Private gFilter As LzmTW.MessageFilter.IFilterAction

    Private Const WM_KEYUP As Integer = &H101
    Private Const WM_MOUSEHOVER As Integer = &H2A1

    Private Function MessageWatcher(ByVal m As Message) As Boolean
        Select Case m.Msg

            Case WM_KEYUP, WM_MOUSEHOVER
                Dim ctr As Control = Control.FromHandle(m.HWnd)

                If Not ctr Is Nothing Then Me.Text = "this is " & ctr.Name
            Case Else
        End Select

        Return False
    End Function

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        gFilter = LzmTW.MessageFilter.FilterHelper.Instance(AddressOf MessageWatcher)

        gFilter.Add()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) _
    Handles Me.FormClosing
        gFilter.Remove()
    End Sub
End Class

#10


引用 8 楼 KissXYL 的回复:
说真的,水兄。这个。不知道你在说什么。我想。你如果可能,最好先说明类的功能,我耐心的读完了帖子。知道你是封装了一个类,简化了实现IMessageFilter的。


我尝试说明怎么使用这个类,通过这个类可以做点什么.

#11


还有。。。
帖子刚发出来就加了精……
是不是太早了。怎么也要多几个回复后再啊。

#12


关于加精,是我自己给自己加精。我习惯啦。

加精的理由,对我自己的贴子来说,不在于回复,而在于过程。


这贴子会比较长。

#13


如果我发个这样的帖子。你会不会一开始就加精呢。所谓执法要公正,流程上。并不能因为你是版主就先加精再把帖子变成精华。当然我不否认你的帖子写的很好。但总有老王卖瓜之嫌。并有执法不公之嫌。

#14


引用 13 楼 KissXYL 的回复:
如果我发个这样的帖子。你会不会一开始就加精呢。所谓执法要公正,流程上。并不能因为你是版主就先加精再把帖子变成精华。当然我不否认你的帖子写的很好。但总有老王卖瓜之嫌。并有执法不公之嫌。


如果你跟我说,你想就某个问题写一个贴子,详细的将你的理解和解决的过程写出来,我肯定的先给你的贴子加精。我也热烈欢迎多多益善。
你以为我总给自己的贴子加精我很开心哪?

至于卖瓜之嫌,不公之嫌,这是你的看法,我不解释。

#15


窗体消息的种类有哪些?


WindowMessage.vb
Namespace LzmTW.MessageFilter

    Public Enum WindowMessage
        WM_NULL = &H0
        WM_CREATE = &H1
        WM_DESTROY = &H2
        WM_MOVE = &H3
        WM_SIZE = &H5
        WM_ACTIVATE = &H6
        WM_SETFOCUS = &H7
        WM_KILLFOCUS = &H8
        WM_ENABLE = &HA
        WM_SETREDRAW = &HB
        WM_SETTEXT = &HC
        WM_GETTEXT = &HD
        WM_GETTEXTLENGTH = &HE
        WM_PAINT = &HF
        WM_CLOSE = &H10
        WM_QUERYENDSESSION = &H11
        WM_QUIT = &H12
        WM_QUERYOPEN = &H13
        WM_ERASEBKGND = &H14
        WM_SYSCOLORCHANGE = &H15
        WM_ENDSESSION = &H16
        WM_SHOWWINDOW = &H18
        WM_CTLCOLOR = &H19
        WM_WININICHANGE = &H1A
        WM_DEVMODECHANGE = &H1B
        WM_ACTIVATEAPP = &H1C
        WM_FONTCHANGE = &H1D
        WM_TIMECHANGE = &H1E
        WM_CANCELMODE = &H1F
        WM_SETCURSOR = &H20
        WM_MOUSEACTIVATE = &H21
        WM_CHILDACTIVATE = &H22
        WM_QUEUESYNC = &H23
        WM_GETMINMAXINFO = &H24
        WM_PAINTICON = &H26
        WM_ICONERASEBKGND = &H27
        WM_NEXTDLGCTL = &H28
        WM_SPOOLERSTATUS = &H2A
        WM_DRAWITEM = &H2B
        WM_MEASUREITEM = &H2C
        WM_DELETEITEM = &H2D
        WM_VKEYTOITEM = &H2E
        WM_CHARTOITEM = &H2F
        WM_SETFONT = &H30
        WM_GETFONT = &H31
        WM_SETHOTKEY = &H32
        WM_GETHOTKEY = &H33
        WM_QUERYDRAGICON = &H37
        WM_COMPAREITEM = &H39
        WM_GETOBJECT = &H3D
        WM_COMPACTING = &H41
        WM_COMMNOTIFY = &H44
        WM_WINDOWPOSCHANGING = &H46
        WM_WINDOWPOSCHANGED = &H47
        WM_POWER = &H48
        WM_COPYDATA = &H4A
        WM_CANCELJOURNAL = &H4B
        WM_NOTIFY = &H4E
        WM_INPUTLANGCHANGEREQUEST = &H50
        WM_INPUTLANGCHANGE = &H51
        WM_TCARD = &H52
        WM_HELP = &H53
        WM_USERCHANGED = &H54
        WM_NOTIFYFORMAT = &H55
        WM_CONTEXTMENU = &H7B
        WM_STYLECHANGING = &H7C
        WM_STYLECHANGED = &H7D
        WM_DISPLAYCHANGE = &H7E
        WM_GETICON = &H7F
        WM_SETICON = &H80
        WM_NCCREATE = &H81
        WM_NCDESTROY = &H82
        WM_NCCALCSIZE = &H83
        WM_NCHITTEST = &H84
        WM_NCPAINT = &H85
        WM_NCACTIVATE = &H86
        WM_GETDLGCODE = &H87
        WM_NCMOUSEMOVE = &HA0
        WM_NCLBUTTONDOWN = &HA1
        WM_NCLBUTTONUP = &HA2
        WM_NCLBUTTONDBLCLK = &HA3
        WM_NCRBUTTONDOWN = &HA4
        WM_NCRBUTTONUP = &HA5
        WM_NCRBUTTONDBLCLK = &HA6
        WM_NCMBUTTONDOWN = &HA7
        WM_NCMBUTTONUP = &HA8
        WM_NCMBUTTONDBLCLK = &HA9
        WM_KEYDOWN = &H100
        WM_KEYUP = &H101
        WM_CHAR = &H102
        WM_DEADCHAR = &H103
        WM_SYSKEYDOWN = &H104
        WM_SYSKEYUP = &H105
        WM_SYSCHAR = &H106
        WM_SYSDEADCHAR = &H107
        WM_KEYLAST = &H108
        WM_IME_STARTCOMPOSITION = &H10D
        WM_IME_ENDCOMPOSITION = &H10E
        WM_IME_COMPOSITION = &H10F
        WM_INITDIALOG = &H110
        WM_COMMAND = &H111
        WM_SYSCOMMAND = &H112
        WM_TIMER = &H113
        WM_HSCROLL = &H114
        WM_VSCROLL = &H115
        WM_INITMENU = &H116
        WM_INITMENUPOPUP = &H117
        WM_MENUSELECT = &H11F
        WM_MENUCHAR = &H120
        WM_ENTERIDLE = &H121
        WM_CTLCOLORMSGBOX = &H132
        WM_CTLCOLOREDIT = &H133
        WM_CTLCOLORLISTBOX = &H134
        WM_CTLCOLORBTN = &H135
        WM_CTLCOLORDLG = &H136
        WM_CTLCOLORSCROLLBAR = &H137
        WM_CTLCOLORSTATIC = &H138
        WM_MOUSEMOVE = &H200
        WM_LBUTTONDOWN = &H201
        WM_LBUTTONUP = &H202
        WM_LBUTTONDBLCLK = &H203
        WM_RBUTTONDOWN = &H204
        WM_RBUTTONUP = &H205
        WM_RBUTTONDBLCLK = &H206
        WM_MBUTTONDOWN = &H207
        WM_MBUTTONUP = &H208
        WM_MBUTTONDBLCLK = &H209
        WM_MOUSEWHEEL = &H20A
        WM_PARENTNOTIFY = &H210
        WM_ENTERMENULOOP = &H211
        WM_EXITMENULOOP = &H212
        WM_NEXTMENU = &H213
        WM_SIZING = &H214
        WM_CAPTURECHANGED = &H215
        WM_MOVING = &H216
        WM_POWERBROADCAST = &H218
        WM_DEVICECHANGE = &H219
        WM_MDICREATE = &H220
        WM_MDIDESTROY = &H221
        WM_MDIACTIVATE = &H222
        WM_MDIRESTORE = &H223
        WM_MDINEXT = &H224
        WM_MDIMAXIMIZE = &H225
        WM_MDITILE = &H226
        WM_MDICASCADE = &H227
        WM_MDIICONARRANGE = &H228
        WM_MDIGETACTIVE = &H229
        WM_MDISETMENU = &H230
        WM_ENTERSIZEMOVE = &H231
        WM_EXITSIZEMOVE = &H232
        WM_DROPFILES = &H233
        WM_MDIREFRESHMENU = &H234
        WM_IME_SETCONTEXT = &H281
        WM_IME_NOTIFY = &H282
        WM_IME_CONTROL = &H283
        WM_IME_COMPOSITIONFULL = &H284
        WM_IME_SELECT = &H285
        WM_IME_CHAR = &H286
        WM_IME_KEYDOWN = &H290
        WM_IME_KEYUP = &H291
        WM_MOUSEHOVER = &H2A1
        WM_MOUSELEAVE = &H2A3
        WM_CUT = &H300
        WM_COPY = &H301
        WM_PASTE = &H302
        WM_CLEAR = &H303
        WM_UNDO = &H304
        WM_RENDERFORMAT = &H305
        WM_RENDERALLFORMATS = &H306
        WM_DESTROYCLIPBOARD = &H307
        WM_DRAWCLIPBOARD = &H308
        WM_PAINTCLIPBOARD = &H309
        WM_VSCROLLCLIPBOARD = &H30A
        WM_SIZECLIPBOARD = &H30B
        WM_ASKCBFORMATNAME = &H30C
        WM_CHANGECBCHAIN = &H30D
        WM_HSCROLLCLIPBOARD = &H30E
        WM_QUERYNEWPALETTE = &H30F
        WM_PALETTEISCHANGING = &H310
        WM_PALETTECHANGED = &H311
        WM_HOTKEY = &H312
        WM_PRINT = &H317
        WM_PRINTCLIENT = &H318
        WM_HANDHELDFIRST = &H358
        WM_HANDHELDLAST = &H35F
        WM_AFXFIRST = &H360
        WM_AFXLAST = &H37F
        WM_PENWINFIRST = &H380
        WM_PENWINLAST = &H38F
    End Enum

End Namespace

#16


学习了。
谢谢...

但是用这个封装后的类有什么好处?

在分析下与WinPro的功能差异就更好了

#17


本帖最后由 lzmtw 于 2008-04-21 19:51:17 编辑
现在,写个在当前程序域中监视窗体实例的类

为方便起见

FilterItemBase.vb
Namespace LzmTW.MessageFilter

    Public MustInherit Class FilterItemBase
        Implements IFilterAction

        Private filter As IFilterAction

        Protected MustOverride Function Action(ByVal m As Message) As Boolean

        Sub New()
            filter = FilterAction.Instance(AddressOf Action)
        End Sub

        Public Sub Add() Implements IFilterAction.Add
            filter.Add()
        End Sub

        Public Sub Remove() Implements IFilterAction.Remove
            filter.Remove()
        End Sub
    End Class

End Namespace

#18


示例二:窗体实例监视类(f.Show过有效)

Public Class FormWatcher
    Inherits LzmTW.MessageFilter.FilterItemBase

    Private gForms As New List(Of Form)

    Public ReadOnly Property Count() As Integer
        Get
            Return Forms.Length
        End Get
    End Property

    Public ReadOnly Property Forms() As Form()
        Get
            Check()
            Return gForms.ToArray
        End Get
    End Property

    Public Function FindForm(ByVal text As String) As Form()
        Dim array As New List(Of Form)

        For Each f As Form In Me.Forms
            If String.Compare(f.Text, text, True) = 0 Then
                array.Add(f)
            End If
        Next

        Return array.ToArray
    End Function

    Public Function FindForm(ByVal t As Type) As Form()
        Dim array As New List(Of Form)

        For Each f As Form In Me.Forms
            If f.GetType Is t Then
                array.Add(f)
            End If
        Next

        Return array.ToArray
    End Function


    Private Sub Check()
        For i As Integer = gForms.Count - 1 To 0 Step -1
            Dim f As Form = gForms(i)
            If f Is Nothing OrElse f.IsDisposed Then
                gForms.Remove(f)
            End If
        Next
    End Sub

    Protected Overrides Function Action(ByVal m As System.Windows.Forms.Message) As Boolean
        Dim ctr As Control = Control.FromHandle(m.HWnd)

        If ctr Is Nothing Then Return False

        If Not TypeOf ctr Is Form Then Return False



        Dim f As Form = CType(ctr, Form)

        If f.IsDisposed Then
            If gForms.Contains(f) Then
                gForms.Remove(f)
            End If
        Else
            If Not gForms.Contains(f) Then
                gForms.Add(f)
            End If
        End If

        Return False
    End Function
End Class

#19


使用:
Public Class Form1

    Private Watcher As FormWatcher



    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Watcher = New FormWatcher

        Watcher.Add()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) _
    Handles Me.FormClosing
        Watcher.Remove()
    End Sub


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim f As New Form
        f.Text = "aaaa"
        f.Show()
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim f As New Form2
        f.Show()
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Console.WriteLine(Watcher.Count)
        For Each f As Form In Watcher.Forms
            Console.WriteLine(f.Text)
        Next
    End Sub

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        Dim array As Form() = Watcher.FindForm("aaaa")
        If array.Length > 0 Then
            Console.WriteLine(array(0).Text)
        End If
    End Sub

    Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
        Dim array As Form() = Watcher.FindForm(GetType(Form2))
        If array.Length > 0 Then
            Console.WriteLine(array(0).Text)
        End If
    End Sub
End Class

#20


#21


扩充一下示例一,用下面的代码实现如图的效果(菜单用键盘选取时无效)

示例代码:
Public Class Form1

    Private WithEvents ControlsWatcher As New LzmTW.MessageFilter.Apply.ControlsWatcher

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ControlsWatcher.Add()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) _
    Handles Me.FormClosing
        ControlsWatcher.Remove()
    End Sub

    Private Sub ControlsWatcher_CurrentControlChanged(ByVal sender As Object, ByVal e As LzmTW.MessageFilter.Apply.CurrentControlChangedEventArgs) _
    Handles ControlsWatcher.CurrentControlChanged
        If sender Is Nothing Then
            Me.ToolStripStatusLabel1.Text = e.ToString
        Else
            Me.ToolStripStatusLabel1.Text = String.Format("{0}:{1}", CType(sender, Form).Name, e.ToString)
        End If

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim f As New Form2
        f.Show()
    End Sub

End Class


关于IMessageFilter,控件或窗体消息

#22


CurrentControlChangedEventArgs.vb
Namespace LzmTW.MessageFilter.Apply

    Public Class CurrentControlChangedEventArgs
        Inherits EventArgs

        Private gControl As Control = Nothing
        Private gToolStripItem As ToolStripItem = Nothing
        Private gControlType As ControlType

        Public ReadOnly Property Control() As Control
            Get
                Return gControl
            End Get
        End Property

        Public ReadOnly Property ToolStripItem() As ToolStripItem
            Get
                Return gToolStripItem
            End Get
        End Property

        Public ReadOnly Property ControlType() As ControlType
            Get
                Return gControlType
            End Get
        End Property

        Friend Sub New(ByVal ctr As Object, ByVal controlType As ControlType)
            Select Case controlType
                Case controlType.Form, controlType.Control, controlType.ToolStrip
                    gControl = CType(ctr, Control)
                Case controlType.ToolStripItem, controlType.ToolStripSeparator
                    gToolStripItem = CType(ctr, ToolStripItem)
                Case Apply.ControlType.NULL

            End Select
            gControlType = controlType
        End Sub

        Public Overrides Function ToString() As String
            Select Case ControlType
                Case Apply.ControlType.NULL
                    Return ""
                Case ControlType.Form, ControlType.Control, ControlType.ToolStrip
                    Return Me.Control.ToString
                Case ControlType.ToolStripItem, ControlType.ToolStripSeparator
                    Return Me.ToolStripItem.ToString
            End Select

            Return ""
        End Function
    End Class

    Public Enum ControlType
        Form
        Control
        ToolStrip
        ToolStripItem
        ToolStripSeparator
        NULL
    End Enum

    Public Delegate Sub CurrentControlChangedHandler(ByVal sender As Object, ByVal e As CurrentControlChangedEventArgs)

End Namespace

#23


ToolStripList.vb

Namespace LzmTW.MessageFilter.Apply
    Public Class ToolStripList

        Private Sub New()
        End Sub

        Public Shared Sub ForEach(ByVal toolStrip As ToolStrip, ByVal action As Action(Of ToolStripItem))
            ListToolStripItem(toolStrip, action)
        End Sub

        Public Shared Sub ForEach(ByVal toolStripItem As ToolStripItem, ByVal action As Action(Of ToolStripItem))
            ListToolStripItem(toolStripItem, action)
        End Sub

        Private Shared Sub ListToolStripItem(ByVal tooStrip As ToolStrip, ByVal action As Action(Of ToolStripItem))
            For Each item As ToolStripItem In tooStrip.Items
                ListToolStripItem(item, action)
            Next
        End Sub

        Private Shared Sub ListToolStripItem(ByVal toolStripItem As ToolStripItem, ByVal action As Action(Of ToolStripItem))
            action.Invoke(toolStripItem)

            Dim NextParent As ToolStripDropDownItem = TryCast(toolStripItem, ToolStripDropDownItem)

            If Not NextParent Is Nothing AndAlso NextParent.HasDropDownItems Then
                For Each item As ToolStripItem In NextParent.DropDownItems
                    ListToolStripItem(item, action)
                Next
            End If
        End Sub

        Public Shared Function FindForm(ByVal item As ToolStripItem) As Form
            Dim dropDown As ToolStripItem = item
            While dropDown.IsOnDropDown
                dropDown = dropDown.OwnerItem
            End While

            Return dropDown.GetCurrentParent.FindForm
        End Function
    End Class
End Namespace

#24


ControlsWatcher.Helper.vb
Imports LzmTW.MessageFilter.WindowMessage

Namespace LzmTW.MessageFilter.Apply
    Partial Class ControlsWatcher
        Private Class Helper
            Inherits FilterItemBase

            Public Event CurrentControlChanged As CurrentControlChangedHandler

            Private current As Control

            Protected Overrides Function Action(ByVal m As System.Windows.Forms.Message) As Boolean
                Select Case m.Msg

                    Case WM_MOUSEACTIVATE, WM_MOUSEWHEEL, WM_MOUSEMOVE, WM_MOUSELEAVE, WM_MOUSEHOVER, _
                        WM_LBUTTONDOWN, WM_LBUTTONDBLCLK, WM_LBUTTONUP, WM_RBUTTONDOWN, WM_RBUTTONDBLCLK, WM_RBUTTONUP, _
                        WM_KEYDOWN, WM_KEYUP

                        Dim ctr As Control = Control.FromHandle(m.HWnd)

                        If Not Object.ReferenceEquals(current, ctr) Then
                            current = ctr

                            Dim mType As ControlType

                            If TypeOf ctr Is Form Then
                                mType = ControlType.Form
                            ElseIf TypeOf ctr Is ToolStrip Then
                                mType = ControlType.ToolStrip
                            ElseIf TypeOf ctr Is Control Then
                                mType = ControlType.Control
                            Else
                                mType = ControlType.NULL
                            End If

                            Me.OnCurrentControlChanged(New CurrentControlChangedEventArgs(current, mType))
                        End If
                    Case Else
                End Select

                Return False
            End Function

            Private Sub OnCurrentControlChanged(ByVal e As CurrentControlChangedEventArgs)
                RaiseEvent CurrentControlChanged(Nothing, e)
            End Sub

        End Class
    End Class
End Namespace



ControlsWatcher.vb
Namespace LzmTW.MessageFilter.Apply
    Public Class ControlsWatcher
        Implements IFilterAction

        Public Event CurrentControlChanged As CurrentControlChangedHandler
        Private WithEvents gHelper As New Helper

        Private currentForm As Form
        Private currentToolStrip As ToolStrip

        Public Sub Add() Implements IFilterAction.Add
            gHelper.Add()
        End Sub

        Public Sub Remove() Implements IFilterAction.Remove
            gHelper.Remove()
        End Sub

        Private Sub OnCurrentControlChanged(ByVal e As CurrentControlChangedEventArgs)
            RaiseEvent CurrentControlChanged(currentForm, e)
        End Sub

        Private Sub gHelper_CurrentControlChanged(ByVal sender As Object, ByVal e As CurrentControlChangedEventArgs) _
        Handles gHelper.CurrentControlChanged

            If e.ControlType = ControlType.NULL Then Return

            Dim form As Form = e.Control.FindForm

            If Not Object.ReferenceEquals(form, currentForm) Then
                currentForm = form
            End If

            Me.OnCurrentControlChanged(e)

            If e.ControlType = ControlType.ToolStrip Then
                If Not Object.ReferenceEquals(e.Control, currentToolStrip) Then
                    If Not currentToolStrip Is Nothing Then
                        ToolStripList.ForEach(currentToolStrip, AddressOf ToolStripItemRemoveHandler)
                    End If

                    currentToolStrip = CType(e.Control, ToolStrip)

                    ToolStripList.ForEach(currentToolStrip, AddressOf ToolStripItemAddHandler)
                End If
            End If
        End Sub

        Private Sub ToolStripItemRemoveHandler(ByVal item As ToolStripItem)
            RemoveHandler item.MouseEnter, AddressOf ToolStripItem_MouseEnter
            RemoveHandler item.MouseLeave, AddressOf ToolStripItem_MouseLeave

            'RemoveHandler item.Paint, AddressOf ToolStripItem_Paint
        End Sub

        Private Sub ToolStripItemAddHandler(ByVal item As ToolStripItem)
            AddHandler item.MouseEnter, AddressOf ToolStripItem_MouseEnter
            AddHandler item.MouseLeave, AddressOf ToolStripItem_MouseLeave

            'AddHandler item.Paint, AddressOf ToolStripItem_Paint
        End Sub

        Private Sub ToolStripItem_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs)
            currentForm = ToolStripList.FindForm(CType(sender, ToolStripItem))

            If TypeOf sender Is ToolStripSeparator Then
                OnCurrentControlChanged(New CurrentControlChangedEventArgs(sender, ControlType.ToolStripSeparator))
            Else
                OnCurrentControlChanged(New CurrentControlChangedEventArgs(sender, ControlType.ToolStripItem))
            End If
        End Sub

        Private Sub ToolStripItem_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs)
            OnCurrentControlChanged(New CurrentControlChangedEventArgs(Nothing, ControlType.NULL))
        End Sub

        'Private currentToolStripItem As ToolStripItem

        'Private Sub ToolStripItem_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
        '    ToolStripList.ForEach(currentToolStrip, AddressOf FindSelectedItem)

        '    If TypeOf currentToolStripItem Is ToolStripSeparator Then
        '        OnCurrentControlChanged(New CurrentControlChangedEventArgs(currentToolStripItem, ControlType.ToolStripSeparator))
        '    Else
        '        OnCurrentControlChanged(New CurrentControlChangedEventArgs(currentToolStripItem, ControlType.ToolStripItem))
        '    End If
        'End Sub

        'Private Sub FindSelectedItem(ByVal item As ToolStripItem)
        '    If item.Selected Then currentToolStripItem = item
        'End Sub
    End Class
End Namespace



注释中的代码尝试实现菜单键盘选取,效果不大好.
此功能代码结束.

#25


比较凌乱。你肯定会整理一次放到自己的blog里的。我回头看你blog.

#26


引用 25 楼 wuyazhe 的回复:
比较凌乱。你肯定会整理一次放到自己的blog里的。我回头看你blog.



我也这样想哦

#27


凡是加NameSpace的,就是项目文件,不加的,是示例文件.

后面会打包上传.放在这也算寄存吧,很多代码我是写了就丢.

#28



代码下载: 在博客园上,VS2005

#29


下载了。没有一行注释……

#30


哈,现在很少写注释了.
我只是变量和函数名称上尽量的写清楚.

#31


别的类比如CatchMessage你用不用无所谓

不过如果你曾经看过或用过IMessageFilter的话,应该看得明白是怎么回事.

那些API你不用管它,我只是试用试用的,类中并没有用它们.

#32


学习

#33


太棒了,大餐!!!!!!

#34


将里头的代码看懂摸透会用,WinForm开发的相当部分知识也就掌握了.
我也意识的加了一些"不相关"的东西在里头.

希望对你们有所启发.仅供参考.

#35


寄存:

192.168.1.242:8086 

“/”应用程序中的服务器错误。
--------------------------------------------------------------------------------

由于目标机器积极拒绝,无法连接。 192.168.1.242:8086 
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 

异常详细信息: System.Net.Sockets.SocketException: 由于目标机器积极拒绝,无法连接。 192.168.1.242:8086

源错误: 

执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。  

堆栈跟踪: 


[SocketException (0x274d): 由于目标机器积极拒绝,无法连接。 192.168.1.242:8086]
   System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +2668969
   System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +717
   CSDN.Community.TopicFileDataCenter.TopicFileComponent.Reply(ReplyGenerateData rgd) +0
   CSDN.Community.TopicFileDataCenter.TopicFileDataCenterEntry.Reply(Guid topicId, DateTime createDate, ReplyInfo reply, CommunityUser user, UserSectionProfile usp) +73
   CSDN.Community.PointForum.Services.ReplyTopicManager.ReplyTopic(ReplyInfo reply, DateTime topicPostDate, String& errorInfo, CommunityUser user, UserSectionProfile usp) +747
   CSDN.Community.PointForum.WebControls.ReplyTopicPage.bt_Submit_Click(Object sender, EventArgs e) +604
   System.Web.UI.WebControls.Button.OnClick(EventArgs e) +105
   System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +107
   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1746

#36


很厉害!佩服了

#37


弱弱的mark一下

#38


我也想知道,正在找這方面的資料~~~~~

#39


test

#40


test

#41


虽然时间有点跨度,但知识没有变。

#42


我是知道了用ImessageFilter之后才看到这个帖子的。

可惜我在c#,你在vb.net

是不是.net搞的语言太多了,高手集中不起来。所以很多时候问不到答案?

#43


 lzmtw 兄,我遇到一个问题,就是不能筛选到窗体失效或者激活的消息。不知道是不是我的代码有误?请你帮我看一下。
Public Class Class1

    Implements IMessageFilter
    Private Const WM_MOVE As Long = &H3
    '窗体失效
    Private Const WM_ACTIVATE As Int32 = &H6
    Private Const WA_INACTIVE As Int32 = 0
    Private Const WM_ACTIVATEAPP As Int32 = &H1C
    Private Const WM_NCACTIVATE As Int32 = &H86
    Private Const WM_KILLFOCUS As Int32 = &H8
    Private Const WM_SETFOCUS As Int32 = &H7
    Private Const WM_LBUTTONDOWN As Integer = &H201
    Private Const WM_KEYDOWN As Long = &H100
    Private Const WM_KEYUP As Long = &H101
    Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
        Select Case m.Msg
            Case WM_LBUTTONDOWN
        
            Case WM_KEYDOWN

            Case WM_ACTIVATE '激活
                Console.WriteLine(m.ToString & "_________________________________")
            Case WM_NCACTIVATE
                Console.WriteLine(m.ToString & "_________________________________")
            Case WM_KILLFOCUS
                Console.WriteLine(m.ToString & "_________________________________")
            Case WM_SETFOCUS

                Console.WriteLine(m.ToString & "_________________________________")
        End Select
        Return False
    End Function
End Class


这是窗体测试代码
Public Class Form1

    Dim c As New Class1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Application.AddMessageFilter(c)
    End Sub
End Class

#1



可以不用关心“筛选”两字,只利用PreFilterMessage监视窗体消息,对消息进行分析。
这些消息局限于当前程序域内。

如要获取非当前程序域窗体消息,需要实现有关Windows钩子.

#2



对窗体消息Message,
Dim m As Message
m.HWnd为窗体句柄。

通过
Dim Ctr As Control = Control.FromHandle(m.HWnd)
取得句柄窗体或控件实例。

#3



如果对消息感兴趣,不妨简化一下IMessageFilter的实现过程。

IFilterAction.vb
Namespace LzmTW.MessageFilter
    Public Interface IFilterAction
        Sub Add()
        Sub Remove()
    End Interface
End Namespace


FilterAction.vb
Namespace LzmTW.MessageFilter

    Friend Class FilterAction
        Implements IMessageFilter, IFilterAction

        Private Action As MessageFilterAction

        Friend Sub New()
        End Sub

        Friend Sub Add(ByVal action As MessageFilterAction)
            Me.Action = action
        End Sub

        Private Function PreFilterMessage(ByRef m As Message) As Boolean _
        Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
            Return Me.Action.Invoke(m)
        End Function

        Public Sub Add() Implements IFilterAction.Add
            Application.AddMessageFilter(Me)
        End Sub

        Public Sub Remove() Implements IFilterAction.Remove
            Application.RemoveMessageFilter(Me)
        End Sub

        Public Shared Function Instance(ByVal acton As MessageFilterAction) As IFilterAction
            Dim filter As New FilterAction
            filter.Add(acton)

            Return filter
        End Function
    End Class

End Namespace

注意这个类的定义修饰,为Friend.


简单的使用方法:
FilterHelper.vb
Namespace LzmTW.MessageFilter
    Public Class FilterHelper
        Private Sub New()
        End Sub

        Public Shared Function Instance(ByVal acton As MessageFilterAction) As IFilterAction
            Return FilterAction.Instance(acton)
        End Function

    End Class

End Namespace

#4


本帖最后由 lzmtw 于 2008-04-21 10:29:45 编辑
MessageFilterAction的定义

Delegate.vb
Namespace LzmTW.MessageFilter
    Public Delegate Function MessageFilterAction(ByVal m As Message) As Boolean
End Namespace

#5



示例一:

Public Class Form1

    Private gFilter As LzmTW.MessageFilter.IFilterAction

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If Not gFilter Is Nothing Then Return

        gFilter = LzmTW.MessageFilter.FilterHelper.Instance(AddressOf MessageWatcher)

        gFilter.Add() '添加到Application并发生作用
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        gFilter.Remove() '从Application中移除
    End Sub

    Private Function MessageWatcher(ByVal m As Message) As Boolean
        Console.WriteLine(m.ToString)

        Return False '对消息不筛选。如为Return Ture,那么所有的窗体消息都筛选掉,窗体不作任何反应,"死"了。
    End Function
End Class

#6



修改MessageWatcher,当你移动鼠标或按Tab键时,下面会提示出消息所捕获的当前控件(Form也是控件,控件就是窗体).
    Private Function MessageWatcher(ByVal m As Message) As Boolean
        Dim ctr As Control = Control.FromHandle(m.HWnd)

        If ctr Is Nothing Then Return False

        Console.WriteLine(ctr.ToString)

        Return False 
    End Function

#7



窗体消息有很多,可以通过m.Msg进行筛选.
    Private Const WM_KEYUP As Integer = &H101
    Private Const WM_MOUSEHOVER As Integer = &H2A1

    Private Function MessageWatcher(ByVal m As Message) As Boolean
        Select Case m.Msg

            Case WM_KEYUP, WM_MOUSEHOVER
                Dim ctr As Control = Control.FromHandle(m.HWnd)

                If ctr Is Nothing Then Return False

                Console.WriteLine(ctr.ToString)
            Case Else

        End Select

        Return False
    End Function

#8


说真的,水兄。这个。不知道你在说什么。我想。你如果可能,最好先说明类的功能,我耐心的读完了帖子。知道你是封装了一个类,简化了实现IMessageFilter的。

#9



整理一下示例一:当移动鼠标或选择控件时,即时显示当前鼠标下面或当前控件的名称

Public Class Form1

    Private gFilter As LzmTW.MessageFilter.IFilterAction

    Private Const WM_KEYUP As Integer = &H101
    Private Const WM_MOUSEHOVER As Integer = &H2A1

    Private Function MessageWatcher(ByVal m As Message) As Boolean
        Select Case m.Msg

            Case WM_KEYUP, WM_MOUSEHOVER
                Dim ctr As Control = Control.FromHandle(m.HWnd)

                If Not ctr Is Nothing Then Me.Text = "this is " & ctr.Name
            Case Else
        End Select

        Return False
    End Function

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        gFilter = LzmTW.MessageFilter.FilterHelper.Instance(AddressOf MessageWatcher)

        gFilter.Add()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) _
    Handles Me.FormClosing
        gFilter.Remove()
    End Sub
End Class

#10


引用 8 楼 KissXYL 的回复:
说真的,水兄。这个。不知道你在说什么。我想。你如果可能,最好先说明类的功能,我耐心的读完了帖子。知道你是封装了一个类,简化了实现IMessageFilter的。


我尝试说明怎么使用这个类,通过这个类可以做点什么.

#11


还有。。。
帖子刚发出来就加了精……
是不是太早了。怎么也要多几个回复后再啊。

#12


关于加精,是我自己给自己加精。我习惯啦。

加精的理由,对我自己的贴子来说,不在于回复,而在于过程。


这贴子会比较长。

#13


如果我发个这样的帖子。你会不会一开始就加精呢。所谓执法要公正,流程上。并不能因为你是版主就先加精再把帖子变成精华。当然我不否认你的帖子写的很好。但总有老王卖瓜之嫌。并有执法不公之嫌。

#14


引用 13 楼 KissXYL 的回复:
如果我发个这样的帖子。你会不会一开始就加精呢。所谓执法要公正,流程上。并不能因为你是版主就先加精再把帖子变成精华。当然我不否认你的帖子写的很好。但总有老王卖瓜之嫌。并有执法不公之嫌。


如果你跟我说,你想就某个问题写一个贴子,详细的将你的理解和解决的过程写出来,我肯定的先给你的贴子加精。我也热烈欢迎多多益善。
你以为我总给自己的贴子加精我很开心哪?

至于卖瓜之嫌,不公之嫌,这是你的看法,我不解释。

#15


窗体消息的种类有哪些?


WindowMessage.vb
Namespace LzmTW.MessageFilter

    Public Enum WindowMessage
        WM_NULL = &H0
        WM_CREATE = &H1
        WM_DESTROY = &H2
        WM_MOVE = &H3
        WM_SIZE = &H5
        WM_ACTIVATE = &H6
        WM_SETFOCUS = &H7
        WM_KILLFOCUS = &H8
        WM_ENABLE = &HA
        WM_SETREDRAW = &HB
        WM_SETTEXT = &HC
        WM_GETTEXT = &HD
        WM_GETTEXTLENGTH = &HE
        WM_PAINT = &HF
        WM_CLOSE = &H10
        WM_QUERYENDSESSION = &H11
        WM_QUIT = &H12
        WM_QUERYOPEN = &H13
        WM_ERASEBKGND = &H14
        WM_SYSCOLORCHANGE = &H15
        WM_ENDSESSION = &H16
        WM_SHOWWINDOW = &H18
        WM_CTLCOLOR = &H19
        WM_WININICHANGE = &H1A
        WM_DEVMODECHANGE = &H1B
        WM_ACTIVATEAPP = &H1C
        WM_FONTCHANGE = &H1D
        WM_TIMECHANGE = &H1E
        WM_CANCELMODE = &H1F
        WM_SETCURSOR = &H20
        WM_MOUSEACTIVATE = &H21
        WM_CHILDACTIVATE = &H22
        WM_QUEUESYNC = &H23
        WM_GETMINMAXINFO = &H24
        WM_PAINTICON = &H26
        WM_ICONERASEBKGND = &H27
        WM_NEXTDLGCTL = &H28
        WM_SPOOLERSTATUS = &H2A
        WM_DRAWITEM = &H2B
        WM_MEASUREITEM = &H2C
        WM_DELETEITEM = &H2D
        WM_VKEYTOITEM = &H2E
        WM_CHARTOITEM = &H2F
        WM_SETFONT = &H30
        WM_GETFONT = &H31
        WM_SETHOTKEY = &H32
        WM_GETHOTKEY = &H33
        WM_QUERYDRAGICON = &H37
        WM_COMPAREITEM = &H39
        WM_GETOBJECT = &H3D
        WM_COMPACTING = &H41
        WM_COMMNOTIFY = &H44
        WM_WINDOWPOSCHANGING = &H46
        WM_WINDOWPOSCHANGED = &H47
        WM_POWER = &H48
        WM_COPYDATA = &H4A
        WM_CANCELJOURNAL = &H4B
        WM_NOTIFY = &H4E
        WM_INPUTLANGCHANGEREQUEST = &H50
        WM_INPUTLANGCHANGE = &H51
        WM_TCARD = &H52
        WM_HELP = &H53
        WM_USERCHANGED = &H54
        WM_NOTIFYFORMAT = &H55
        WM_CONTEXTMENU = &H7B
        WM_STYLECHANGING = &H7C
        WM_STYLECHANGED = &H7D
        WM_DISPLAYCHANGE = &H7E
        WM_GETICON = &H7F
        WM_SETICON = &H80
        WM_NCCREATE = &H81
        WM_NCDESTROY = &H82
        WM_NCCALCSIZE = &H83
        WM_NCHITTEST = &H84
        WM_NCPAINT = &H85
        WM_NCACTIVATE = &H86
        WM_GETDLGCODE = &H87
        WM_NCMOUSEMOVE = &HA0
        WM_NCLBUTTONDOWN = &HA1
        WM_NCLBUTTONUP = &HA2
        WM_NCLBUTTONDBLCLK = &HA3
        WM_NCRBUTTONDOWN = &HA4
        WM_NCRBUTTONUP = &HA5
        WM_NCRBUTTONDBLCLK = &HA6
        WM_NCMBUTTONDOWN = &HA7
        WM_NCMBUTTONUP = &HA8
        WM_NCMBUTTONDBLCLK = &HA9
        WM_KEYDOWN = &H100
        WM_KEYUP = &H101
        WM_CHAR = &H102
        WM_DEADCHAR = &H103
        WM_SYSKEYDOWN = &H104
        WM_SYSKEYUP = &H105
        WM_SYSCHAR = &H106
        WM_SYSDEADCHAR = &H107
        WM_KEYLAST = &H108
        WM_IME_STARTCOMPOSITION = &H10D
        WM_IME_ENDCOMPOSITION = &H10E
        WM_IME_COMPOSITION = &H10F
        WM_INITDIALOG = &H110
        WM_COMMAND = &H111
        WM_SYSCOMMAND = &H112
        WM_TIMER = &H113
        WM_HSCROLL = &H114
        WM_VSCROLL = &H115
        WM_INITMENU = &H116
        WM_INITMENUPOPUP = &H117
        WM_MENUSELECT = &H11F
        WM_MENUCHAR = &H120
        WM_ENTERIDLE = &H121
        WM_CTLCOLORMSGBOX = &H132
        WM_CTLCOLOREDIT = &H133
        WM_CTLCOLORLISTBOX = &H134
        WM_CTLCOLORBTN = &H135
        WM_CTLCOLORDLG = &H136
        WM_CTLCOLORSCROLLBAR = &H137
        WM_CTLCOLORSTATIC = &H138
        WM_MOUSEMOVE = &H200
        WM_LBUTTONDOWN = &H201
        WM_LBUTTONUP = &H202
        WM_LBUTTONDBLCLK = &H203
        WM_RBUTTONDOWN = &H204
        WM_RBUTTONUP = &H205
        WM_RBUTTONDBLCLK = &H206
        WM_MBUTTONDOWN = &H207
        WM_MBUTTONUP = &H208
        WM_MBUTTONDBLCLK = &H209
        WM_MOUSEWHEEL = &H20A
        WM_PARENTNOTIFY = &H210
        WM_ENTERMENULOOP = &H211
        WM_EXITMENULOOP = &H212
        WM_NEXTMENU = &H213
        WM_SIZING = &H214
        WM_CAPTURECHANGED = &H215
        WM_MOVING = &H216
        WM_POWERBROADCAST = &H218
        WM_DEVICECHANGE = &H219
        WM_MDICREATE = &H220
        WM_MDIDESTROY = &H221
        WM_MDIACTIVATE = &H222
        WM_MDIRESTORE = &H223
        WM_MDINEXT = &H224
        WM_MDIMAXIMIZE = &H225
        WM_MDITILE = &H226
        WM_MDICASCADE = &H227
        WM_MDIICONARRANGE = &H228
        WM_MDIGETACTIVE = &H229
        WM_MDISETMENU = &H230
        WM_ENTERSIZEMOVE = &H231
        WM_EXITSIZEMOVE = &H232
        WM_DROPFILES = &H233
        WM_MDIREFRESHMENU = &H234
        WM_IME_SETCONTEXT = &H281
        WM_IME_NOTIFY = &H282
        WM_IME_CONTROL = &H283
        WM_IME_COMPOSITIONFULL = &H284
        WM_IME_SELECT = &H285
        WM_IME_CHAR = &H286
        WM_IME_KEYDOWN = &H290
        WM_IME_KEYUP = &H291
        WM_MOUSEHOVER = &H2A1
        WM_MOUSELEAVE = &H2A3
        WM_CUT = &H300
        WM_COPY = &H301
        WM_PASTE = &H302
        WM_CLEAR = &H303
        WM_UNDO = &H304
        WM_RENDERFORMAT = &H305
        WM_RENDERALLFORMATS = &H306
        WM_DESTROYCLIPBOARD = &H307
        WM_DRAWCLIPBOARD = &H308
        WM_PAINTCLIPBOARD = &H309
        WM_VSCROLLCLIPBOARD = &H30A
        WM_SIZECLIPBOARD = &H30B
        WM_ASKCBFORMATNAME = &H30C
        WM_CHANGECBCHAIN = &H30D
        WM_HSCROLLCLIPBOARD = &H30E
        WM_QUERYNEWPALETTE = &H30F
        WM_PALETTEISCHANGING = &H310
        WM_PALETTECHANGED = &H311
        WM_HOTKEY = &H312
        WM_PRINT = &H317
        WM_PRINTCLIENT = &H318
        WM_HANDHELDFIRST = &H358
        WM_HANDHELDLAST = &H35F
        WM_AFXFIRST = &H360
        WM_AFXLAST = &H37F
        WM_PENWINFIRST = &H380
        WM_PENWINLAST = &H38F
    End Enum

End Namespace

#16


学习了。
谢谢...

但是用这个封装后的类有什么好处?

在分析下与WinPro的功能差异就更好了

#17


本帖最后由 lzmtw 于 2008-04-21 19:51:17 编辑
现在,写个在当前程序域中监视窗体实例的类

为方便起见

FilterItemBase.vb
Namespace LzmTW.MessageFilter

    Public MustInherit Class FilterItemBase
        Implements IFilterAction

        Private filter As IFilterAction

        Protected MustOverride Function Action(ByVal m As Message) As Boolean

        Sub New()
            filter = FilterAction.Instance(AddressOf Action)
        End Sub

        Public Sub Add() Implements IFilterAction.Add
            filter.Add()
        End Sub

        Public Sub Remove() Implements IFilterAction.Remove
            filter.Remove()
        End Sub
    End Class

End Namespace

#18


示例二:窗体实例监视类(f.Show过有效)

Public Class FormWatcher
    Inherits LzmTW.MessageFilter.FilterItemBase

    Private gForms As New List(Of Form)

    Public ReadOnly Property Count() As Integer
        Get
            Return Forms.Length
        End Get
    End Property

    Public ReadOnly Property Forms() As Form()
        Get
            Check()
            Return gForms.ToArray
        End Get
    End Property

    Public Function FindForm(ByVal text As String) As Form()
        Dim array As New List(Of Form)

        For Each f As Form In Me.Forms
            If String.Compare(f.Text, text, True) = 0 Then
                array.Add(f)
            End If
        Next

        Return array.ToArray
    End Function

    Public Function FindForm(ByVal t As Type) As Form()
        Dim array As New List(Of Form)

        For Each f As Form In Me.Forms
            If f.GetType Is t Then
                array.Add(f)
            End If
        Next

        Return array.ToArray
    End Function


    Private Sub Check()
        For i As Integer = gForms.Count - 1 To 0 Step -1
            Dim f As Form = gForms(i)
            If f Is Nothing OrElse f.IsDisposed Then
                gForms.Remove(f)
            End If
        Next
    End Sub

    Protected Overrides Function Action(ByVal m As System.Windows.Forms.Message) As Boolean
        Dim ctr As Control = Control.FromHandle(m.HWnd)

        If ctr Is Nothing Then Return False

        If Not TypeOf ctr Is Form Then Return False



        Dim f As Form = CType(ctr, Form)

        If f.IsDisposed Then
            If gForms.Contains(f) Then
                gForms.Remove(f)
            End If
        Else
            If Not gForms.Contains(f) Then
                gForms.Add(f)
            End If
        End If

        Return False
    End Function
End Class

#19


使用:
Public Class Form1

    Private Watcher As FormWatcher



    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Watcher = New FormWatcher

        Watcher.Add()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) _
    Handles Me.FormClosing
        Watcher.Remove()
    End Sub


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim f As New Form
        f.Text = "aaaa"
        f.Show()
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim f As New Form2
        f.Show()
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Console.WriteLine(Watcher.Count)
        For Each f As Form In Watcher.Forms
            Console.WriteLine(f.Text)
        Next
    End Sub

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        Dim array As Form() = Watcher.FindForm("aaaa")
        If array.Length > 0 Then
            Console.WriteLine(array(0).Text)
        End If
    End Sub

    Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
        Dim array As Form() = Watcher.FindForm(GetType(Form2))
        If array.Length > 0 Then
            Console.WriteLine(array(0).Text)
        End If
    End Sub
End Class

#20


#21


扩充一下示例一,用下面的代码实现如图的效果(菜单用键盘选取时无效)

示例代码:
Public Class Form1

    Private WithEvents ControlsWatcher As New LzmTW.MessageFilter.Apply.ControlsWatcher

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ControlsWatcher.Add()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) _
    Handles Me.FormClosing
        ControlsWatcher.Remove()
    End Sub

    Private Sub ControlsWatcher_CurrentControlChanged(ByVal sender As Object, ByVal e As LzmTW.MessageFilter.Apply.CurrentControlChangedEventArgs) _
    Handles ControlsWatcher.CurrentControlChanged
        If sender Is Nothing Then
            Me.ToolStripStatusLabel1.Text = e.ToString
        Else
            Me.ToolStripStatusLabel1.Text = String.Format("{0}:{1}", CType(sender, Form).Name, e.ToString)
        End If

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim f As New Form2
        f.Show()
    End Sub

End Class


关于IMessageFilter,控件或窗体消息

#22


CurrentControlChangedEventArgs.vb
Namespace LzmTW.MessageFilter.Apply

    Public Class CurrentControlChangedEventArgs
        Inherits EventArgs

        Private gControl As Control = Nothing
        Private gToolStripItem As ToolStripItem = Nothing
        Private gControlType As ControlType

        Public ReadOnly Property Control() As Control
            Get
                Return gControl
            End Get
        End Property

        Public ReadOnly Property ToolStripItem() As ToolStripItem
            Get
                Return gToolStripItem
            End Get
        End Property

        Public ReadOnly Property ControlType() As ControlType
            Get
                Return gControlType
            End Get
        End Property

        Friend Sub New(ByVal ctr As Object, ByVal controlType As ControlType)
            Select Case controlType
                Case controlType.Form, controlType.Control, controlType.ToolStrip
                    gControl = CType(ctr, Control)
                Case controlType.ToolStripItem, controlType.ToolStripSeparator
                    gToolStripItem = CType(ctr, ToolStripItem)
                Case Apply.ControlType.NULL

            End Select
            gControlType = controlType
        End Sub

        Public Overrides Function ToString() As String
            Select Case ControlType
                Case Apply.ControlType.NULL
                    Return ""
                Case ControlType.Form, ControlType.Control, ControlType.ToolStrip
                    Return Me.Control.ToString
                Case ControlType.ToolStripItem, ControlType.ToolStripSeparator
                    Return Me.ToolStripItem.ToString
            End Select

            Return ""
        End Function
    End Class

    Public Enum ControlType
        Form
        Control
        ToolStrip
        ToolStripItem
        ToolStripSeparator
        NULL
    End Enum

    Public Delegate Sub CurrentControlChangedHandler(ByVal sender As Object, ByVal e As CurrentControlChangedEventArgs)

End Namespace

#23


ToolStripList.vb

Namespace LzmTW.MessageFilter.Apply
    Public Class ToolStripList

        Private Sub New()
        End Sub

        Public Shared Sub ForEach(ByVal toolStrip As ToolStrip, ByVal action As Action(Of ToolStripItem))
            ListToolStripItem(toolStrip, action)
        End Sub

        Public Shared Sub ForEach(ByVal toolStripItem As ToolStripItem, ByVal action As Action(Of ToolStripItem))
            ListToolStripItem(toolStripItem, action)
        End Sub

        Private Shared Sub ListToolStripItem(ByVal tooStrip As ToolStrip, ByVal action As Action(Of ToolStripItem))
            For Each item As ToolStripItem In tooStrip.Items
                ListToolStripItem(item, action)
            Next
        End Sub

        Private Shared Sub ListToolStripItem(ByVal toolStripItem As ToolStripItem, ByVal action As Action(Of ToolStripItem))
            action.Invoke(toolStripItem)

            Dim NextParent As ToolStripDropDownItem = TryCast(toolStripItem, ToolStripDropDownItem)

            If Not NextParent Is Nothing AndAlso NextParent.HasDropDownItems Then
                For Each item As ToolStripItem In NextParent.DropDownItems
                    ListToolStripItem(item, action)
                Next
            End If
        End Sub

        Public Shared Function FindForm(ByVal item As ToolStripItem) As Form
            Dim dropDown As ToolStripItem = item
            While dropDown.IsOnDropDown
                dropDown = dropDown.OwnerItem
            End While

            Return dropDown.GetCurrentParent.FindForm
        End Function
    End Class
End Namespace

#24


ControlsWatcher.Helper.vb
Imports LzmTW.MessageFilter.WindowMessage

Namespace LzmTW.MessageFilter.Apply
    Partial Class ControlsWatcher
        Private Class Helper
            Inherits FilterItemBase

            Public Event CurrentControlChanged As CurrentControlChangedHandler

            Private current As Control

            Protected Overrides Function Action(ByVal m As System.Windows.Forms.Message) As Boolean
                Select Case m.Msg

                    Case WM_MOUSEACTIVATE, WM_MOUSEWHEEL, WM_MOUSEMOVE, WM_MOUSELEAVE, WM_MOUSEHOVER, _
                        WM_LBUTTONDOWN, WM_LBUTTONDBLCLK, WM_LBUTTONUP, WM_RBUTTONDOWN, WM_RBUTTONDBLCLK, WM_RBUTTONUP, _
                        WM_KEYDOWN, WM_KEYUP

                        Dim ctr As Control = Control.FromHandle(m.HWnd)

                        If Not Object.ReferenceEquals(current, ctr) Then
                            current = ctr

                            Dim mType As ControlType

                            If TypeOf ctr Is Form Then
                                mType = ControlType.Form
                            ElseIf TypeOf ctr Is ToolStrip Then
                                mType = ControlType.ToolStrip
                            ElseIf TypeOf ctr Is Control Then
                                mType = ControlType.Control
                            Else
                                mType = ControlType.NULL
                            End If

                            Me.OnCurrentControlChanged(New CurrentControlChangedEventArgs(current, mType))
                        End If
                    Case Else
                End Select

                Return False
            End Function

            Private Sub OnCurrentControlChanged(ByVal e As CurrentControlChangedEventArgs)
                RaiseEvent CurrentControlChanged(Nothing, e)
            End Sub

        End Class
    End Class
End Namespace



ControlsWatcher.vb
Namespace LzmTW.MessageFilter.Apply
    Public Class ControlsWatcher
        Implements IFilterAction

        Public Event CurrentControlChanged As CurrentControlChangedHandler
        Private WithEvents gHelper As New Helper

        Private currentForm As Form
        Private currentToolStrip As ToolStrip

        Public Sub Add() Implements IFilterAction.Add
            gHelper.Add()
        End Sub

        Public Sub Remove() Implements IFilterAction.Remove
            gHelper.Remove()
        End Sub

        Private Sub OnCurrentControlChanged(ByVal e As CurrentControlChangedEventArgs)
            RaiseEvent CurrentControlChanged(currentForm, e)
        End Sub

        Private Sub gHelper_CurrentControlChanged(ByVal sender As Object, ByVal e As CurrentControlChangedEventArgs) _
        Handles gHelper.CurrentControlChanged

            If e.ControlType = ControlType.NULL Then Return

            Dim form As Form = e.Control.FindForm

            If Not Object.ReferenceEquals(form, currentForm) Then
                currentForm = form
            End If

            Me.OnCurrentControlChanged(e)

            If e.ControlType = ControlType.ToolStrip Then
                If Not Object.ReferenceEquals(e.Control, currentToolStrip) Then
                    If Not currentToolStrip Is Nothing Then
                        ToolStripList.ForEach(currentToolStrip, AddressOf ToolStripItemRemoveHandler)
                    End If

                    currentToolStrip = CType(e.Control, ToolStrip)

                    ToolStripList.ForEach(currentToolStrip, AddressOf ToolStripItemAddHandler)
                End If
            End If
        End Sub

        Private Sub ToolStripItemRemoveHandler(ByVal item As ToolStripItem)
            RemoveHandler item.MouseEnter, AddressOf ToolStripItem_MouseEnter
            RemoveHandler item.MouseLeave, AddressOf ToolStripItem_MouseLeave

            'RemoveHandler item.Paint, AddressOf ToolStripItem_Paint
        End Sub

        Private Sub ToolStripItemAddHandler(ByVal item As ToolStripItem)
            AddHandler item.MouseEnter, AddressOf ToolStripItem_MouseEnter
            AddHandler item.MouseLeave, AddressOf ToolStripItem_MouseLeave

            'AddHandler item.Paint, AddressOf ToolStripItem_Paint
        End Sub

        Private Sub ToolStripItem_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs)
            currentForm = ToolStripList.FindForm(CType(sender, ToolStripItem))

            If TypeOf sender Is ToolStripSeparator Then
                OnCurrentControlChanged(New CurrentControlChangedEventArgs(sender, ControlType.ToolStripSeparator))
            Else
                OnCurrentControlChanged(New CurrentControlChangedEventArgs(sender, ControlType.ToolStripItem))
            End If
        End Sub

        Private Sub ToolStripItem_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs)
            OnCurrentControlChanged(New CurrentControlChangedEventArgs(Nothing, ControlType.NULL))
        End Sub

        'Private currentToolStripItem As ToolStripItem

        'Private Sub ToolStripItem_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
        '    ToolStripList.ForEach(currentToolStrip, AddressOf FindSelectedItem)

        '    If TypeOf currentToolStripItem Is ToolStripSeparator Then
        '        OnCurrentControlChanged(New CurrentControlChangedEventArgs(currentToolStripItem, ControlType.ToolStripSeparator))
        '    Else
        '        OnCurrentControlChanged(New CurrentControlChangedEventArgs(currentToolStripItem, ControlType.ToolStripItem))
        '    End If
        'End Sub

        'Private Sub FindSelectedItem(ByVal item As ToolStripItem)
        '    If item.Selected Then currentToolStripItem = item
        'End Sub
    End Class
End Namespace



注释中的代码尝试实现菜单键盘选取,效果不大好.
此功能代码结束.

#25


比较凌乱。你肯定会整理一次放到自己的blog里的。我回头看你blog.

#26


引用 25 楼 wuyazhe 的回复:
比较凌乱。你肯定会整理一次放到自己的blog里的。我回头看你blog.



我也这样想哦

#27


凡是加NameSpace的,就是项目文件,不加的,是示例文件.

后面会打包上传.放在这也算寄存吧,很多代码我是写了就丢.

#28



代码下载: 在博客园上,VS2005

#29


下载了。没有一行注释……

#30


哈,现在很少写注释了.
我只是变量和函数名称上尽量的写清楚.

#31


别的类比如CatchMessage你用不用无所谓

不过如果你曾经看过或用过IMessageFilter的话,应该看得明白是怎么回事.

那些API你不用管它,我只是试用试用的,类中并没有用它们.

#32


学习

#33


太棒了,大餐!!!!!!

#34


将里头的代码看懂摸透会用,WinForm开发的相当部分知识也就掌握了.
我也意识的加了一些"不相关"的东西在里头.

希望对你们有所启发.仅供参考.

#35


寄存:

192.168.1.242:8086 

“/”应用程序中的服务器错误。
--------------------------------------------------------------------------------

由于目标机器积极拒绝,无法连接。 192.168.1.242:8086 
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 

异常详细信息: System.Net.Sockets.SocketException: 由于目标机器积极拒绝,无法连接。 192.168.1.242:8086

源错误: 

执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。  

堆栈跟踪: 


[SocketException (0x274d): 由于目标机器积极拒绝,无法连接。 192.168.1.242:8086]
   System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +2668969
   System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +717
   CSDN.Community.TopicFileDataCenter.TopicFileComponent.Reply(ReplyGenerateData rgd) +0
   CSDN.Community.TopicFileDataCenter.TopicFileDataCenterEntry.Reply(Guid topicId, DateTime createDate, ReplyInfo reply, CommunityUser user, UserSectionProfile usp) +73
   CSDN.Community.PointForum.Services.ReplyTopicManager.ReplyTopic(ReplyInfo reply, DateTime topicPostDate, String& errorInfo, CommunityUser user, UserSectionProfile usp) +747
   CSDN.Community.PointForum.WebControls.ReplyTopicPage.bt_Submit_Click(Object sender, EventArgs e) +604
   System.Web.UI.WebControls.Button.OnClick(EventArgs e) +105
   System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +107
   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1746

#36


很厉害!佩服了

#37


弱弱的mark一下

#38


我也想知道,正在找這方面的資料~~~~~

#39


test

#40


test

#41


虽然时间有点跨度,但知识没有变。

#42


我是知道了用ImessageFilter之后才看到这个帖子的。

可惜我在c#,你在vb.net

是不是.net搞的语言太多了,高手集中不起来。所以很多时候问不到答案?

#43


 lzmtw 兄,我遇到一个问题,就是不能筛选到窗体失效或者激活的消息。不知道是不是我的代码有误?请你帮我看一下。
Public Class Class1

    Implements IMessageFilter
    Private Const WM_MOVE As Long = &H3
    '窗体失效
    Private Const WM_ACTIVATE As Int32 = &H6
    Private Const WA_INACTIVE As Int32 = 0
    Private Const WM_ACTIVATEAPP As Int32 = &H1C
    Private Const WM_NCACTIVATE As Int32 = &H86
    Private Const WM_KILLFOCUS As Int32 = &H8
    Private Const WM_SETFOCUS As Int32 = &H7
    Private Const WM_LBUTTONDOWN As Integer = &H201
    Private Const WM_KEYDOWN As Long = &H100
    Private Const WM_KEYUP As Long = &H101
    Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
        Select Case m.Msg
            Case WM_LBUTTONDOWN
        
            Case WM_KEYDOWN

            Case WM_ACTIVATE '激活
                Console.WriteLine(m.ToString & "_________________________________")
            Case WM_NCACTIVATE
                Console.WriteLine(m.ToString & "_________________________________")
            Case WM_KILLFOCUS
                Console.WriteLine(m.ToString & "_________________________________")
            Case WM_SETFOCUS

                Console.WriteLine(m.ToString & "_________________________________")
        End Select
        Return False
    End Function
End Class


这是窗体测试代码
Public Class Form1

    Dim c As New Class1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Application.AddMessageFilter(c)
    End Sub
End Class