鼠标按下或基于鼠标按钮更新控制光标

Posted

技术标签:

【中文标题】鼠标按下或基于鼠标按钮更新控制光标【英文标题】:Update Control Cursor on Mouse Down or based on Mouse Button 【发布时间】:2019-03-22 16:10:53 【问题描述】:

当鼠标左键 = 鼠标左键时,我无法在鼠标移动事件中更改鼠标光标。

在“文本控制坐标”文本框中的 gif 图像中,您可以看到我正在更新此文本框,其中输入了光标应该更新到的内容。这是底部框中的最后一个条目。光标设置为“SizeAll”,但是当我使用鼠标左键移动控件时,我有代码将控件光标设置为“手”。文本框显示正确达到了将光标更新为“手”的逻辑。问题是光标仅在我释放鼠标左键后才会更新。它会一直这样做,直到我再次开始移动鼠标并且 MouseMove 事件再次接管为止。

Private Sub ClsTextObj_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    ' Get object under cursor when user moved mouse - MouseMove
    ' We are only going to perform the WORK if the object is TypeOf clsTextObj
    If TypeOf sender Is clsTextObj Then
        Dim txt_clsText_ctrl_tmp = DirectCast(sender, clsTextObj)

        'Declare Bool to determine if Left Mouse Button is being used
        Dim IsMouseLeftButton = e.Button = Windows.Forms.MouseButtons.Left

        Dim mCursor As Cursor
        Dim MouseCursor = "Logic Never Reached"

        'Set mCursor var to the hand cursor when the LEFT Mouse Button is being used
        If IsMouseLeftButton Then
            MouseCursor = "Hand"
            mCursor = Cursors.Hand
        Else
            MouseCursor = "SizeAll"
            mCursor = Cursors.SizeAll
        End If

        'START Determine Mouse Cursor - Find where the mouse cursor is within the control
        Dim MouseIsInLeftEdge As Boolean
        Dim MouseIsInRightEdge As Boolean
        Dim MouseIsInTopEdge As Boolean
        Dim MouseIsInBottomEdge As Boolean

        MouseIsInLeftEdge = Math.Abs(e.X) <= 9
        MouseIsInRightEdge = Math.Abs(e.X - txt_clsText_ctrl_tmp.Width) <= 9
        MouseIsInTopEdge = Math.Abs(e.Y) <= 9
        MouseIsInBottomEdge = Math.Abs(e.Y - txt_clsText_ctrl_tmp.Height) <= 9

        If MouseIsInLeftEdge Then
            If MouseIsInTopEdge Then
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeNWSE
            ElseIf MouseIsInBottomEdge Then
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeNESW
            Else
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeWE
            End If
        ElseIf MouseIsInRightEdge Then
            If MouseIsInTopEdge Then
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeNESW
            ElseIf MouseIsInBottomEdge Then
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeNWSE
            Else
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeWE
            End If
        ElseIf (MouseIsInTopEdge Or MouseIsInBottomEdge) Then
            txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeNS
        Else
            txt_clsText_ctrl_tmp.Appearance.Cursor = mCursor
            'txt_clsText_ctrl_tmp.Appearance.Cursor = Cursor.SizeAll
        End If
        'END Determining Mouse Cursor

        'Capture Mouse Down Clicks while moving mouse cursor.  Mouse Move overrides Mouse Down basically and so we capture mouse down buttons while moving here
        'If e.Button = Windows.Forms.MouseButtons.Left Then
        If IsMouseLeftButton Then
            txt_clsText_ctrl.Appearance.Cursor = Cursors.Hand
            txt_clsText_ctrl.Location = New Point(txt_clsText_ctrl.Location.X + (e.X - initialClickLocation.X), txt_clsText_ctrl.Location.Y + (e.Y - initialClickLocation.Y))
        End If

        'Output mouse details
        ClsTextObj1.Value = "X: " & txt_clsText_ctrl_tmp.Location.X + e.X _
                          & ",Y: " & txt_clsText_ctrl_tmp.Location.Y + e.Y

        'Build User output info
        builder.Clear()
        builder.Append("Control Name: " & txt_clsText_ctrl_tmp.Name).AppendLine()
        builder.Append("e.X " & e.X & ", e.Y: " & e.Y).AppendLine()
        builder.Append("e.Point Location: " & e.Location.ToString()).AppendLine()
        builder.Append("txt_clsText_ctrl Point Location: " & txt_clsText_ctrl_tmp.Location.ToString()).AppendLine()
        builder.Append("Form Location: X=" & txt_clsText_ctrl_tmp.Location.X + e.X)
        builder.Append(",Y=" & txt_clsText_ctrl_tmp.Location.Y + e.Y & "").AppendLine()
        builder.Append("initial Ctrl Location: " & initialCtrlLocation.ToString()).AppendLine()
        builder.Append("initial Click Location: " & initialClickLocation.ToString()).AppendLine()
        builder.Append("Calc Point: " & "X: " & (e.X - initialClickLocation.X))
        builder.Append(",Y: " & (e.Y - initialClickLocation.Y)).AppendLine()
        builder.Append("New Label Pos: " & "X: " & txt_clsText_ctrl_tmp.Location.X + (e.X - initialClickLocation.X))
        builder.Append(",Y: " & txt_clsText_ctrl_tmp.Location.Y + (e.Y - initialClickLocation.Y)).AppendLine()
        builder.Append("Mouse Button: " & e.Button.ToString()).AppendLine()
        builder.Append("Left Edge: " & MouseIsInLeftEdge).AppendLine()
        builder.Append("Right Edge: " & MouseIsInRightEdge).AppendLine()
        builder.Append("Top Edge: " & MouseIsInTopEdge).AppendLine()
        builder.Append("Bottom Edge: " & MouseIsInBottomEdge).AppendLine()
        builder.Append("Cursor: " & appendMouseCursor)

        ClsTextObj2.Value = builder.ToString()

    End If
