所以,我正在WPF中创建类似程序的绘画。 在画布上,我有以下功能:
为实现这一目标,我有3个活动:MouseDown
,MouseMove
,MouseUp
当我开始在画布上绘图时,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
}
}
}
答案 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
}
}