在vb.net中,是否有用于在按钮外单击的事件侦听器?

在vb.net中,是否有用于在按钮外单击的事件侦听器?,vb.net,events,mouseevent,Vb.net,Events,Mouseevent,我正在创建一个自定义菜单,我希望当用户单击表单上的任何其他位置时,该菜单关闭。我试过使用.LostFocus,但只有当他们点击的东西能够获得焦点时,它才起作用。很多东西都没有焦点,因此菜单一直打开。我需要一个按钮上的监听器,上面写着:“如果鼠标被点击,但它不在你身上,那么做些什么(关闭)” 有什么建议吗 谢谢。您可以为表单中的每个控件创建一个MouseDown事件处理程序 For Each c As Control In Me.Controls AddHandler c.

我正在创建一个自定义菜单,我希望当用户单击表单上的任何其他位置时,该菜单关闭。我试过使用.LostFocus,但只有当他们点击的东西能够获得焦点时,它才起作用。很多东西都没有焦点,因此菜单一直打开。我需要一个按钮上的监听器,上面写着:“如果鼠标被点击,但它不在你身上,那么做些什么(关闭)”

有什么建议吗


谢谢。

您可以为表单中的每个控件创建一个MouseDown事件处理程序

    For Each c As Control In Me.Controls
        AddHandler c.MouseDown, AddressOf c_MouseDown
    Next
然后检查事件的发送者是否不是您的按钮

Private Sub c_MouseDown(sender As Object, e As MouseEventArgs)
    If sender Is Button1 Then
        MsgBox("Open costumized menu")
    Else
        MsgBox("Replace this with 'close something'")
    End If
End Sub
编辑:当然,您也必须为表单创建eventhandler

AddHandler Me.MouseDown, AddressOf c_MouseDown

最好将处理程序放入构造函数中

在窗体构造函数中设置
鼠标单击
事件处理程序,如下所示:

Public Sub New()
    Me.MouseClick += mouseClick
End Sub
Private Sub mouseClick(sender As Object, e As MouseEventArgs)
    ' Do whatever logic you want here
    ' For example you can capture which mouse button was clicked, like this:
    If e.Button = MouseButtons.Left Then

    End If
End Sub
然后您可以编写事件处理程序代码,如下所示:

Public Sub New()
    Me.MouseClick += mouseClick
End Sub
Private Sub mouseClick(sender As Object, e As MouseEventArgs)
    ' Do whatever logic you want here
    ' For example you can capture which mouse button was clicked, like this:
    If e.Button = MouseButtons.Left Then

    End If
End Sub

感谢您提供的信息,但我通过使用此页面上的代码解决了我的问题:


显然,使用钩子是检测鼠标点击的唯一方法。它甚至可以检测到程序外的点击。

唯一的方法就是使用钩子

下面是一些代码。你还是应该好好读一读。您需要转到project/properties/Debug并取消选中EnabletheVisualStudioHostingProcess复选框

此代码将计算窗体运行时屏幕上任何位置的所有鼠标左键和右键单击次数

对于所需的表单:

Public Class Form1
    Private WithEvents MouseDetector As MouseDetector
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        MouseDetector = New MouseDetector
    End Sub
    Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
        RemoveHandler MouseDetector.MouseLeftButtonClick, AddressOf MouseDetector_MouseLeftButtonClick
        RemoveHandler MouseDetector.MouseRightButtonClick, AddressOf MouseDetector_MouseRightButtonClick
        MouseDetector.Dispose()
    End Sub
    Private Sub MouseDetector_MouseLeftButtonClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MouseDetector.MouseLeftButtonClick
        If IsNumeric(LabelLeft.Text) Then
            LabelLeft.Text = CInt(LabelLeft.Text) + 1
        Else
            LabelLeft.Text = 1
        End If
    End Sub
    Private Sub MouseDetector_MouseRightButtonClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MouseDetector.MouseRightButtonClick
        If IsNumeric(LabelRight.Text) Then
            LabelRight.Text = CInt(LabelRight.Text) + 1
        Else
            LabelRight.Text = 1
        End If
    End Sub
End Class
向项目中添加一个类,将其命名为MouseDetector,并将以下代码复制到其中

Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.Windows.Forms
Public Class MouseDetector
    Public Event MouseLeftButtonClick(ByVal sender As Object, ByVal e As MouseEventArgs)
    Public Event MouseRightButtonClick(ByVal sender As Object, ByVal e As MouseEventArgs)
    Private Delegate Function MouseHookCallback(ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer
    Private MouseHookCallbackDelegate As MouseHookCallback
    Private MouseHookID As Integer
    Public Sub New()
        If MouseHookID = 0 Then
            MouseHookCallbackDelegate = AddressOf MouseHookProc
            MouseHookID = SetWindowsHookEx(CInt(14), MouseHookCallbackDelegate, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly.GetModules()(0)), 0)
            If MouseHookID = 0 Then
                'error
            End If
        End If
    End Sub
    Public Sub Dispose()
        If Not MouseHookID = -1 Then
            UnhookWindowsHookEx(MouseHookID)
            MouseHookCallbackDelegate = Nothing
        End If
        MouseHookID = -1
    End Sub
    Private Enum MouseMessages
        WM_LeftButtonDown = 513
        WM_LeftButtonUp = 514
        WM_LeftDblClick = 515
        WM_RightButtonDown = 516
        WM_RightButtonUp = 517
        WM_RightDblClick = 518
    End Enum
    <StructLayout(LayoutKind.Sequential)> _
    Private Structure Point
        Public x As Integer
        Public y As Integer
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
    Private Structure MouseHookStruct
        Public pt As Point
        Public hwnd As Integer
        Public wHitTestCode As Integer
        Public dwExtraInfo As Integer
    End Structure
    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Private Shared Function CallNextHookEx( _
         ByVal idHook As Integer, _
         ByVal nCode As Integer, _
         ByVal wParam As IntPtr, _
          ByVal lParam As IntPtr) As Integer
    End Function
    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)> _
     Private Shared Function SetWindowsHookEx _
          (ByVal idHook As Integer, ByVal HookProc As MouseHookCallback, _
           ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
    End Function
    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)> _
    Private Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Integer
    End Function
    Private Function MouseHookProc(ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer
        If nCode < 0 Then
            Return CallNextHookEx(MouseHookID, nCode, wParam, lParam)
        End If
        Dim MouseData As MouseHookStruct = Marshal.PtrToStructure(lParam, GetType(MouseHookStruct))
        Select Case wParam
            Case MouseMessages.WM_LeftButtonUp
                RaiseEvent MouseLeftButtonClick(Nothing, New MouseEventArgs(MouseButtons.Left, 1, MouseData.pt.x, MouseData.pt.y, 0))
            Case MouseMessages.WM_RightButtonUp
                RaiseEvent MouseRightButtonClick(Nothing, New MouseEventArgs(MouseButtons.Right, 1, MouseData.pt.x, MouseData.pt.y, 0))
        End Select
        Return CallNextHookEx(MouseHookID, nCode, wParam, lParam)
    End Function
End Class
导入System.Runtime.InteropServices
输入系统。反射
导入System.Windows.Forms
公共类鼠标检测器
公共事件MouseLeftButtonClick(ByVal sender作为对象,ByVal e作为MouseEventArgs)
公共事件MouseRightButtonClick(ByVal sender作为对象,ByVal e作为MouseEventArgs)
私有委托函数MouseHookCallback(ByVal nCode为整数,ByVal wParam为整数,ByVal lParam为IntPtr)为整数
专用MouseHookCallback代理作为MouseHookCallback
作为整数的私有MouseHookID
公共分新()
如果MouseHookID=0,则
MouseHookCallbackDelegate=MouseHookProc的地址
MouseHookID=SetWindowsHookEx(CInt(14),MouseHookCallbackDelegate,Marshal.GetHINSTANCE(Assembly.getExecutionGassembly.GetModules()(0)),0)
如果MouseHookID=0,则
“错误
如果结束
如果结束
端接头
公共分包商()
如果不是MouseHookID=-1,则
unhookwindowshookx(MouseHookID)
MouseHookCallbackDelegate=无
如果结束
MouseHookID=-1
端接头
私有枚举鼠标消息
WM_LeftButtonDown=513
WM_LeftButtonUp=514
WM_LeftDblClick=515
WM_RightButtonDown=516
WM_RightButtonUp=517
WM_RightDblClick=518
结束枚举
_
私有结构点
公共x作为整数
公共y作为整数
端部结构
_
私有结构MouseHookStruct
公共pt作为点
作为整数的公共hwnd
作为整数的公共代码
公共dwExtraInfo作为整数
端部结构
_
私有共享函数CallNextHookEx(_
ByVal idHook作为整数_
ByVal nCode作为整数_
ByVal wParam作为IntPtr_
ByVal lParam(作为IntPtr)作为整数
端函数
_
私有共享函数SetWindowsHookEx_
(ByVal idHook作为整数,ByVal HookProc作为MouseHookCallback_
ByVal hInstance作为IntPtr,ByVal wParam作为Integer)作为Integer
端函数
_
私有共享函数unhookwindowshookx(ByVal idHook作为整数)作为整数
端函数
私有函数MouseHookProc(ByVal nCode为整数,ByVal wParam为整数,ByVal lParam为IntPtr)为整数
如果nCode<0,则
Return CallNextHookEx(MouseHookID、nCode、wParam、lParam)
如果结束
将MouseData设置为MouseHookStruct=Marshal.PtrToStructure(lParam,GetType(MouseHookStruct))
选择案例wParam
Case MouseMessages.WM_LeftButtonUp
RaiseEvent mouseleftbutton单击(无,新的MouseEventArgs(MouseButtons.Left,1,MouseData.pt.x,MouseData.pt.y,0))
Case MouseMessages.WM_rightbutnup
RaiseEvent鼠标右键单击(无,新鼠标右键(MouseButtons.Right,1,MouseData.pt.x,MouseData.pt.y,0))
结束选择
Return CallNextHookEx(MouseHookID、nCode、wParam、lParam)
端函数
末级

以防万一它在某个时候对某人有用。。。这是基于Daniel的答案和我通过网络搜索找到的其他类似建议。这有两件事我在其他例子中没有看到#1-仅将单击处理程序添加到非输入控件,2,它递归地为包含其他控件的控件添加单击处理程序。这个有4层深

'Add Click Handler to all non-input controls
Private Sub FrmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    For Each c1 As Control In Me.Controls
        If Not c1.CanSelect Then
            AddHandler c1.MouseClick, AddressOf ClickHandler
            For Each c2 As Control In c1.Controls
                If Not c2.CanSelect Then
                    AddHandler c2.MouseClick, AddressOf ClickHandler
                    For Each c3 As Control In c2.Controls
                        If Not c3.CanSelect Then
                            AddHandler c3.MouseClick, AddressOf ClickHandler
                            For Each c4 As Control In c3.Controls
                                If Not c4.CanSelect Then
                                    AddHandler c4.MouseClick, AddressOf ClickHandler
                                End If
                            Next
                        End If
                    Next
                End If
            Next
        End If
    Next
End Sub

'Click Handler
Private Sub ClickHandler(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
    MsgBox("Do something!!!")
End Sub

表单点击事件如何?您如何创建自定义菜单?您正在创建一个窗体作为菜单吗?不,菜单不是窗体,而是一个面板。我尝试了Mdi和正则形式,但都没有达到我的目的。他们都有注意力和控制力的问题。因此,面板似乎是目前最好的方式。form.click事件仅在您未单击其他控件时才会触发。引用:“但菜单基本上是一个面板”。你做得根本不对,菜单应该是一个顶级窗口。如果您想拯救它,那么您需要使用Capture属性。显示面板时,将其设置为true。您将获得所有鼠标事件,甚至是面板之外的事件。这仅在他单击窗体而不是其他控件(如其他按钮)时有效。谢谢Daniel,但这似乎有点不切实际,因为我的许多控件都是动态创建的。每次创建新控件时,我都必须运行这个。还有,很多控制