End Sub

我在这里缺少什么?在使用鼠标左键时,我可以成功更新应用程序的其他部分,但鼠标光标除外。我什至尝试在控件上使用 Refresh() 以及其他一些在控件移动时似乎从未让光标变成手的愚蠢想法。

您甚至可以看到我在 MouseMove Sub 中根据控件的边缘成功更新了鼠标光标。但是,当按下鼠标左键时,就好像鼠标光标的更新被暂停,直到我松开按钮。

10.19.18 更新: 我改用了表单光标:

If IsMouseLeftButton And IsMouseDown Then
        Me.Cursor = Cursors.Hand
        'txt_clsText_ctrl.Appearance.Cursor = Cursors.Hand
        txt_clsText_ctrl.Location = New Point(txt_clsText_ctrl.Location.X + (e.X - initialClickLocation.X), txt_clsText_ctrl.Location.Y + (e.Y - initialClickLocation.Y))
End If

由于我使用的是表单光标,我必须确保将其更新回默认值。我发现 MouseUp 可以很好地解决这个问题。至少我还没有遇到任何错误。

Private Sub ClsTextObj_MouseUp(sender As Object, e As MouseEventArgs)
    If TypeOf sender Is STORE.PDFBuilder.clsTextObj Then
        Dim txt_clsText_ctrl_tmp = DirectCast(sender, STORE.PDFBuilder.clsTextObj)

        IsMouseDown = False
        Me.Cursor = Cursors.Default

    End If
End Sub

最后,对于任何普通 .NET 控件,您都可以使用相同的代码,但我不必使用 Control.Appearance.Cursor ---> 您可以使用 Control.Cursor

【问题讨论】:

什么是clsTextObj? TextBox 派生类?它的Appearance 属性有什么作用?设置/定义光标类型/样式?您应该检查该代码。 这部分“Dim IsMouseLeftButton = e.Button = Windows.Forms.MouseButtons.Left”是否正常工作? 我支持的应用程序使用了由 Infragisitcs 公司创建的 3rd Part Controls。我写了一些与我现在在 C# 中所做的非常相似的东西,但它使用标准的 .NET 控件并且运行良好。 @Jimi 让我想到,由于 Appearance 属性中我无法访问的代码,我应该改用表单光标。我更新了我的代码,以在使用鼠标左键时将表单光标更新为手。这非常有效。 【参考方案1】:

在 Jimi 的推动下,我改为使用表单光标,因为我正在使用的 Infragistics 控件无法在使用鼠标按钮时更新鼠标光标,无论出于何种原因。我改为使用表单光标。代码如下:

