2014-02-28 107 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)我現在沒有時間提供示例,因爲我在我回家的路上,但它不應該太難,只需在你點擊之前點擊你想去的地方,從你所在的地方分出一小段距離。

希望這有任何幫助。