Profile Picture

MouseLeave and MouseEnter events fire after every MouseMove event

Posted By Lance Levendowski 8 Years Ago

MouseLeave and MouseEnter events fire after every MouseMove event

Author
Message
Lance Levendowski
Posted 8 Years Ago
View Quick Profile
Forum Newbie

Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)

Group: Forum Members
Last Active: 6 Months Ago
Posts: 60, Visits: 157
NChartControls fire MouseLeave and MouseEnter events after every MouseMove event when NChartControl.Settings.RenderSurface = window.

Is there any way to prevent this behavior?

Run the following example to reproduce the issue.
Public Class MouseEventsForm
  Inherits Windows.Forms.Form

  Private WithEvents _ChartControl1 As Nevron.Chart.WinForm.NChartControl
  Private WithEvents _CheckBox1 As Windows.Forms.CheckBox
  Private WithEvents _CheckBox2 As Windows.Forms.CheckBox
  Private WithEvents _TextBox1 As Windows.Forms.TextBox

  Public Sub New()
    Me.Size = New Drawing.Size(1200, 824)
    Me.StartPosition = FormStartPosition.CenterScreen

    Dim chart As New Nevron.Chart.NCartesianChart
    chart.Enable3D = True
    chart.Projection.SetPredefinedProjection(Nevron.GraphicsCore.PredefinedProjection.Orthogonal)
    Call AddLineSeries(250, 0.5#, Drawing.Color.Black, chart)

    Dim chartBounds As New Drawing.Rectangle(0, 0, Me.ClientSize.Width - 300, Me.ClientSize.Height - 24)
    Me._ChartControl1 = New Nevron.Chart.WinForm.NChartControl
    Me._ChartControl1.Charts.Clear()
    Me._ChartControl1.Charts.Add(chart)
    Me._ChartControl1.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Right Or AnchorStyles.Bottom
    Me._ChartControl1.Bounds = chartBounds
    Me._ChartControl1.Settings.JitterMode = Nevron.Chart.JitterMode.Disabled
    Me._ChartControl1.Settings.RenderSurface = Nevron.GraphicsCore.RenderSurface.Window
    '
    Me.Controls.Add(Me._ChartControl1)

    Me._CheckBox1 = New Windows.Forms.CheckBox
    Me._CheckBox1.Text = "Render to Window"
    Me._CheckBox1.Location = New Drawing.Point(0, Me._ChartControl1.Bottom)
    Me._CheckBox1.AutoSize = True
    Me._CheckBox1.Anchor = AnchorStyles.Left Or AnchorStyles.Bottom
    Me._CheckBox1.Checked = (Me._ChartControl1.Settings.RenderSurface = Nevron.GraphicsCore.RenderSurface.Window)
    Me.Controls.Add(Me._CheckBox1)

    Me._CheckBox2 = New Windows.Forms.CheckBox
    Me._CheckBox2.Text = "Include MouseMove Events"
    Me._CheckBox2.Location = New Drawing.Point(Me._CheckBox1.Right + 4, Me._ChartControl1.Bottom)
    Me._CheckBox2.AutoSize = True
    Me._CheckBox2.Anchor = AnchorStyles.Left Or AnchorStyles.Bottom
    Me._CheckBox2.Checked = False
    Me.Controls.Add(Me._CheckBox2)

    Me._TextBox1 = New Windows.Forms.TextBox
    Me._TextBox1.Text = ""
    Me._TextBox1.Multiline = True
    Me._TextBox1.MaxLength = System.Int32.MaxValue
    Me._TextBox1.Bounds = New Drawing.Rectangle(Me._ChartControl1.Right + 4, Me._ChartControl1.Top, Me.ClientSize.Width - (Me._ChartControl1.Right + 4), Me._ChartControl1.Height)
    Me._TextBox1.ScrollBars = ScrollBars.Both
    Me._TextBox1.Anchor = AnchorStyles.Right Or AnchorStyles.Top Or AnchorStyles.Bottom
    Me.Controls.Add(Me._TextBox1)
  End Sub
  Private Sub AddLineSeries( _
    ByVal count As Integer, _
    ByVal phaseOffset As Double, _
    ByVal color As Drawing.Color, _
    ByVal chart As Nevron.Chart.NCartesianChart)

    Dim series As New Nevron.Chart.NLineSeries
    series.DataLabelStyle.Visible = False
    series.BorderStyle.Color = color
    series.BorderStyle.Width = New Nevron.GraphicsCore.NLength(2.5!)
    '
    Call Me.AddLineData(count, phaseOffset, series)

    chart.Series.Add(series)
  End Sub
  Private Sub AddLineData( _
    ByVal count As Integer, _
    ByVal phaseOffset As Double, _
    ByVal series As Nevron.Chart.NLineSeries)

    Dim prevYVal As Double = 0
    Dim prevXVal As Double = 0

    Dim valueCount As Integer = series.Values.Count

    If valueCount > 0 Then
      prevYVal = CDbl(series.Values(valueCount - 1))
      prevXVal = CDbl(series.XValues(valueCount - 1))
    End If

    Dim xValues As Double() = New Double(count - 1) {}
    Dim yValues As Double() = New Double(count - 1) {}

    Const constValue As Double = 0.5# 'Replaces the random value from the example.
    Dim magnitude As Double = 0.01 + constValue * 5

    ' continuous
    Dim angle As Double = 2 * Math.PI * phaseOffset
    Dim phase As Double = 10 * (Math.PI * 2 * constValue) / count + 0.0001

    Dim i As Integer = 0
    Do While i < count
      Dim yStep As Double = Math.Sin(angle) * magnitude
      Dim xStep As Double = 0.01 + constValue * magnitude

      If xStep < 0 Then
        xStep = 0
      End If

      angle += phase
      prevXVal += xStep

      yValues(i) = prevYVal + yStep
      xValues(i) = prevXVal
      i += 1
    Loop

    series.Values.AddRange(yValues)
    series.XValues.AddRange(xValues)
  End Sub

  Private Sub _CheckBox1_CheckedChanged(sender As Object, e As System.EventArgs) Handles _CheckBox1.CheckedChanged
    If (Me._TextBox1 IsNot Nothing) Then
      Me._TextBox1.Text = ""
    End If
    If (Me._CheckBox1.Checked) Then
      Me._ChartControl1.Settings.RenderSurface = Nevron.GraphicsCore.RenderSurface.Window
    Else
      Me._ChartControl1.Settings.RenderSurface = Nevron.GraphicsCore.RenderSurface.Bitmap
    End If
  End Sub

  Private Sub _ChartControl1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles _ChartControl1.MouseDown
    Static cnt As Integer : cnt += 1
    Call Me.AddMessage(System.String.Format("{0} MouseDown", cnt.ToString("000")))
  End Sub
  Private Sub _ChartControl1_MouseEnter(sender As Object, e As System.EventArgs) Handles _ChartControl1.MouseEnter
    Static cnt As Integer : cnt += 1
    Call Me.AddMessage(System.String.Format("{0} MouseEnter", cnt.ToString("000")))
  End Sub
  Private Sub _ChartControl1_MouseLeave(sender As Object, e As System.EventArgs) Handles _ChartControl1.MouseLeave
    Static cnt As Integer : cnt += 1
    Call Me.AddMessage(System.String.Format("{0} MouseLeave", cnt.ToString("000")))
  End Sub
  Private Sub _ChartControl1_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles _ChartControl1.MouseMove
    Static cnt As Integer : cnt += 1
    If (Me._CheckBox2.Checked) Then
      Call Me.AddMessage(System.String.Format("{0} MouseMove", cnt.ToString("000")))
    End If
  End Sub
  Private Sub _ChartControl1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles _ChartControl1.MouseUp
    Static cnt As Integer : cnt += 1
    Call Me.AddMessage(System.String.Format("{0} MouseUp", cnt.ToString("000")))
  End Sub

  Private Sub AddMessage(ByVal message As String)
    If (Me._TextBox1.Text = "") Then
      Me._TextBox1.Text = message
    Else
      Me._TextBox1.Text = message & System.Environment.NewLine & Me._TextBox1.Text
    End If
  End Sub

End Class



Nevron Support
Posted 8 Years Ago
View Quick Profile
Supreme Being

Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)

