无法在Wpf画布上从右下角到左上角绘制矩形

无法在Wpf画布上从右下角到左上角绘制矩形

问题描述:

我正在实现允许用户在运行时通过拖动鼠标在Wpf画布上绘制矩形的功能。我当前能够绘制矩形当我从拖动左上角下鼠标左键,但是当我拖动矩形是不可见从左下角到top.Below鼠标是我使用的XAML代码:无法在Wpf画布上从右下角到左上角绘制矩形

<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) 
    { 

    } 
} 
+0

@Sinatr我不想画第二个矩形,只是要移动现有的矩形。 –

+0

@Sinatr我的意思是绘制矩形,就像我们在绘画工具中做的一样。按下鼠标按钮并拖动以绘制矩形。如果在向下对角线方向(UL到LR)中拖动,则它起作用,但如果我们向上对角线方向拖动(LR到UL),则该矩形不可见。 –

更好的使用路径与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个角。所以这很复杂。

最简单的方法是简单地记住开始鼠标的位置,然后检查哪里是位置,他们之间绘制矩形。显然,新的鼠标位置可以是任一角落,取决于鼠标相对于起点移动的方向。

所以:

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将处理调整为正或负的改变,而改变位置,我们还需要一个条件检查,以确定哪个点,开始或新的鼠标,是左上角。

演示:

+0

我唯一缺少的就是存储起点。谢谢。 –

+0

“最简单的方法..”,不完全是。更简单的是从两个点创建一个Rect。无论每个Point表示什么确切的角落,Rect将始终正确创建(如我的答案中所示)。 – Clemens

+0

@Clemens,这只是措辞。我喜欢你的解决方案。虽然我看不出如何使我的工作更轻松。目的不是要改变太多(至少xaml)。 – Sinatr