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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18495880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 14:50:29  来源:igfitidea点击:

in vb.net is there an event listener for clicking outside a button?

vb.neteventsmouseevent

提问by John

I am creating a customized menu and I want the menu to close when the user clicks anywhere else on the form. I tried using .LostFocus, but that only works if the thing they click on can take the focus. Lots of things don't take focus and therefore the menu stays open. I need a listener on the button that says, "if the mouse was clicked and it wasn't on you, then do something (close)".

我正在创建一个自定义菜单,我希望在用户单击表单上的任何其他位置时关闭菜单。我尝试使用 .LostFocus,但只有当他们点击的东西可以成为焦点时才有效。很多事情都没有得到关注,因此菜单保持打开状态。我需要一个按钮上的监听器说,“如果鼠标被点击并且它不在你身上,那么做一些事情(关闭)”。

Any suggestions?

有什么建议?

Thanks.

谢谢。

回答by Daniel Abou Chleih

You could create a MouseDown-Eventhandler for every Control in your form

您可以为表单中的每个控件创建一个 MouseDown-Eventhandler

    For Each c As Control In Me.Controls
        AddHandler c.MouseDown, AddressOf c_MouseDown
    Next

Then check if the sender of the event is not your button

然后检查事件的发送者是否不是您的按钮

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

Edit: Of course you have to create an eventhandler for the form too

编辑:当然你也必须为表单创建一个事件处理程序

AddHandler Me.MouseDown, AddressOf c_MouseDown

Best to put the handler in the constructor

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

回答by Karl Anderson

Setup the MouseClickevent handler in the form constructor, like this:

MouseClick在表单构造函数中设置事件处理程序,如下所示:

Public Sub New()
    Me.MouseClick += mouseClick
End Sub

Then you can write your event handler code, like this:

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

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

回答by John

Thanks for the info, but I solved my question by using the code on this page:

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

http://www.daniweb.com/software-development/vbnet/threads/369609/detecting-a-mouse-click

http://www.daniweb.com/software-development/vbnet/threads/369609/detecting-a-mouse-click

Apparently using a Hook is the only way to detect ANY mouse click. It even detects clicks outside of my program.

显然,使用 Hook 是检测任何鼠标点击的唯一方法。它甚至可以检测到我的程序之外的点击。

回答by user3829572

The only way to do it is with the hook.

唯一的方法是使用钩子。

Here is some code. You should still read up on it. And you will need to go to project / properties / Debug and uncheck enable the visual studio hosting process checkbox.

这是一些代码。你仍然应该仔细阅读它。您需要转到项目/属性/调试并取消选中启用 Visual Studio 托管进程复选框。

This code will count all your left and right mouse clicks anywhere on the screen while the form is running.

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

For the Form you want it in:

对于您想要的表格:

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

Add a class to the project and name it MouseDetector and copy the following code into it.

在项目中添加一个类并将其命名为 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

回答by Sirmqc

Just in case its useful to someone at some point... This builds on Daniel's answer and other similar suggestions I've found via a web search. This does 2 things I didn't see in other examples. #1 - only add the click handler to non-input controls, and #2, it recursively adds the click handler for controls that contain other controls. This one goes 4 levels deep.

以防万一它在某些时候对某人有用......这建立在丹尼尔的回答和我通过网络搜索找到的其他类似建议的基础上。这做了两件我在其他例子中没有看到的事情。#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