Group: Forum Members
Last Active: Last Week
Posts: 3,054, Visits: 4,009
Hi Lance,

Thank you for pointing out this problem. It turns out windows forms generates mouse enter / leave events for every mouse move which occurs in the hardware accelerated inner window of the control. We've implemented a workaround for this behavior and will publish a SP today or tomorrow. You can then test it and check whether it fixes the problem.


Best Regards,
Nevron Support Team



Lance Levendowski
Posted 8 Years Ago
View Quick Profile
Forum Newbie

Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)

Group: Forum Members
Last Active: 6 Months Ago
Posts: 60, Visits: 157
The extra MouseLeave and MouseEnter events do not occur in build 16.5.9.12 so thank you for the quick response.

NChartControl.OnMouseLeave and NChartControl.OnMouseEnter are still being called after every MouseMove event when the NChartControl is rendering to a window.  I've implemented a workaround to account for this behavior so its not an issue at this time, but ideally those methods would only be called when appropriate.


Nevron Support
Posted 8 Years Ago
View Quick Profile
Supreme Being

Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)

Group: Forum Members
Last Active: Last Week
Posts: 3,054, Visits: 4,009
Hi Lance,

Those two methods are called from WinForms - we've also overridden them to filter unwanted Enter/Leave events. The workaround we used was:

  protected override void OnMouseLeave(EventArgs e)
  {
            // This is required because when in window mode mouse leave enter is called on every mouse move
            Point mousePosition = Control.MousePosition;

            NWin32.RECT rect = new NWin32.RECT();
            NUser32.GetWindowRect(this.Handle, ref rect);

            Rectangle windowRect = new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);

            if (!windowRect.Contains(mousePosition))
            {
                m_MouseIsOver = false;
                base.OnMouseLeave(e);

                if (m_View != null)
                {
                    m_View.Controller.OnMouseLeave(this, e);
                }
            }
  }

  protected override void OnMouseEnter(EventArgs e)
  {
            // This is required because when in window mode mouse leave enter is called on every mouse move
            if (!m_MouseIsOver)
            {
                m_MouseIsOver = true;

                base.OnMouseEnter(e);

                if (m_View != null)
                {
                    m_View.Controller.OnMouseEnter(this, e);
                }
            }
  }

probably you did something similar...




Best Regards,
Nevron Support Team



Lance Levendowski
Posted 8 Years Ago
View Quick Profile
Forum Newbie

Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)Forum Newbie (0 reputation)

Group: Forum Members
Last Active: 6 Months Ago
Posts: 60, Visits: 157
Yes, I did something similar.  Thanks for sharing your code!





Similar Topics


Reading This Topic