我正在创建一个自定义菜单,并且我希望在用户单击表单上的其他任何位置时关闭菜单。我尝试使用 .LostFocus,但只有当他们点击的东西能够获得焦点时才有效。很多事情都没有集中注意力,因此菜单保持打开状态。我需要一个按钮上的监听器,上面写着“如果鼠标被点击但它不在你身上,那么做一些事情(关闭)”。
有什么建议么?
谢谢。
我正在创建一个自定义菜单,并且我希望在用户单击表单上的其他任何位置时关闭菜单。我尝试使用 .LostFocus,但只有当他们点击的东西能够获得焦点时才有效。很多事情都没有集中注意力,因此菜单保持打开状态。我需要一个按钮上的监听器,上面写着“如果鼠标被点击但它不在你身上,那么做一些事情(关闭)”。
有什么建议么?
谢谢。
您可以为表单中的每个控件创建一个 MouseDown-Eventhandler
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
编辑:当然你也必须为表单创建一个事件处理程序
AddHandler Me.MouseDown, AddressOf c_MouseDown
最好将处理程序放在构造函数中
唯一的方法是使用钩子。
这是一些代码。你仍然应该阅读它。您需要转到项目/属性/调试并取消选中启用视觉工作室托管过程复选框。
此代码将计算窗体运行时屏幕上任何位置的所有鼠标左键和右键单击。
对于您想要的表格:
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
在表单构造函数中设置MouseClick
事件处理程序,如下所示:
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
感谢您提供信息,但我使用此页面上的代码解决了我的问题:
http://www.daniweb.com/software-development/vbnet/threads/369609/detecting-a-mouse-click
显然使用 Hook 是检测任何鼠标点击的唯一方法。它甚至可以检测到我的程序之外的点击。
以防万一它在某些时候对某人有用......这建立在丹尼尔的回答和我通过网络搜索找到的其他类似建议的基础上。这做了两件我在其他例子中没有看到的事情。#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