2014-02-28 66 views
0

我正在尝试制作一个简单的图像编辑器,用户可以在其中加载图像并在其上绘制箭头,文本和矩形。如何让用户使用WPF中的画布绘制线条

现在我有一个窗口,有一些按钮和一个带有画布和里面的图像的视图框。

基本上,用户将单击箭头按钮,单击画布上的某处,移动将显示一条线的鼠标,然后单击其他地方以实际绘制线条。

如何让画布在单击绘图按钮后才开始监听鼠标点击?这是我到目前为止。

<Window x:Class="ImageEditor.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="600" Width="800"> 
    <Window.CommandBindings> 
     <CommandBinding Command="local:CapturePointsCommand" Executed="CommandBinding_Executed" CanExecute="CommandBinding_CanExecute"/> 
    </Window.CommandBindings> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <Button Grid.Row="0" Name="_drawArrow" Height="69" Width="69" Click="_drawArrow_Click" HorizontalAlignment="Left" Margin="5,5,0,5"> 
      <Image Source="Media/arrow.png"/> 
     </Button> 
     <Button Grid.Row="0" Name="_drawBox" Height="69" Width="69" Click="_drawBox_Click" HorizontalAlignment="Left" Margin="79,5,0,5"> 
      <Image Source="Media/rectangle.png"/> 
     </Button> 
     <Button Grid.Row="0" Name="_drawText" Height="69" Width="69" Click="_drawText_Click" HorizontalAlignment="Left" Margin="153,5,0,5"> 
      <Image Source="Media/text.png"/> 
     </Button> 
     <Viewbox Grid.Row="1"> 
      <Canvas Name="_canvas" Height="{Binding Height, ElementName=_picture}" Width="{Binding Width, ElementName=_picture}" MouseLeftButtonUp="_canvas_MouseLeftButtonUp"> 
       <Image Name="_picture" Source="{Binding Image}" Height="488" Width="800"/> 
      </Canvas> 
     </Viewbox> 
     <Button Grid.Row="2" HorizontalAlignment="Right" Name="_Load_Button" Content="Load" Margin="0,5,5,5" Width="75" Height="23" Click="_Load_Button_Click" /> 
     <Button Grid.Row="2" HorizontalAlignment="Right" Name="_Save_Button" Content="Save" Margin="0,5,85,5" Width="75" Height="23" Click="_Save_Button_Click" /> 
     <Button Grid.Row="2" HorizontalAlignment="Right" Name="_Cancel_Button" Content="Cancel" Margin="0,5,165,5" Width="75" Height="23" Click="_Cancel_Button_Click" /> 
     <Button Grid.Row="2" HorizontalAlignment="Right" Name="_Reset_Button" Content="Reset" Margin="0,5,245,5" Width="75" Height="23" Click="_Reset_Button_Click" /> 
    </Grid> 
</Window> 

以此为后面的代码:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Windows.Forms; 
using System.IO; 

namespace ImageEditor 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public static readonly RoutedCommand CapturePointsCommand = new RoutedCommand(); 

     private ImageSource _image; 

     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     public ImageSource Image 
     { 
      get 
      { 
       return this._image; 
      } 
      set 
      { 
       this._image = value; 
      } 
     } 

     private List<Point> _points = new List<Point>(); 

     public List<Point> Points 
     { 
      get 
      { 
       return this._points; 
      } 
      set 
      { 
       this._points = value; 
      } 
     } 

     private void _Save_Button_Click(object sender, RoutedEventArgs e) 
     { 
      if (Image == null) 
       System.Windows.Forms.MessageBox.Show("There is nothing to save"); 
      else 
      { 
       Image = this._picture.Source; 
       this.Close(); 
      } 
     } 

     private void _Reset_Button_Click(object sender, RoutedEventArgs e) 
     { 
      this._picture.Source = Image; 
     } 

     private void _Cancel_Button_Click(object sender, RoutedEventArgs e) 
     { 
      Image = null; 
      this._picture.Source = null; 
      this.Close(); 
     } 

     private void _Load_Button_Click(object sender, RoutedEventArgs e) 
     { 
      OpenFileDialog ofd = new OpenFileDialog(); 
      string path; 
      if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) 
      { 
       path = ofd.FileName; 
       Uri pathUri = new Uri(path); 
       PngBitmapDecoder decoder = new PngBitmapDecoder(pathUri, BitmapCreateOptions.None, BitmapCacheOption.None); 
       BitmapSource pathSrc = decoder.Frames[0]; 
       Image = pathSrc; 
       this._picture.Source = Image; 
      } 
      else 
      { 
       path = null; 
      } 
     } 

     private void _drawArrow_Click(object sender, RoutedEventArgs e) 
     { 
      Line line = new Line(); 
      line.Stroke = Brushes.Black; 
      line.X1 = Points[0].X; 
      line.Y1 = Points[0].Y; 
      line.X2 = Points[1].X; 
      line.Y2 = Points[1].Y; 

      this._canvas.Children.Add(line); 
     } 

     private void _drawBox_Click(object sender, RoutedEventArgs e) 
     { 

     } 

     private void _drawText_Click(object sender, RoutedEventArgs e) 
     { 

     } 

     private void _canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
     { 
      Point p = Mouse.GetPosition(_canvas); 
      Points.Add(p); 
     } 

     private void _drawArrow_MouseDown(object sender, MouseButtonEventArgs e) 
     { 

     } 

     private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) 
     { 

     } 

     private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
     { 

     } 
    } 
} 

