无法在 Wpf canvas 上从右下角到左上角绘制矩形
Not able to draw rectangle on Wpf canvas from lower right corner to upper left corner
我正在实现允许用户在 运行 时间通过拖动在 Wpf canvas 上绘制矩形的功能 mouse.I 目前我能够在拖动鼠标时绘制矩形从左上角到左下角,但是当我从左下角拖动鼠标到 top.Below 时矩形不可见是我正在使用的 xaml 代码:
<Canvas x:Name="CanvasContainer" MouseLeftButtonDown="CanvasContainer_MouseLeftButtonDown" MouseLeftButtonUp="CanvasContainer_MouseLeftButtonUp" MouseMove="CanvasContainer_MouseMove" >
<Rectangle x:Name="RectangleMarker" Canvas.Left="0" Stroke="Red" Width="0" Height="0" Panel.ZIndex="1"></Rectangle>
<Line x:Name="LineMarker" Stroke="Red" X1="0" Y1="0" X2="0" Y2="0"></Line>
<Image Canvas.Left="0" Canvas.Top="0" x:Name="PdfImage" RenderTransformOrigin="0.5,0.5" MouseWheel="PdfImage_MouseWheel" ClipToBounds="True" Panel.ZIndex="0">
<Image.LayoutTransform>
<ScaleTransform ScaleX="1" ScaleY="1" CenterX="0.5" CenterY="0.5" />
</Image.LayoutTransform>
</Image>
</Canvas>
下面是根据鼠标位置更新矩形位置的事件处理。
private void CanvasContainer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
try
{
Point startPoint = Mouse.GetPosition(CanvasContainer);
Canvas.SetLeft(RectangleMarker, startPoint.X);
Canvas.SetTop(RectangleMarker,startPoint.Y);
}
catch (Exception ex)
{
}
}
private void CanvasContainer_MouseMove(object sender, MouseEventArgs e)
{
try
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Point endPoint = Mouse.GetPosition(CanvasContainer);
Point startPoint = new Point((double)RectangleMarker.GetValue(Canvas.LeftProperty), (double)RectangleMarker.GetValue(Canvas.TopProperty));
double x = Math.Min(startPoint.X, endPoint.X);
double y = Math.Min(startPoint.Y, endPoint.Y);
double width = endPoint.X - startPoint.X;
double height = endPoint.Y - startPoint.Y;
if (width < 0)
{
x = startPoint.X + width;
}
if (height < 0)
{
y = startPoint.Y + height;
}
RectangleMarker.Width = Math.Abs(width);
RectangleMarker.Height = Math.Abs(height);
if (x!=startPoint.X)
{
Canvas.SetLeft(RectangleMarker, x);
}
else if(y!=startPoint.Y)
{
Canvas.SetTop(RectangleMarker, y);
}
}
}
catch (Exception ex)
{
}
}
最好使用具有 RectangleGeometry 的路径:
<Canvas Background="Transparent"
MouseLeftButtonDown="CanvasContainer_MouseLeftButtonDown"
MouseLeftButtonUp="CanvasContainer_MouseLeftButtonUp"
MouseMove="CanvasContainer_MouseMove">
<Path Stroke="Red">
<Path.Data>
<RectangleGeometry x:Name="selectionRect"/>
</Path.Data>
</Path>
</Canvas>
后面的代码:
private Point? startPoint;
private void CanvasContainer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var element = (UIElement)sender;
element.CaptureMouse();
startPoint = e.GetPosition(element);
}
private void CanvasContainer_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
((UIElement)sender).ReleaseMouseCapture();
startPoint = null;
}
private void CanvasContainer_MouseMove(object sender, MouseEventArgs e)
{
if (startPoint.HasValue)
{
selectionRect.Rect = new Rect(
startPoint.Value, e.GetPosition((IInputElement)sender));
}
}
正如我之前在评论中提到的,您的问题不是 绘图,而是 调整大小。
调整矩形大小时,有 4 个可能的方向,4 个边和 4 个角。所以有点复杂。
最简单的方法就是记住start鼠标位置,然后检查new位置在哪里,在它们之间画矩形。显然,新的鼠标位置可以是任一角,具体取决于鼠标相对于起点移动的方向。
所以:
Point _start;
void CanvasContainer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) =>
_start = Mouse.GetPosition(CanvasContainer);
void CanvasContainer_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var mouse = Mouse.GetPosition(CanvasContainer);
Canvas.SetLeft(RectangleMarker, _start.X > mouse.X ? mouse.X : _start.X);
Canvas.SetTop(RectangleMarker, _start.Y > mouse.Y ? mouse.Y : _start.Y);
RectangleMarker.Width = Math.Abs(mouse.X - _start.X);
RectangleMarker.Height = Math.Abs(mouse.Y - _start.Y);
}
}
Math.Abs
将处理正向或负向变化的大小调整,而对于改变位置,我们仍然需要进行条件检查以确定左上角是起始点还是新鼠标点。
演示:
我正在实现允许用户在 运行 时间通过拖动在 Wpf canvas 上绘制矩形的功能 mouse.I 目前我能够在拖动鼠标时绘制矩形从左上角到左下角,但是当我从左下角拖动鼠标到 top.Below 时矩形不可见是我正在使用的 xaml 代码:
<Canvas x:Name="CanvasContainer" MouseLeftButtonDown="CanvasContainer_MouseLeftButtonDown" MouseLeftButtonUp="CanvasContainer_MouseLeftButtonUp" MouseMove="CanvasContainer_MouseMove" >
<Rectangle x:Name="RectangleMarker" Canvas.Left="0" Stroke="Red" Width="0" Height="0" Panel.ZIndex="1"></Rectangle>
<Line x:Name="LineMarker" Stroke="Red" X1="0" Y1="0" X2="0" Y2="0"></Line>
<Image Canvas.Left="0" Canvas.Top="0" x:Name="PdfImage" RenderTransformOrigin="0.5,0.5" MouseWheel="PdfImage_MouseWheel" ClipToBounds="True" Panel.ZIndex="0">
<Image.LayoutTransform>
<ScaleTransform ScaleX="1" ScaleY="1" CenterX="0.5" CenterY="0.5" />
</Image.LayoutTransform>
</Image>
</Canvas>
下面是根据鼠标位置更新矩形位置的事件处理。
private void CanvasContainer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
try
{
Point startPoint = Mouse.GetPosition(CanvasContainer);
Canvas.SetLeft(RectangleMarker, startPoint.X);
Canvas.SetTop(RectangleMarker,startPoint.Y);
}
catch (Exception ex)
{
}
}
private void CanvasContainer_MouseMove(object sender, MouseEventArgs e)
{
try
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Point endPoint = Mouse.GetPosition(CanvasContainer);
Point startPoint = new Point((double)RectangleMarker.GetValue(Canvas.LeftProperty), (double)RectangleMarker.GetValue(Canvas.TopProperty));
double x = Math.Min(startPoint.X, endPoint.X);
double y = Math.Min(startPoint.Y, endPoint.Y);
double width = endPoint.X - startPoint.X;
double height = endPoint.Y - startPoint.Y;
if (width < 0)
{
x = startPoint.X + width;
}
if (height < 0)
{
y = startPoint.Y + height;
}
RectangleMarker.Width = Math.Abs(width);
RectangleMarker.Height = Math.Abs(height);
if (x!=startPoint.X)
{
Canvas.SetLeft(RectangleMarker, x);
}
else if(y!=startPoint.Y)
{
Canvas.SetTop(RectangleMarker, y);
}
}
}
catch (Exception ex)
{
}
}
最好使用具有 RectangleGeometry 的路径:
<Canvas Background="Transparent"
MouseLeftButtonDown="CanvasContainer_MouseLeftButtonDown"
MouseLeftButtonUp="CanvasContainer_MouseLeftButtonUp"
MouseMove="CanvasContainer_MouseMove">
<Path Stroke="Red">
<Path.Data>
<RectangleGeometry x:Name="selectionRect"/>
</Path.Data>
</Path>
</Canvas>
后面的代码:
private Point? startPoint;
private void CanvasContainer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var element = (UIElement)sender;
element.CaptureMouse();
startPoint = e.GetPosition(element);
}
private void CanvasContainer_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
((UIElement)sender).ReleaseMouseCapture();
startPoint = null;
}
private void CanvasContainer_MouseMove(object sender, MouseEventArgs e)
{
if (startPoint.HasValue)
{
selectionRect.Rect = new Rect(
startPoint.Value, e.GetPosition((IInputElement)sender));
}
}
正如我之前在评论中提到的,您的问题不是 绘图,而是 调整大小。
调整矩形大小时,有 4 个可能的方向,4 个边和 4 个角。所以有点复杂。
最简单的方法就是记住start鼠标位置,然后检查new位置在哪里,在它们之间画矩形。显然,新的鼠标位置可以是任一角,具体取决于鼠标相对于起点移动的方向。
所以:
Point _start;
void CanvasContainer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) =>
_start = Mouse.GetPosition(CanvasContainer);
void CanvasContainer_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var mouse = Mouse.GetPosition(CanvasContainer);
Canvas.SetLeft(RectangleMarker, _start.X > mouse.X ? mouse.X : _start.X);
Canvas.SetTop(RectangleMarker, _start.Y > mouse.Y ? mouse.Y : _start.Y);
RectangleMarker.Width = Math.Abs(mouse.X - _start.X);
RectangleMarker.Height = Math.Abs(mouse.Y - _start.Y);
}
}
Math.Abs
将处理正向或负向变化的大小调整,而对于改变位置,我们仍然需要进行条件检查以确定左上角是起始点还是新鼠标点。
演示: