C#WPF MouseUp事件未被触发

时间:2015-11-27 12:40:54

标签: c# wpf canvas mouseup

所以,我正在WPF中创建类似程序的绘画。 在画布上,我有以下功能:

  • 画一条线
  • 移动一行
  • 旋转一行

为实现这一目标,我有3个活动:MouseDownMouseMoveMouseUp

当我开始在画布上绘图时,MouseDown&完全触发MouseMove事件。但是,MouseUp未被触发...当我在移动时绘图时会出现此问题。在触发所有事件后调用draw函数时,它工作正常。

Redraw功能中的注释部分搞乱了MouseUp事件。评论时,该活动正常运作

代码:

namespace Roomplanner.Controls
{
    /// <summary>
    /// Interaction logic for DrawingControl.xaml
    /// </summary>
    public partial class DrawingControl : UserControl
    {
        //Size settings
        private double _zoomLevel = 1.1;
        private int _mapWidth = 765;
        private int _mapHeight = 430;
        private static MouseState _mouseState = MouseState.Idle;

        //Wall variables
        private List<Point> Pt1 = new List<Point>();
        private List<Point> Pt2 = new List<Point>();
        private Point _NewPt1, _NewPt2;
        private bool _isDrawing = false;


        private const int object_radius = 3;

        // We're over an object if the distance squared
        // between the mouse and the object is less than this.
        private const int over_dist_squared = object_radius * object_radius;

        public DrawingControl()
        {
            //Automated
            InitializeComponent();

            //
            drawingCanvas.Width     = _mapWidth;
            drawingCanvas.Height    = _mapHeight;

            drawingCanvas.MouseWheel += DrawingCanvas_MouseWheel;


        }


        //==================================================================================
        //MOUSE FUNCTIONS
        //==================================================================================
        private void DrawingCanvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            // See what we're over.
            Point hit_point;
            int segment_number;

            if (MouseIsOverEndpoint(Mouse.GetPosition(drawingCanvas), out segment_number, out hit_point))
            {
                // Start moving this end point.
                drawingCanvas.MouseMove -= DrawingCanvas_MouseMove_NotDown;
                drawingCanvas.MouseMove += DrawingCanvas_MouseMove_MovingEndPoint;
                drawingCanvas.MouseUp += DrawingCanvas_MouseUp_MovingEndPoint;

                // Remember the segment number.
                MovingSegment = segment_number;

                // See if we're moving the start end point.
                MovingStartEndPoint = (Pt1[segment_number].Equals(hit_point));

                // Remember the offset from the mouse to the point.
                OffsetX = hit_point.X - e.GetPosition(drawingCanvas).X;
                OffsetY = hit_point.Y - e.GetPosition(drawingCanvas).Y;
            }
            else if (MouseIsOverSegment(Mouse.GetPosition(drawingCanvas), out segment_number))
            {
                // Start moving this segment.
                drawingCanvas.MouseMove -= DrawingCanvas_MouseMove_NotDown;
                drawingCanvas.MouseMove += DrawingCanvas_MouseMove_MovingSegment;
                drawingCanvas.MouseUp += DrawingCanvas_MouseUp_MovingSegment;

                // Remember the segment number.
                MovingSegment = segment_number;

                // Remember the offset from the mouse to the segment's first point.
                OffsetX = Pt1[segment_number].X - e.GetPosition(drawingCanvas).X;
                OffsetY = Pt1[segment_number].Y - e.GetPosition(drawingCanvas).Y;
            }
            else
            {
                // Start drawing a new segment.
                drawingCanvas.MouseMove -= DrawingCanvas_MouseMove_NotDown;
                drawingCanvas.MouseMove += DrawingCanvas_MouseMove_Drawing;
                drawingCanvas.MouseUp += DrawingCanvas_MouseUp_Drawing;

                _isDrawing = true;
                _NewPt1 = new Point(e.GetPosition(drawingCanvas).X, e.GetPosition(drawingCanvas).Y);
                _NewPt2 = new Point(e.GetPosition(drawingCanvas).X, e.GetPosition(drawingCanvas).Y);
            }
        }
        // We're drawing a new segment.
        private void DrawingCanvas_MouseMove_Drawing(object sender, MouseEventArgs e)
        {
            // Save the new point.
            _NewPt2 = new Point(e.GetPosition(drawingCanvas).X, e.GetPosition(drawingCanvas).Y);

            // Redraw.
            Redraw();

        }

