如何在MouseMove事件期间停止控件闪烁

时间:2017-07-27 18:17:56

标签: vb.net winforms charts graphics

我知道这是一个非常受欢迎的问题,但我发现的解决方案都没有对我有用。

背景:我在VS2015中有一个Windows窗体项目,它从文本文件中读取数据,并在折线图上将数据绘制为多个系列。 Chart.MouseMove事件找到离鼠标最近的点并在其周围绘制一个圆。圆圈在Chart_Paint事件中绘制

Private Sub crtLogView(sender As Object,e As PaintEventArgs) Handles crtLogView.Paint
       Dim whitePen as New Pne(Color.White,2)
       e.Graphics.DrawEllipse(whitePen,cir) '//cir is a Public Rectangle
End Sub

在图表上移动鼠标时,随机控件会闪烁然后重新开启,这非常烦人。我在下面发布了MouseMove事件代码。

我尝试过的潜在解决方案:

  • 启用表单的DoubleBuffered属性,它不执行任何操作
  • 使用Me.Invalidate()和Me.Update()方法,它不会移动圆圈
  • 使用Chart.Invalidate()和Chart.Update()方法,但是效果很慢
  • 将以下代码添加到我的Form_Load例程中,该例程似乎无效

非常感谢任何帮助

Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.DoubleBuffer, True)
Me.SetStyle(ControlStyles.UserPaint, True)

MouseMove事件代码:

 Private Sub crtLogView_MouseMove(sender As Object, e As MouseEventArgs) Handles crtLogView.MouseMove

        '//Show data for closest point to cursor & draw circle around point
        Dim hResult As HitTestResult = crtLogView.HitTest(e.X, e.Y)
        Dim srsNam As String = ""
        Dim mouseY As Single
        Dim pntDist As Double = 0
        Dim pntX As Single
        Dim pntY As Single
        Dim mouseX As Single

        On Error GoTo ErrTrap

        '//Get X-Axis Position as integer
        mouseX = Int(hResult.ChartArea.AxisX.PixelPositionToValue(e.X))
        '// Set time value
        lblTime.Text = String.Format("{0:n2}", hResult.ChartArea.AxisX.PixelPositionToValue(e.X) / 160)

        '//Get Y-Axis Position
        mouseY = hResult.ChartArea.AxisY.PixelPositionToValue(e.Y)

        '//Get distance from mouse to point on Series(0)
        pntDist = Math.Abs(crtLogView.Series(0).Points(mouseX).YValues(0) - mouseY)
        srsNam = crtLogView.Series(0).Name '//1st series name
        '//Find closest series
        For i As Integer = 1 To crtLogView.Series.Count - 1
            If Math.Abs(crtLogView.Series(i).Points(mouseX).YValues(0) - mouseY) < pntDist Then
                pntDist = Math.Abs(crtLogView.Series(i).Points(mouseX).YValues(0) - mouseY)
                srsNam = crtLogView.Series(i).Name
            End If
        Next

        '//Set Top/Left values for circle
        pntY = crtLogView.ChartAreas(0).AxisY.ValueToPixelPosition(crtLogView.Series(srsNam).Points(mouseX).YValues(0)) - 4
        pntX = crtLogView.ChartAreas(0).AxisX.ValueToPixelPosition(Val(mouseX)) - 4

        '//Move circle to closest point
        cir.Location = New Point(pntX, pntY)

        '//Refresh the form to move the circle

        '//This works, but takes 2+ seconds to take effect
        'crtLogView.Invalidate()
        'crtLogView.Update()

        '//This does not work
        'Me.Invalidate()
        'Me.Update()

        '//This works, but randomly makes other controls flash/flicker
        Me.Refresh() 
ErrTrap:
    End Sub

1 个答案:

答案 0 :(得分:0)

在评论中,我提供了一个使用图表注释或数据点标签的示例,作为在鼠标光标下的点周围自定义绘制圆圈的替代方法,并将其包含在下面的代码中。但是,我意识到DataPoint Marker应该提供OP正在寻找的功能,并且可能是正确的解决方案。因此,该选项也包括在内。

注释是图表级图形,其中 - DataPoint Label和DataPoint Marker顾名思义与各个DataPoints相关联。可以使用正确的注释大小,因为它们的大小被指定为图表区域维度的百分比。此示例不会尝试根据当前图表大小调整注释的大小。

以下代码示例适用于WinForm。在VS中,向WinForm项目添加一个新类,并用此替换自动生成的代码。将此表单设置为启动表单。

{{1}}