WPF - 使用鼠标事件在画布上绘图

27

我在处理canvas上的鼠标事件方面遇到了问题。我想使用鼠标在画布上绘制图形,我已经编写了这些事件处理程序,但是当我开始绘制时,它们似乎没有起作用。

    private void paintSurface_MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ButtonState == MouseButtonState.Pressed)
            currentPoint = e.GetPosition(this);
    }

    private void paintSurface_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            Line line = new Line();

            line.Stroke = SystemColors.WindowFrameBrush;
            line.X1 = currentPoint.X;
            line.Y1 = currentPoint.Y;
            line.X2 = e.GetPosition(this).X;
            line.Y2 = e.GetPosition(this).Y;

            currentPoint = e.GetPosition(this);

            paintSurface.Children.Add(line);
        }
    }

你能告诉我缺少了什么或者如何重写它使得它开始工作吗?

4个回答

70

我敢打赌你的画布接收不到鼠标事件,因为它的背景属性设置为透明。

对我来说这很正常。

输入图像描述

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Canvas  Name="paintSurface" MouseDown="Canvas_MouseDown_1" MouseMove="Canvas_MouseMove_1" >
        <Canvas.Background>
            <SolidColorBrush Color="White" Opacity="0"/>
        </Canvas.Background>
    </Canvas>
</Window>


using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Shapes;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {

        Point currentPoint = new Point();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Canvas_MouseDown_1(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.ButtonState == MouseButtonState.Pressed)
                currentPoint = e.GetPosition(this);
        }

        private void Canvas_MouseMove_1(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Line line = new Line();

                line.Stroke = SystemColors.WindowFrameBrush;
                line.X1 = currentPoint.X;
                line.Y1 = currentPoint.Y;
                line.X2 = e.GetPosition(this).X;
                line.Y2 = e.GetPosition(this).Y;

                currentPoint = e.GetPosition(this);

                paintSurface.Children.Add(line);
            }
        }

    }
}

3
好的,我明白了。谢谢你。 - Dawid B
我该如何更新点击捕获以解决菜单引起的偏移问题? - Benjin
13
在GetPosition中,不要传递窗口的引用,而应传递Canvas的引用,这样坐标将相对于Canvas而不是窗口。 - Andy
1
+1 给安迪的评论。如果您添加边距,您将看到差异。 - EvAlex
@Andy 在所有的 GetPosition 函数中,我是否都要传递 PaintSurface 参数(你有三个函数)?我仍然得到奇怪的结果:无论我在哪里点击,它都将起始点作为画布边缘,并绘制一条线到单击点,然后正常继续。 - Khalil Khalaf
1
我认为这是误导性的,将画布的背景属性设置为任何非空值都会解决问题。 "如果未定义背景,则面板元素不会接收鼠标或触笔事件。如果您需要处理鼠标或触笔事件但不想为面板设置背景,请使用Transparent。"来源:https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.panel.background?view=windowsdesktop-6.0 - Piotr Golacki

8

简单使用InkCanvas

 <InkCanvas x:Name="InkCanvas" x:FieldModifier="public" Background="Transparent" Opacity="1" EditingMode="GestureOnly" ForceCursor="True" Cursor="Pen" >
                            <InkCanvas.DefaultDrawingAttributes>
                                <DrawingAttributes Color="White" Width="7" Height="7" />
                            </InkCanvas.DefaultDrawingAttributes>
                        </InkCanvas>

4
使用Line时,粗线(line.StrokeThickness = 20)看起来像这样:

enter image description here

所以我尝试了PolyLine并且运作良好。(来自这个示例http://www.c-sharpcorner.com/uploadfile/mahesh/polyline-in-wpf/)

Canvas.MouseMove += (sender, args) =>
{
    if (args.LeftButton == MouseButtonState.Pressed)
    {
        Polyline polyLine;
        if (PathModeCanvas.Children.Count == 0)
        {
            polyLine = new Polyline();
            polyLine.Stroke = new SolidColorBrush(Colors.AliceBlue);
            polyLine.StrokeThickness = 10;

            Canvas.Children.Add(polyLine);
        }

        polyLine = (Polyline)Canvas.Children[0];
        Point currentPoint = args.GetPosition(Canvas);
        polyLine.Points.Add(currentPoint);
   }
};

1
public partial class MainWindow : Window
    {
        Line newLine;
        Point start;
        Point end;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void DrawCanvas_MouseDown_1(object sender, MouseButtonEventArgs e)
    {
        start = e.GetPosition(this);
    }

    private void DrawCanvas_MouseMove_1(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            end = e.GetPosition(this);
        }
    }

    private void DrawCanvas_MouseUp_1(object sender, MouseButtonEventArgs e)
    {

        newLine = new Line();
        newLine.Stroke = SystemColors.WindowFrameBrush;
        newLine.X1 = start.X;
        newLine.Y1 = start.Y;
        newLine.X2 = end.X;
        newLine.Y2 = end.Y;

        DrawCanvas.Children.Add(newLine);
    }
}

2
这个可以工作,但形状将在鼠标松开后显示。 - Khalil Khalaf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接