        // Stop drawing.
        private void DrawingCanvas_MouseUp_Drawing(object sender, MouseEventArgs e)
        {
            _isDrawing = false;
            Console.WriteLine("UP");
            // Reset the event handlers.
            drawingCanvas.MouseMove -= DrawingCanvas_MouseMove_Drawing;
            drawingCanvas.MouseMove += DrawingCanvas_MouseMove_NotDown;
            drawingCanvas.MouseUp -= DrawingCanvas_MouseUp_Drawing;

            // Create the new segment.
            Pt1.Add(_NewPt1);
            Pt2.Add(_NewPt2);

            // Redraw.
            Redraw();
        }


        private void DrawingCanvas_MouseMove_NotDown(object sender, MouseEventArgs e)
        {

            //See what we're hovering
            Point hit_point;
            int segment_number;
            Point curpos = Mouse.GetPosition(drawingCanvas);

            if (MouseIsOverEndpoint(curpos, out segment_number, out hit_point))
                Cursor = Cursors.Arrow;
            else if (MouseIsOverSegment(curpos, out segment_number))
                Cursor = Cursors.Hand;
        }

        private void DrawingCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if(e.Delta > 0)
            {
                sourceGridST.ScaleX *= _zoomLevel;
                sourceGridST.ScaleY *= _zoomLevel;
            }
            else
            {
                sourceGridST.ScaleX /= _zoomLevel;
                sourceGridST.ScaleY /= _zoomLevel;
            }
        }

        // The segment we're moving or the segment whose end point we're moving.
        private int MovingSegment = -1;

        // The end point we're moving.
        private bool MovingStartEndPoint = false;

        // The offset from the mouse to the object being moved.
        private double OffsetX, OffsetY;

        // See if the mouse is over an end point.
        private bool MouseIsOverEndpoint(Point mouse_pt, out int segment_number, out Point hit_pt)
        {
            for (int i = 0; i < Pt1.Count; i++)
            {
                // Check the starting point.
                if (FindDistanceToPointSquared(mouse_pt, Pt1[i]) < over_dist_squared)
                {
                    // We're over this point.
                    segment_number = i;
                    hit_pt = Pt1[i];
                    return true;
                }

                // Check the end point.
                if (FindDistanceToPointSquared(mouse_pt, Pt2[i]) < over_dist_squared)
                {
                    // We're over this point.
                    segment_number = i;
                    hit_pt = Pt2[i];
                    return true;
                }
            }

            segment_number = -1;
            hit_pt = new Point(-1, -1);
            return false;
        }

        // See if the mouse is over a line segment.
        private bool MouseIsOverSegment(Point mouse_pt, out int segment_number)
        {
            for (int i = 0; i < Pt1.Count; i++)
            {
                // See if we're over the segment.
                Point closest;
                if (FindDistanceToSegmentSquared(
                    mouse_pt, Pt1[i], Pt2[i], out closest)
                        < over_dist_squared)
                {
                    // We're over this segment.
                    segment_number = i;
                    return true;
                }
            }

            segment_number = -1;
            return false;
        }

        #region "Moving End Point"

        // We're moving an end point.
        private void DrawingCanvas_MouseMove_MovingEndPoint(object sender, MouseEventArgs e)
        {
            // Move the point to its new location.
            if (MovingStartEndPoint)
                Pt1[MovingSegment] =
                    new Point(e.GetPosition(drawingCanvas).X + OffsetX, e.GetPosition(drawingCanvas).Y + OffsetY);
            else
                Pt2[MovingSegment] =
                    new Point(e.GetPosition(drawingCanvas).X + OffsetX, e.GetPosition(drawingCanvas).Y + OffsetY);

            // Redraw.
            Redraw();

        }

        // Stop moving the end point.
        private void DrawingCanvas_MouseUp_MovingEndPoint(object sender, MouseEventArgs e)
        {
            // Reset the event handlers.
            drawingCanvas.MouseMove += DrawingCanvas_MouseMove_NotDown;
            drawingCanvas.MouseMove -= DrawingCanvas_MouseMove_MovingEndPoint;
            drawingCanvas.MouseUp -= DrawingCanvas_MouseUp_MovingEndPoint;

            // Redraw.
            Redraw();
        }

        #endregion // Moving End Point

        #region "Moving Segment"

        // We're moving a segment.
        private void DrawingCanvas_MouseMove_MovingSegment(object sender, MouseEventArgs e)
        {
            // See how far the first point will move.
            double new_x1 = e.GetPosition(drawingCanvas).X + OffsetX;
            double new_y1 = e.GetPosition(drawingCanvas).Y + OffsetY;

            double dx = new_x1 - Pt1[MovingSegment].X;
            double dy = new_y1 - Pt1[MovingSegment].Y;

            if (dx == 0 && dy == 0) return;

            // Move the segment to its new location.
            Pt1[MovingSegment] = new Point(new_x1, new_y1);
            Pt2[MovingSegment] = new Point(
                Pt2[MovingSegment].X + dx,
                Pt2[MovingSegment].Y + dy);

            // Redraw.
            Redraw();

        }

        // Stop moving the segment.
        private void DrawingCanvas_MouseUp_MovingSegment(object sender, MouseEventArgs e)
        {
            // Reset the event handlers.
            drawingCanvas.MouseMove += DrawingCanvas_MouseMove_NotDown;
            drawingCanvas.MouseMove -= DrawingCanvas_MouseMove_MovingSegment;
            drawingCanvas.MouseUp -= DrawingCanvas_MouseUp_MovingSegment;

            // Redraw.
            Redraw();
        }

        #endregion // Moving End Point

        //==================================================================================
        //END MOUSE FUNCTIONS
        //==================================================================================

        // Calculate the distance squared between two points.
        private int FindDistanceToPointSquared(Point pt1, Point pt2)
        {
            int dx = (int)pt1.X - (int)pt2.X;
            int dy = (int)pt1.Y - (int)pt2.Y;
            return dx * dx + dy * dy;
        }

        // Calculate the distance squared between
        // point pt and the segment p1 --> p2.
        private double FindDistanceToSegmentSquared(Point pt, Point p1, Point p2, out Point closest)
        {
            float dx = (float)p2.X - (float)p1.X;
            float dy = (float)p2.Y - (float)p1.Y;
            if ((dx == 0) && (dy == 0))
            {
                // It's a point not a line segment.
                closest = p1;
                dx = (float)pt.X - (float)p1.X;
                dy = (float)pt.Y - (float)p1.Y;
                return dx * dx + dy * dy;
            }

            // Calculate the t that minimizes the distance.
            float t = (float)((pt.X - p1.X) * dx + (pt.Y - p1.Y) * dy) / (dx * dx + dy * dy);

            // See if this represents one of the segment's
            // end points or a point in the middle.
            if (t < 0)
            {
                closest = new Point(p1.X, p1.Y);
                dx = (float)pt.X - (float)p1.X;
                dy = (float)pt.Y - (float)p1.Y;
            }
            else if (t > 1)
            {
                closest = new Point(p2.X, p2.Y);
                dx = (float)pt.X - (float)p2.X;
                dy = (float)pt.Y - (float)p2.Y;
            }
            else
            {
                closest = new Point(p1.X + t * dx, p1.Y + t * dy);
                dx = (float)pt.X - (float)closest.X;
                dy = (float)pt.Y - (float)closest.Y;
            }

            return dx * dx + dy * dy;
        }


        private void DrawWalls(Line wall)
        {
            wall.Stroke = Brushes.Black;
            drawingCanvas.Children.Add(wall);

        }
        private void ChangeSize(int x, int y)
        {
            drawingCanvas.Height = y;
            drawingCanvas.Width = x;
        }

        private void Redraw()
        {
            drawingCanvas.Children.Clear();
            // Draw the segments.
            for (int i = 0; i < Pt1.Count; i++)
            {
                // Draw the segment
                Line wall = new Line();
                wall.X1 = Pt1[i].X;
                wall.X2 = Pt2[i].X;
                wall.Y1 = Pt1[i].Y;
                wall.Y2 = Pt2[i].Y;
                wall.Stroke = Brushes.Black;
                drawingCanvas.Children.Add(wall);

            }

            // Draw the end points.
            foreach (Point pt in Pt1)
            {
                Rectangle rect = new Rectangle();
                rect.Stroke = Brushes.LightGray;
                rect.Width  = 6;
                rect.Height = 6;
                Canvas.SetTop(rect, pt.Y - object_radius);
                Canvas.SetLeft(rect, pt.X - object_radius);
                drawingCanvas.Children.Add(rect);

            }
            foreach (Point pt in Pt2)
            {
                Rectangle rect = new Rectangle();
                rect.Stroke = Brushes.LightGray;
                rect.Width = 6;
                rect.Height = 6;
                Canvas.SetTop(rect, pt.Y - object_radius);
                Canvas.SetLeft(rect, pt.X - object_radius);
                drawingCanvas.Children.Add(rect);
            }

            // If there's a new segment under constructions, draw it.
            if (_isDrawing)
            {
                //When Uncommented the MouseUP event is never called
                //Line wall = new Line();
                //wall.X1 = _NewPt1.X;
                //wall.X2 = _NewPt2.Y;
                //wall.Y1 = _NewPt1.Y;
                //wall.Y2 = _NewPt2.Y;
                //wall.Stroke = Brushes.Black;
                //drawingCanvas.Children.Add(wall);       
            }
        }

        private void btnSizeChanged_Click(object sender, RoutedEventArgs e)
        {
            ChangeSize(int.Parse(tbxHeight.Text), int.Parse( tbxWidth.Text));
        }

        private void MouseMove_(object sender, MouseEventArgs e)
        {

        }

        private void btnDraw_Click(object sender, RoutedEventArgs e)
        {
            _mouseState = ( _mouseState == MouseState.DrawStart )? MouseState.DrawEnd : MouseState.DrawStart;
        }

        public enum MouseState
        {
            DrawStart, DrawEnd, Idle
        }

    }
}

1 个答案:

答案 0 :(得分:0)

也许您删除了触发事件的路径。

我通过使用队列保存最后 10 条路径解决了这个问题

Path LastPath = null;
Queue<Path> GarbagePath = new Queue<Path>(); // save last pathes
private void MainCanvas_MouseMove(object sender, MouseEventArgs e) {
    if (this.IsMouseDown == true && this.ShapeCurr == DrawShape.LINE) {
        this.EndPoint = Mouse.GetPosition(this.mainCanvas);
        if (this.LastPath != null) {
            this.GarbagePath.Enqueue(this.LastPath);
            if (this.GarbagePath.Count == 10) {
                this.mainCanvas.Children.Remove(this.GarbagePath.Dequeue());
            }
            this.LastPath.Visibility = Visibility.Hidden;
        }
        this.LastPath = this.DrawLine(this.BeginPoint, this.EndPoint); // draw
    }
}