【问题标题】:WPF How to draw Circle on Mouse eventsWPF如何在鼠标事件上绘制圆圈
【发布时间】:2017-11-21 07:48:48
【问题描述】:

我是 WPF 新手。

我想在鼠标移动事件上在画布上画一个圆圈。我已经编写了将其拖到画布上的逻辑。但是我想在我的画布上单击鼠标时创建一个圆圈,并且它应该根据鼠标在画布上的移动来调整大小。

我怎样才能做到这一点?

这是我的代码

    Ellipse elip = new Ellipse();
    private double pointx;
    private double pointy;        

    private void canvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        canvas.MouseMove -= MouseMove_NotDown;
        canvas.MouseMove += canvas_PreviewMouseMove;
        canvas.MouseUp += canvas_PreviewMouseUp;

        Point location = e.MouseDevice.GetPosition(canvas);
        elip = new Ellipse();
        elip.Height = 1;
        elip.Width = 1;
        elip.Stroke = Brushes.Black;
        elip.StrokeThickness = 2;
        Canvas.SetTop(elip, location.Y + 1);
        Canvas.SetLeft(elip, location.X + 1);
        pointx = location.X + 1;
        pointy = location.Y + 1;
        canvas.Children.Add(elip);
    }

    private void MouseMove_NotDown(object sender, MouseEventArgs e)
    {
        canvas.Cursor = Cursors.Hand;
    }

    private void canvas_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        try
        {
            Point location = e.MouseDevice.GetPosition(canvas);
            double height = location.Y - pointy;
            double width = location.X - pointx;
            if (height >= 0 && width >= 0)
            {
                elip.Height = height;
                elip.Width = width;
            }
            else if (height < 0 || width < 0)
            {
                if (height < 0)
                {
                    elip.Height = height + (-height) + 1;
                    elip.Width = width;
                }
                else if (width < 0)
                {
                    elip.Height = height;
                    elip.Width = width + (-width) + 1;
                }
            }
        }
        catch
        {

        }
    }

    private void canvas_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        elip.Stroke = Brushes.Black;
        elip.StrokeThickness = 2;

        canvas.MouseMove -= canvas_PreviewMouseMove;
        canvas.MouseMove += MouseMove_NotDown;
        canvas.MouseUp += canvas_PreviewMouseUp;
    }

【问题讨论】:

  • 请发布您迄今为止尝试过的内容。一些指针,将您的画布背景设置为颜色(如果您不想要颜色,则为透明),否则它将不会获得鼠标单击事件。然后您将使用 MouseDown 和 MouseMove 事件处理程序。
  • 谢谢大家。我已经更新了我的代码,请看一下。提前致谢。
  • 阅读该代码的提示;监听器的所有附加和删除意味着 lot 可能会因为应该如此简单的事情而出错。尽量避免这种情况。
  • 感谢格鲁特。你能否解释一下,这将有助于我解决我的问题。当我尝试绘制第 11 个圆圈时,我最多可以使用上面的代码绘制 10 个圆圈,但它不起作用。
  • 我将在稍后发布一个示例。当您初始化控件(或窗口)时,只需附加一次侦听器会更容易。

标签: c# wpf


【解决方案1】:

最好只附加一次听众。这使您的应用程序逻辑更易于理解和调试。

如果 WPF 的 canvas 没有设置背景,它不会捕获鼠标事件,除非画布上有被点击的东西,所以 给它一个背景颜色(白色或透明是很好)

XAML:

<Window x:Class="mausing.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:mausing"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Canvas x:Name="canvas" Background="White"></Canvas>
</Grid>

C#:

public partial class MainWindow : Window
{
    private Ellipse elip = new Ellipse();
    private Point anchorPoint;

    public MainWindow()
    {
        InitializeComponent();
        canvas.MouseMove += canvas_MouseMove;
        canvas.MouseUp += canvas_MouseUp;
        canvas.MouseDown += canvas_MouseDown;
    }

    private void canvas_MouseDown(object sender, MouseButtonEventArgs e)
    {
        //capture the mouse on the canvas
        //(this also helps us keep track of whether or not we're drawing)
        canvas.CaptureMouse();

        anchorPoint = e.MouseDevice.GetPosition(canvas);
        elip = new Ellipse
        {
            Stroke = Brushes.Black,
            StrokeThickness = 2
        };
        canvas.Children.Add(elip);
    }

    private void canvas_MouseMove(object sender, MouseEventArgs e)
    {
        //if we are not drawing, we don't need to do anything when the mouse moves
        if (!canvas.IsMouseCaptured)
            return;

        Point location = e.MouseDevice.GetPosition(canvas);

        double minX = Math.Min(location.X, anchorPoint.X);
        double minY = Math.Min(location.Y, anchorPoint.Y);
        double maxX = Math.Max(location.X, anchorPoint.X);
        double maxY = Math.Max(location.Y, anchorPoint.Y);

        Canvas.SetTop(elip, minY);
        Canvas.SetLeft(elip, minX);

        double height = maxY - minY;
        double width = maxX - minX;

        elip.Height = Math.Abs(height);
        elip.Width = Math.Abs(width);       
    }

    private void canvas_MouseUp(object sender, MouseButtonEventArgs e)
    {
        // we are now no longer drawing
        canvas.ReleaseMouseCapture();
    }
}

【讨论】:

  • @Clemens 谢谢,我正要解决这个问题:p
  • 而不是处理is_drawing 标志,更好的是capture the mouse 并检查它是否is captured。 Release the capture 鼠标向上。
  • 我还可以补充一点,与其重新计算椭圆的顶部/左侧位置,不如使用带有 EllipseGeometry 的 Path,它保持其中心,但这可能超出了这里的范围。
  • @Clemens 虽然我同意这可能更漂亮,但我并不想在这里重写 adobe illustrator ;) 让我们先让 OP 解决这个问题。
  • 最后一点,您通常在 XAML 中附加事件处理程序,而不是在代码后面,例如 &lt;Canvas MouseDown="canvas_MouseDown" .../&gt;
猜你喜欢
  • 2011-04-18
  • 1970-01-01
  • 2013-07-25
  • 1970-01-01
  • 2018-08-12
  • 1970-01-01
  • 1970-01-01
  • 2015-12-31
  • 1970-01-01
相关资源
最近更新 更多