回答

2

下面的代码为我提供了适合您的功能。

枚举是您希望用户能够绘制的所有不同形状的列表。您实现的按钮应设置activeShapeType值。将您的方法从绘制矩形,圆等添加到Canvas_MouseLeftButtonDown事件中的switch语句中。

右键单击事件将允许用户在第二次点击之前取消他们正在绘制的线。

public bool IsFirstPoint = true; 
    public Point StartPoint; 
    public enum ShapeType 
    { 
     line, 
     circle, 
     rectangle 
    } 
    public ShapeType activeShapeType = ShapeType.line; 


    private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     if (IsFirstPoint) 
     { 
      StartPoint = (Mouse.GetPosition(Surface)); 
      IsFirstPoint = false; 
     } 
     else 
     { 
      switch (activeShapeType) 
      { 
       case ShapeType.line: 
        Line line = new Line() { X1 = StartPoint.X, Y1 = StartPoint.Y, X2 = Mouse.GetPosition(Surface).X, Y2 = Mouse.GetPosition(Surface).Y, Stroke = Brushes.Black }; 
        Surface.Children.Add(line); 
        break; 
       case ShapeType.rectangle: 
        /*Your code to draw rectangle here*/ 
        break; 
      } 
      IsFirstPoint = true; 
     } 
    } 

    private void Surface_MouseRightButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     IsFirstPoint = true; 
    } 

此代码应该在移动鼠标的同时添加临时行。

private void Surface_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (!IsFirstPoint) 
     { 

      if (Surface.Children.Count > 0) 
      { 
       var child = (from c in Surface.Children.OfType<FrameworkElement>() 
          where "tempLine".Equals(c.Tag) 
          select c).First(); 
       if (child != null) 
       { 
        Surface.Children.Remove(child); 
       } 
      } 


      switch (activeShapeType) 
      { 
       case ShapeType.line: 
        Line line = new Line() { Tag="tempLine", X1 = StartPoints.X, Y1 = StartPoints.Y, X2 = Mouse.GetPosition(Surface).X, Y2 = Mouse.GetPosition(Surface).Y, Stroke = Brushes.Black }; 
        Surface.Children.Add(line);      


        return; 
      } 
     } 
    } 
+0

谢谢你,我结束了这一修改。对于画布 “IsHitTestVisible”设置为false,直到您单击按钮并在添加形状后设置为false以防止提前捕获点。 – Adam

0

我做了这样的事情使用InkCanvas,绘画,添加符号到画布上。

但是我用布尔控制大部分事物,所以当你点击一个按钮时,你知道你处于哪个状态。

然后当你点击画布时,状态用来说好吧我处于方形/箭头状态,这就是我应该画的东西。然而。我认为你正在寻找的是

关闭,向上移动功能。

当你点击画布mousedown时,你会得到你想要开始你的图形的位置,当你按下鼠标的时候移动鼠标,你可以做一个拖动动画,或者跳过它直接到你释放的位置在画布上。获取另一个位置,然后从这些位置画线..

x1,y1(画布上的mousedown位置)x2,y2(画布上的mouseup)我现在没有时间提供示例,因为我在我回家的路上,但它不应该太难,只需在你点击之前点击你想去的地方,从你所在的地方分出一小段距离。

希望这有任何帮助。