Private Sub ClsTextObj_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)

    ' Get object under cursor when user moved mouse - MouseMove
    ' We are only going to perform the WORK if the object is TypeOf clsTextObj
    If TypeOf sender Is clsTextObj Then
        Dim txt_clsText_ctrl_tmp = DirectCast(sender, clsTextObj)

        Dim IsMouseLeftButton = e.Button = Windows.Forms.MouseButtons.Left

        Dim mCursor As Cursor
        Dim MouseCursor = "Logic Never Reached"

        If IsMouseLeftButton And IsMouseDown Then
            MouseCursor = "Hand"    'Used to output info to screen
            mCursor = Cursors.Hand
        Else
            MouseCursor = "SizeAll" 'Used to output info to screen
            mCursor = Cursors.SizeAll
        End If

        'START Determine Mouse Cursor - Find where the mouse cursor is within the control
        Dim MouseIsInLeftEdge As Boolean
        Dim MouseIsInRightEdge As Boolean
        Dim MouseIsInTopEdge As Boolean
        Dim MouseIsInBottomEdge As Boolean

        MouseIsInLeftEdge = Math.Abs(e.X) <= 9
        MouseIsInRightEdge = Math.Abs(e.X - txt_clsText_ctrl_tmp.Width) <= 9
        MouseIsInTopEdge = Math.Abs(e.Y) <= 9
        MouseIsInBottomEdge = Math.Abs(e.Y - txt_clsText_ctrl_tmp.Height) <= 9

        If MouseIsInLeftEdge Then
            If MouseIsInTopEdge Then
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeNWSE
            ElseIf MouseIsInBottomEdge Then
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeNESW
            Else
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeWE
            End If
        ElseIf MouseIsInRightEdge Then
            If MouseIsInTopEdge Then
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeNESW
            ElseIf MouseIsInBottomEdge Then
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeNWSE
            Else
                txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeWE
            End If
        ElseIf (MouseIsInTopEdge Or MouseIsInBottomEdge) Then
            txt_clsText_ctrl_tmp.Appearance.Cursor = Cursors.SizeNS
        Else
            txt_clsText_ctrl_tmp.Appearance.Cursor = mCursor
        End If
        'END Determining Mouse Cursor

        'Capture Mouse Down Clicks while moving mouse cursour.  Mouse Move overrides Mouse Down basically and so we capture mouse down buttons while moving here
        'If e.Button = Windows.Forms.MouseButtons.Left Then
        If IsMouseLeftButton Then 'And IsMouseDown Then
            Me.Cursor = mCursor
            txt_clsText_ctrl.Location = New Point(txt_clsText_ctrl.Location.X + (e.X - initialClickLocation.X), txt_clsText_ctrl.Location.Y + (e.Y - initialClickLocation.Y))
        End If


        ClsTextObj1.Value = "X: " & txt_clsText_ctrl_tmp.Location.X + e.X _
                          & ",Y: " & txt_clsText_ctrl_tmp.Location.Y + e.Y

        'Build User output info
        builder.Clear()
        builder.Append("Control Name: " & txt_clsText_ctrl_tmp.Name).AppendLine()
        builder.Append("e.X " & e.X & ", e.Y: " & e.Y).AppendLine()
        builder.Append("e.Point Location: " & e.Location.ToString()).AppendLine()
        builder.Append("txt_clsText_ctrl Point Location: " & txt_clsText_ctrl_tmp.Location.ToString()).AppendLine()
        builder.Append("Form Location: X=" & txt_clsText_ctrl_tmp.Location.X + e.X)
        builder.Append(",Y=" & txt_clsText_ctrl_tmp.Location.Y + e.Y & "").AppendLine()
        builder.Append("initial Ctrl Location: " & initialCtrlLocation.ToString()).AppendLine()
        builder.Append("initial Click Location: " & initialClickLocation.ToString()).AppendLine()
        builder.Append("Calc Point: " & "X: " & (e.X - initialClickLocation.X))
        builder.Append(",Y: " & (e.Y - initialClickLocation.Y)).AppendLine()
        builder.Append("New Label Pos: " & "X: " & txt_clsText_ctrl_tmp.Location.X + (e.X - initialClickLocation.X))
        builder.Append(",Y: " & txt_clsText_ctrl_tmp.Location.Y + (e.Y - initialClickLocation.Y)).AppendLine()
        builder.Append("Mouse Button: " & e.Button.ToString()).AppendLine()
        builder.Append("Left Edge: " & MouseIsInLeftEdge).AppendLine()
        builder.Append("Right Edge: " & MouseIsInRightEdge).AppendLine()
        builder.Append("Top Edge: " & MouseIsInTopEdge).AppendLine()
        builder.Append("Bottom Edge: " & MouseIsInBottomEdge).AppendLine()
        builder.Append("Cursor: " & MouseCursor).AppendLine()
        builder.Append("Is Mouse Down: " & IsMouseDown).AppendLine()
        builder.Append("Is Mouse Left: " & IsMouseLeftButton)

        ClsTextObj2.Value = builder.ToString()

    End If

End Sub

Private Sub ClsTextObj_MouseDown(sender As Object, e As MouseEventArgs)
    ' Get object under cursor when user clicked MouseDown
    If TypeOf sender Is clsTextObj Then

        initialClickLocation = New Point(e.X, e.Y)

        txt_clsText_ctrl = DirectCast(sender, clsTextObj)

        IsMouseDown = True

        initialCtrlLocation = txt_clsText_ctrl.Location

        'ListView Stuff
        updateListView()

    End If
End Sub

Private Sub ClsTextObj_MouseUp(sender As Object, e As MouseEventArgs)

    IsMouseDown = False
    Me.Cursor = Cursors.Default

End Sub

通过一些额外的代码,我终于得到了我需要的东西:

【讨论】:

以上是关于鼠标按下或基于鼠标按钮更新控制光标的主要内容,如果未能解决你的问题,请参考以下文章

鼠标按下时CSS光标更改不起作用

第十三周

第十三周总结

如何在Mac上使用鼠标键来控制指针?技巧来啦

鼠标坏了,怎样用键盘操作电脑呢?

鼠标与滚轮事件