Userform VBA: 处理鼠标事件
Userform VBA: deal with mouse events
我正在开发 VBA UserForm
(在 Excel
中),它允许用户在表单内移动标签并显示另一个表单(或我将显示的 MessageBox
告诉你前面)。
仅出于这个问题的目的,这是我使用的表格:
如您所见,LABEL01
标签是表单中唯一的 control
。
然后,我开始声明一些有用的变量:
Public DOWN As Boolean 'To check if the mouse is down
Public OFF_X As Single 'Horizontal offset of the pointer inside the label
Public OFF_Y As Single 'Vertical offset of the pointer inside the label
表格由事件初始化:
Private Sub UserForm_Initialize()
LABEL01.MousePointer = 5 'Mouse pointer 5 - move
End Sub
要移动标签,我正在使用事件:
Private Sub LABEL01_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
DOWN = True: OFF_X = X: OFF_Y = Y
End Sub
Private Sub LABEL01_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If DOWN Then
LABEL01.Left = LABEL01.Left + X - OFF_X
LABEL01.Top = LABEL01.Top + Y - OFF_Y
End If
End Sub
Private Sub LABEL01_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
DOWN = False
End Sub
并显示我正在使用事件的 MessageBox:
Private Sub LABEL01_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
MsgBox "It's like I'm over it..."
End Sub
一切正常,唯一的问题是,当我双击 label
调用消息框时,我引发了 MouseDown
事件,并且在关闭消息框后, MouseDown/MouseMove/MouseUp
链保持不完整:
有解决这个问题的想法吗?
在 MsgBox 之后,用户窗体似乎没有意识到它重新获得了焦点(并且鼠标现在位于不同的位置)。我发现的唯一解决方法是模拟鼠标单击表单。此单击应发生在保存位置,以防止任何不需要的操作(如单击按钮)。我找到的最佳位置是在表单本身的左上角。
为此,您首先需要一个模块(您不能将代码放入表格中):
Public Type POINTAPI
X As Long
Y As Long
End Type
Public Declare Function GetCursorPos Lib "user32" (Point As POINTAPI) As Long
Public Declare Function SetCursorPos Lib "user32" (ByVal X As Integer, ByVal Y As Integer) As Long
Public Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, _
ByVal cButtons As Long, ByVal dwExtraInfo As Long)
Public Const MOUSEEVENT_LEFTDOWN = &H2
Public Const MOUSEEVENT_LEFTUP = &H4
这会访问三个例程来获取和设置鼠标位置以及模拟鼠标事件。
现在,在表单中放置一个模拟鼠标点击的 Sub,并在调用 msgBox 之后调用该例程:
Sub AdjustMouse()
Dim mousePos As POINTAPI
' Save current mouse pos
GetCursorPos mousePos
' "Move" the mouse to the top left corner of the form
SetCursorPos Me.Left + 1, Me.Top + 1
' Simulate a MouseClick so that form gets back the focus.
mouse_event MOUSEEVENT_LEFTDOWN, 0, 0, 0, 0
mouse_event MOUSEEVENT_LEFTUP, 0, 0, 0, 0
' "Move" the mouse back to the previous position
SetCursorPos mousePos.X, mousePos.Y
End Sub
我正在开发 VBA UserForm
(在 Excel
中),它允许用户在表单内移动标签并显示另一个表单(或我将显示的 MessageBox
告诉你前面)。
仅出于这个问题的目的,这是我使用的表格:
如您所见,LABEL01
标签是表单中唯一的 control
。
然后,我开始声明一些有用的变量:
Public DOWN As Boolean 'To check if the mouse is down
Public OFF_X As Single 'Horizontal offset of the pointer inside the label
Public OFF_Y As Single 'Vertical offset of the pointer inside the label
表格由事件初始化:
Private Sub UserForm_Initialize()
LABEL01.MousePointer = 5 'Mouse pointer 5 - move
End Sub
要移动标签,我正在使用事件:
Private Sub LABEL01_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
DOWN = True: OFF_X = X: OFF_Y = Y
End Sub
Private Sub LABEL01_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If DOWN Then
LABEL01.Left = LABEL01.Left + X - OFF_X
LABEL01.Top = LABEL01.Top + Y - OFF_Y
End If
End Sub
Private Sub LABEL01_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
DOWN = False
End Sub
并显示我正在使用事件的 MessageBox:
Private Sub LABEL01_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
MsgBox "It's like I'm over it..."
End Sub
一切正常,唯一的问题是,当我双击 label
调用消息框时,我引发了 MouseDown
事件,并且在关闭消息框后, MouseDown/MouseMove/MouseUp
链保持不完整:
有解决这个问题的想法吗?
在 MsgBox 之后,用户窗体似乎没有意识到它重新获得了焦点(并且鼠标现在位于不同的位置)。我发现的唯一解决方法是模拟鼠标单击表单。此单击应发生在保存位置,以防止任何不需要的操作(如单击按钮)。我找到的最佳位置是在表单本身的左上角。
为此,您首先需要一个模块(您不能将代码放入表格中):
Public Type POINTAPI
X As Long
Y As Long
End Type
Public Declare Function GetCursorPos Lib "user32" (Point As POINTAPI) As Long
Public Declare Function SetCursorPos Lib "user32" (ByVal X As Integer, ByVal Y As Integer) As Long
Public Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, _
ByVal cButtons As Long, ByVal dwExtraInfo As Long)
Public Const MOUSEEVENT_LEFTDOWN = &H2
Public Const MOUSEEVENT_LEFTUP = &H4
这会访问三个例程来获取和设置鼠标位置以及模拟鼠标事件。
现在,在表单中放置一个模拟鼠标点击的 Sub,并在调用 msgBox 之后调用该例程:
Sub AdjustMouse()
Dim mousePos As POINTAPI
' Save current mouse pos
GetCursorPos mousePos
' "Move" the mouse to the top left corner of the form
SetCursorPos Me.Left + 1, Me.Top + 1
' Simulate a MouseClick so that form gets back the focus.
mouse_event MOUSEEVENT_LEFTDOWN, 0, 0, 0, 0
mouse_event MOUSEEVENT_LEFTUP, 0, 0, 0, 0
' "Move" the mouse back to the previous position
SetCursorPos mousePos.X, mousePos.Y
End Sub