首页 > 解决方案 > I'm trying to move a Rectangle in a Canvas ( in a WPF app) using the Mouse event but it don't work

问题描述

I develop a wpf application and I have to move a rectangle in a canvas (and the end goal is to make sure my rectangle can not get out of the canvas). So I searched and tried many solutions on the Web, but I was not working yet. Then I tried to rewrite a solution, but it did not work.

<Grid x:Name="mainGrid">
    <Canvas x:Name="CanvasImplant" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="27,27,26,0" Height="415">
        <Rectangle x:Name="MovableShape" Opacity="0.85" Width="93" Height="62" HorizontalAlignment="left" VerticalAlignment="Top" Margin="930,140" Stroke="Black" StrockThickness="1" MouseDown="MovShp_MouseDown" MouseUp="MovShp_MouseUp" MouseMove="MovShp_MouseMove"/>
    </Canvas>
</Grid>
private bool drag = true;
private Point StartPt;
private double newX, newY;

private void MovShp_MouseDown(object sender, MouseButtonEventArgs e)
{
    drag = true;
    Cursor = Cursors.Hand;
    startPt = e.Getposition(CanvasImplant);
    Mouse.Capture((UIElement)sender);
}

private void MovShp_MouseUp(object sender, MouseButtonEventArgs e)
{
    drag = false;
    Cursor = Cursors.Arrow;
    Mouse.Capture(null);
}

private void MovShp_MouseMove(object sender, MouseButtonEventArgs e)
{
    if (drag)
    {
        double deltaX = e.GetPosition(CanvasImplant).X - startPt.X;
        double deltaY = e.GetPosition(CanvasImplant).Y - startPt.Y;

        newX = deltaX + Canvas.GetLeft(MovableShape);
        newY = deltaY + Canvas.GetTop(MovableShape);

        if (newX < 0)
            newX = 0;
        else if (newX + MovableShape.ActualWidth > CanvasImplant.ActualWidth)
            newX = CanvasImplant.ActualWidth - MovableShape.ActualWidth;

        if (newY < 0)
            newY = 0;
        else if (newY + MovableShape.ActualHeight > CanvasImplant.ActualHeight )
            newY = CanvasImplant.ActualHeight - MovableShape.ActualHeight ;

        MovableShape.SetValue(Canvas.LeftProperty, newX);
        MovableShape.SetValue(Canvas.TopProperty, newY);
    }

}

When I click on MovableShape, the mouse becomes a hand and when I release the left mouse button, it becomes an arrow, but when I drag the rectangle, it does not follow the mouse and when I release the click, it do not move.

标签: c#wpfcanvaswpf-controlsmouseevent

解决方案


有几件事。

  1. 您需要在形状上设置填充,否则您的点击事件只会在非常细的边框上触发
  2. 鼠标移动和鼠标向上事件需要是 Canvas 事件,而不是形状
  3. 您需要每次在移动事件处理程序中将 startPt 设置为新位置
  4. 您需要删除形状的边距和水平/垂直位置
  5. 您需要使用 Canvas 而不是形状来捕获鼠标

这对我有用:

    <Grid x:Name="mainGrid"  >
    <Canvas x:Name="CanvasImplant" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MouseMove="MovShp_MouseMove"  MouseUp="MovShp_MouseUp" Background="Transparent">
        <Rectangle Canvas.Left="10" Canvas.Top="20" x:Name="MovableShape" Fill="Transparent"  Opacity="0.85" Width="93" Height="62" Stroke="Black" 
                   StrokeThickness="1" MouseDown="MovShp_MouseDown" />
    </Canvas>
</Grid>

和处理程序:

private void MovShp_MouseDown(object sender, MouseButtonEventArgs e)
{
    drag = true;
    Cursor = Cursors.Hand;
    startPt = e.GetPosition(CanvasImplant);
    Mouse.Capture(CanvasImplant);
}

private void MovShp_MouseUp(object sender, MouseButtonEventArgs e)
{
    drag = false;
    Cursor = Cursors.Arrow;
    Mouse.Capture(null);
}

private void MovShp_MouseMove(object sender, MouseEventArgs e)
{
    if (drag)
    {
        var mp = e.GetPosition(CanvasImplant);
        double deltaX = mp .X - startPt.X;
        double deltaY = mp .Y - startPt.Y;

        var newX = deltaX + Canvas.GetLeft(MovableShape);
        var newY = deltaY + Canvas.GetTop(MovableShape);

        if (newX < 0)
            newX = 0;
        else if (newX + MovableShape.ActualWidth > CanvasImplant.ActualWidth)
            newX = CanvasImplant.ActualWidth - MovableShape.ActualWidth;

        if (newY < 0)
            newY = 0;
        else if (newY + MovableShape.ActualHeight > CanvasImplant.ActualHeight)
            newY = CanvasImplant.ActualHeight - MovableShape.ActualHeight;

        Canvas.SetLeft(MovableShape, newX);
        Canvas.SetTop(MovableShape, newY);

        startPt = mp ;
    }

}

推荐阅读