You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1018 lines
37 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using Brush = System.Windows.Media.Brush;
using Color = System.Windows.Media.Color;
using Point = System.Windows.Point;
namespace WpfSketch
{
/// <summary>
/// Window1.xaml 的交互逻辑
/// </summary>
public partial class Window1 : Window
{
public delegate void ImageSaveEventHandler(BitmapSource image);
public ImageSaveEventHandler ImageSaveEvent;
private ColorPicker DefaultColorPicker;
public string ImageFile { get; set; }
/// <summary>
/// 目标图片
/// </summary>
public BitmapSource DestImage { get; set; } = null;
private static Mutex mutex = new Mutex(true, "alldream-WpfSketch");
public Window1()
{
_history = new Stack<StrokesHistoryNode>();
_redoHistory = new Stack<StrokesHistoryNode>();
InitializeComponent();
//ImageFile = "C:\\temp\\out-m.png";
DefaultColorPicker = new ColorPicker();
//SetColor(DefaultColorPicker);
_selectedColor = DefaultColorPicker;
SetEnable(false, _mode);
SetTopMost(true);
SetBrushSize(_brushSizes[_brushIndex]);
//ExtraToolPanel.Opacity = 0;
btnFontIncrease.Visibility = Visibility.Hidden;
btnFontDecrease.Visibility = Visibility.Hidden;
MainInkCanvas.Strokes.StrokesChanged += StrokesChanged;
//MainInkCanvas.AddHandler(InkCanvas.MouseLeftButtonDownEvent, new MouseButtonEventHandler(MainInkCanvas_MouseLeftButtonDown), true);
//MainInkCanvas.MouseLeftButtonDown += MainInkCanvas_MouseLeftButtonDown;
MainInkCanvas.PreviewMouseLeftButtonDown += MainInkCanvas_MouseLeftButtonDown;
MainInkCanvas.MouseLeftButtonUp += MainInkCanvas_MouseLeftButtonUp;
MainInkCanvas.MouseRightButtonUp += MainInkCanvas_MouseRightButtonUp;
MainInkCanvas.MouseMove += MainInkCanvas_MouseMove;
_drawerTextBox.IsHitTestVisible = true;
_drawerTextBox.FontSize = 24.0;
//_drawerTextBox.Background = Application.Current.Resources["TrueTransparent"] as Brush;
_drawerTextBox.Background = Brushes.Transparent;//
_drawerTextBox.AcceptsReturn = true;
_drawerTextBox.TextWrapping = TextWrapping.Wrap;
_drawerTextBox.LostFocus += _drawerTextBox_LostFocus;
}
public Window1(BitmapSource destImage)
: this()
{
this.DestImage = destImage;
}
#region /---------Setter---------/
private ColorPicker _selectedColor;
private bool _inkVisibility = true;
private bool _displayExtraToolPanel = false;
private bool _enable = false;
private readonly int[] _brushSizes = { 4, 6, 8, 10, 14 };
private int _brushIndex = 0;
private bool _displayOrientation;
private DrawMode _mode = DrawMode.Pen;
private void SetEnable(bool enable, DrawMode mode)
{
_enable = enable;
_mode = mode;
InkCanvasEditingMode editingMode = InkCanvasEditingMode.Ink;
bool bUseCustomCursor = true;
switch (_mode)
{
case DrawMode.Select:
bUseCustomCursor = false;
editingMode = InkCanvasEditingMode.Select;
break;
case DrawMode.Pen:
editingMode = InkCanvasEditingMode.Ink;
break;
case DrawMode.Text:
editingMode = InkCanvasEditingMode.None;
break;
case DrawMode.Line:
editingMode = InkCanvasEditingMode.None;
break;
case DrawMode.Arrow:
editingMode = InkCanvasEditingMode.None;
break;
case DrawMode.Rectangle:
editingMode = InkCanvasEditingMode.None;
break;
case DrawMode.Circle:
editingMode = InkCanvasEditingMode.None;
break;
case DrawMode.Ray:
editingMode = InkCanvasEditingMode.None;
break;
case DrawMode.Erase:
bUseCustomCursor = false;
editingMode = InkCanvasEditingMode.EraseByStroke;
break;
case DrawMode.None:
_mode = DrawMode.None;
break;
default:
_mode = DrawMode.Select;
break;
}
if (_mode == DrawMode.Ray)
{
MainInkCanvas.Cursor = new Cursor(new MemoryStream(WpfSketch.Properties.Resources.));
}
else
{
MainInkCanvas.Cursor = Cursors.Cross;
}
if (_mode == DrawMode.Text)
{
btnFontIncrease.Visibility = Visibility.Visible;
btnFontDecrease.Visibility = Visibility.Visible;
}
else
{
btnFontIncrease.Visibility = Visibility.Hidden;
btnFontDecrease.Visibility = Visibility.Hidden;
}
MainInkCanvas.UseCustomCursor = bUseCustomCursor;
MainInkCanvas.EditingMode = editingMode;
if (!_enable || _mode == DrawMode.None)
{
MainInkCanvas.EditingMode = InkCanvasEditingMode.None;
}
btnNone.IsChecked = !enable;
//if(_mode == DrawMode.None)
//{
// btnNone.IsChecked = true;
//}
// Background = Application.Current.Resources[enable ? "FakeTransparent" : "TrueTransparent"] as Brush;
}
//private void SetColor(ColorPicker b)
//{
// if (ReferenceEquals(_selectedColor, b)) return;
// var solidColorBrush = b.Foreground as SolidColorBrush;
// if (solidColorBrush == null)
// return;
// MainInkCanvas.DefaultDrawingAttributes.Color = solidColorBrush.Color;
// b.IsActived = true;
// if (_selectedColor != null)
// _selectedColor.IsActived = false;
// _selectedColor = b;
// _drawerTextBox.Foreground = solidColorBrush;
//}
private void SetForeColor(Color color)
{
if(_selectedColor == null)
{
return;
}
var solidColorBrush = _selectedColor.Foreground as SolidColorBrush;
solidColorBrush.Color = color;
MainInkCanvas.DefaultDrawingAttributes.FitToCurve = true;
MainInkCanvas.DefaultDrawingAttributes.IgnorePressure = false;
MainInkCanvas.DefaultDrawingAttributes.IsHighlighter = false;
MainInkCanvas.DefaultDrawingAttributes.StylusTip = StylusTip.Ellipse;
MainInkCanvas.DefaultDrawingAttributes.Color = solidColorBrush.Color;
_drawerTextBox.Foreground = solidColorBrush;
}
private void SetBrushSize(double s)
{
MainInkCanvas.DefaultDrawingAttributes.Height = s;
MainInkCanvas.DefaultDrawingAttributes.Width = s;
}
private void SetOrientation(bool v)
{
//PaletteRotate.BeginAnimation(RotateTransform.AngleProperty, new DoubleAnimation(v ? -90 : 0, Duration4));
//Palette.BeginAnimation(MinWidthProperty, new DoubleAnimation(v ? 90 : 0, Duration7));
_displayOrientation = v;
}
private void SetTopMost(bool v)
{
//PinButton.IsActived = v;
Topmost = v;
}
#endregion
#region Shape Drawer
private Point _drawerIntPos;
private bool _drawerIsMove = false;
private Stroke _drawerLastStroke;
private TextBox _drawerTextBox = new TextBox();
private void _drawerTextBox_LostFocus(object sender, RoutedEventArgs e)
{
String text = _drawerTextBox.Text;
if (text.Length > 0)
{
var textBlock = new TextBlock();
//textBlock.TextWrapping = TextWrapping.NoWrap;
textBlock.Text = text;
MainInkCanvas.Children.Add(textBlock);
textBlock.Visibility = Visibility.Visible;
textBlock.Foreground = _drawerTextBox.Foreground;
textBlock.FontSize = _drawerTextBox.FontSize;
textBlock.TextWrapping = _drawerTextBox.TextWrapping;
InkCanvas.SetLeft(textBlock, InkCanvas.GetLeft(_drawerTextBox));
InkCanvas.SetTop(textBlock, InkCanvas.GetTop(_drawerTextBox));
textBlock.Width = _drawerTextBox.Width;
textBlock.Height = _drawerTextBox.Height;
}
MainInkCanvas.Children.Remove(_drawerTextBox);
//throw new NotImplementedException();
}
private void MainInkCanvas_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
SetEnable(false, _mode);
}
private void MainInkCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (_enable == false || _mode == DrawMode.Select || _mode == DrawMode.Pen || _mode == DrawMode.None || e.LeftButton != MouseButtonState.Pressed)
{
return;
}
if (MainInkCanvas.Children.Contains(_drawerTextBox))
{
return;
}
_ignoreStrokesChange = true;
_drawerIsMove = true;
_drawerIntPos = e.GetPosition(MainInkCanvas);
_drawerLastStroke = null;
if (_mode == DrawMode.Text)
{
_drawerTextBox.Text = "";
if (MainInkCanvas.Children.Contains(_drawerTextBox) == false)
MainInkCanvas.Children.Add(_drawerTextBox);
_drawerTextBox.Visibility = Visibility.Visible;
InkCanvas.SetLeft(_drawerTextBox, _drawerIntPos.X);
InkCanvas.SetTop(_drawerTextBox, _drawerIntPos.Y);
_drawerTextBox.Width = 0;
_drawerTextBox.Height = 0;
}
}
private void MainInkCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_drawerIsMove == true)
{
Point endP = e.GetPosition(MainInkCanvas);
if (_drawerLastStroke != null && _mode != DrawMode.Ray && _mode != DrawMode.Text)
{
StrokeCollection collection = new StrokeCollection();
collection.Add(_drawerLastStroke);
Push(_history, new StrokesHistoryNode(collection, StrokesHistoryNodeType.Added));
}
if (_drawerLastStroke != null && (_mode == DrawMode.Ray || _mode == DrawMode.Text))
{
//us animation?
/*
var ani = new DoubleAnimation(1, 1, Duration4);
ani.Completed += (obj,arg)=> { MainInkCanvas.Strokes.Remove(_drawerLastStroke); };
MainInkCanvas.BeginAnimation(OpacityProperty, ani);
*/
MainInkCanvas.Strokes.Remove(_drawerLastStroke);
}
if (_mode == DrawMode.Text)
{
// resize drawer text box
_drawerTextBox.Width = Math.Abs(endP.X - _drawerIntPos.X);
_drawerTextBox.Height = Math.Abs(endP.Y - _drawerIntPos.Y);
if (_drawerTextBox.Width <= 100 || _drawerTextBox.Height <= 40)
{
_drawerTextBox.Width = 100;
_drawerTextBox.Height = 40;
}
InkCanvas.SetLeft(_drawerTextBox, Math.Min(_drawerIntPos.X, endP.X));
InkCanvas.SetTop(_drawerTextBox, Math.Min(_drawerIntPos.Y, endP.Y));
_drawerTextBox.Focus();
}
_drawerIsMove = false;
_ignoreStrokesChange = false;
}
else
{
if (_mode != DrawMode.Select)
{
if (_mode == DrawMode.None)
{
SetEnable(false, _mode);
}
else
{
DrawMode mode = _mode;
SetEnable(true, DrawMode.None);
SetEnable(true, mode);
}
}
//else
//{
// //SetEnable(true, _mode);
// //_enable = true;
//}
}
}
private void MainInkCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (_drawerIsMove == false)
return;
DrawingAttributes drawingAttributes = MainInkCanvas.DefaultDrawingAttributes.Clone();
Stroke stroke = null;
drawingAttributes.StylusTip = StylusTip.Ellipse;
drawingAttributes.IgnorePressure = true;
Point endP = e.GetPosition(MainInkCanvas);
if (_mode == DrawMode.Text)
{
List<Point> pointList = new List<Point>
{
new Point(_drawerIntPos.X, _drawerIntPos.Y),
new Point(_drawerIntPos.X, endP.Y),
new Point(endP.X, endP.Y),
new Point(endP.X, _drawerIntPos.Y),
new Point(_drawerIntPos.X, _drawerIntPos.Y),
};
drawingAttributes.Width = 2;
drawingAttributes.Height = 2;
drawingAttributes.FitToCurve = false;//must be false,other wise rectangle can not be drawed correct
StylusPointCollection point = new StylusPointCollection(pointList);
stroke = new Stroke(point)
{
DrawingAttributes = drawingAttributes,
};
}
else if (_mode == DrawMode.Ray)
{
//high lighter is ray line
drawingAttributes.IsHighlighter = true;
List<Point> pointList = new List<Point>
{
new Point(_drawerIntPos.X, _drawerIntPos.Y),
new Point(endP.X, endP.Y),
};
StylusPointCollection point = new StylusPointCollection(pointList);
stroke = new Stroke(point)
{
DrawingAttributes = drawingAttributes,
};
}
else if (_mode == DrawMode.Line)
{
List<Point> pointList = new List<Point>
{
new Point(_drawerIntPos.X, _drawerIntPos.Y),
new Point(endP.X, endP.Y),
};
StylusPointCollection point = new StylusPointCollection(pointList);
stroke = new Stroke(point)
{
DrawingAttributes = drawingAttributes,
};
}
else if (_mode == DrawMode.Arrow)
{
double w = 15, h = 15;
double theta = Math.Atan2(_drawerIntPos.Y - endP.Y, _drawerIntPos.X - endP.X);
double sint = Math.Sin(theta);
double cost = Math.Cos(theta);
List<Point> pointList = new List<Point>
{
new Point(_drawerIntPos.X, _drawerIntPos.Y),
new Point(endP.X , endP.Y),
new Point(endP.X + (w*cost - h*sint), endP.Y + (w*sint + h*cost)),
new Point(endP.X,endP.Y),
new Point(endP.X + (w*cost + h*sint), endP.Y - (h*cost - w*sint)),
};
StylusPointCollection point = new StylusPointCollection(pointList);
drawingAttributes.FitToCurve = false;//must be false,other wise rectangle can not be drawed correct
stroke = new Stroke(point)
{
DrawingAttributes = drawingAttributes,
};
}
else if (_mode == DrawMode.Rectangle)
{
List<Point> pointList = new List<Point>
{
new Point(_drawerIntPos.X, _drawerIntPos.Y),
new Point(_drawerIntPos.X, endP.Y),
new Point(endP.X, endP.Y),
new Point(endP.X, _drawerIntPos.Y),
new Point(_drawerIntPos.X, _drawerIntPos.Y),
};
drawingAttributes.FitToCurve = false;//must be false,other wise rectangle can not be drawed correct
StylusPointCollection point = new StylusPointCollection(pointList);
stroke = new Stroke(point)
{
DrawingAttributes = drawingAttributes,
};
}
else if (_mode == DrawMode.Circle)
{
List<Point> pointList = GenerateEclipseGeometry(_drawerIntPos, endP);
StylusPointCollection point = new StylusPointCollection(pointList);
stroke = new Stroke(point)
{
DrawingAttributes = drawingAttributes
};
}
if (_drawerLastStroke != null)
MainInkCanvas.Strokes.Remove(_drawerLastStroke);
if (stroke != null)
MainInkCanvas.Strokes.Add(stroke);
_drawerLastStroke = stroke;
}
#endregion
#region /---------Generator---------/
private static string GenerateFileName(string fileExt = ".fdw")
{
return DateTime.Now.ToString("yyyyMMdd-HHmmss") + fileExt;
}
private List<Point> GenerateEclipseGeometry(Point st, Point ed)
{
double a = 0.5 * (ed.X - st.X);
double b = 0.5 * (ed.Y - st.Y);
List<Point> pointList = new List<Point>();
for (double r = 0; r <= 2 * Math.PI; r = r + 0.01)
{
pointList.Add(new Point(0.5 * (st.X + ed.X) + a * Math.Cos(r), 0.5 * (st.Y + ed.Y) + b * Math.Sin(r)));
}
return pointList;
}
#endregion
#region /---------IO---------/
private StrokeCollection _preLoadStrokes = null;
private void QuickSave(string filename = "QuickSave_")
{
//Save(new FileStream("Save\\" + filename + GenerateFileName(), FileMode.OpenOrCreate));
if(this.DestImage != null)
{
Save2Image();
}
else
{
Save(null);
}
}
private void Save2Image()
{
try
{
//string strFile = "C:\\temp\\rend.png";
double width = MainInkCanvas.ActualWidth;
double height = MainInkCanvas.ActualHeight;
RenderTargetBitmap bmpCopied = new RenderTargetBitmap((int)Math.Round(width)
, (int)Math.Round(height), 96, 96, PixelFormats.Default);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(MainInkCanvas);
dc.DrawImage(this.img.Source, new Rect(new System.Windows.Point(), new System.Windows.Size(width, height)));
dc.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), new System.Windows.Size(width, height)));
}
bmpCopied.Render(dv);
this.DestImage = bmpCopied;
_saved = true;
ImageSaveEvent?.Invoke(this.DestImage);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void Save(Stream fs)
{
try
{
//string strFile = "C:\\temp\\rend.png";
double width = MainInkCanvas.ActualWidth;
double height = MainInkCanvas.ActualHeight;
RenderTargetBitmap bmpCopied = new RenderTargetBitmap((int)Math.Round(width)
, (int)Math.Round(height), 96, 96, PixelFormats.Default);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(MainInkCanvas);
dc.DrawImage(this.img.Source, new Rect(new System.Windows.Point(), new System.Windows.Size(width, height)));
dc.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), new System.Windows.Size(width, height)));
}
bmpCopied.Render(dv);
using (FileStream file = new FileStream(ImageFile, FileMode.Create, FileAccess.Write))
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmpCopied));
encoder.Save(file);
_saved = true;
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
//try
//{
// if (fs == Stream.Null) return;
// MainInkCanvas.Strokes.Save(fs);
// _saved = true;
// Display("画板保存成功");
// fs.Close();
//}
//catch (Exception ex)
//{
// MessageBox.Show(ex.ToString());
// Display("画板保存失败");
//}
}
private StrokeCollection Load(Stream fs)
{
try
{
return new StrokeCollection(fs);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
Display("画板加载失败");
}
return new StrokeCollection();
}
private void AnimatedReload(StrokeCollection sc)
{
_preLoadStrokes = sc;
//var ani = new DoubleAnimation(0, Duration3);
//ani.Completed += LoadAniCompleted;
//MainInkCanvas.BeginAnimation(OpacityProperty, ani);
}
private void LoadAniCompleted(object sender, EventArgs e)
{
if (_preLoadStrokes == null) return;
MainInkCanvas.Strokes = _preLoadStrokes;
//Display("画板加载完成");
_saved = true;
ClearHistory();
//MainInkCanvas.BeginAnimation(OpacityProperty, new DoubleAnimation(1, Duration3));
}
private static string[] GetSavePathList()
{
return Directory.GetFiles("Save", "*.fdw");
}
private static string GetFileNameFromPath(string path)
{
return System.IO.Path.GetFileName(path);
}
#endregion
#region /---------Helper---------/
private string _staticInfo = "";
private bool _displayingInfo;
private async void Display(string info)
{
//InfoBox.Text = info;
_displayingInfo = true;
//await InfoDisplayTimeUp(new Progress<string>(box => InfoBox.Text = box));
}
private Task InfoDisplayTimeUp(IProgress<string> box)
{
return Task.Run(() =>
{
Task.Delay(2000).Wait();
box.Report(_staticInfo);
_displayingInfo = false;
});
}
private void SetStaticInfo(string info)
{
_staticInfo = info;
//if (!_displayingInfo)
// InfoBox.Text = _staticInfo;
}
private static Stream SaveDialog(string initFileName, string fileExt = ".fdw", string filter = "Free Draw Save (*.fdw)|*fdw")
{
var dialog = new Microsoft.Win32.SaveFileDialog()
{
DefaultExt = fileExt,
Filter = filter,
FileName = initFileName,
InitialDirectory = Directory.GetCurrentDirectory() + "Save"
};
return dialog.ShowDialog() == true ? dialog.OpenFile() : Stream.Null;
}
private static Stream OpenDialog(string fileExt = ".fdw", string filter = "Free Draw Save (*.fdw)|*fdw")
{
var dialog = new Microsoft.Win32.OpenFileDialog()
{
DefaultExt = fileExt,
Filter = filter,
};
return dialog.ShowDialog() == true ? dialog.OpenFile() : Stream.Null;
}
#endregion
#region /---------Judge--------/
private bool _saved = false;
private bool IsUnsaved()
{
return MainInkCanvas.Strokes.Count != 0 && !_saved;
}
private bool PromptToSave()
{
if (!IsUnsaved())
return true;
var r = MessageBox.Show("You have unsaved work, do you want to save it now?", "Unsaved data",
MessageBoxButton.YesNoCancel);
if (r == MessageBoxResult.Yes || r == MessageBoxResult.OK)
{
QuickSave();
return true;
}
if (r == MessageBoxResult.No || r == MessageBoxResult.None)
return true;
return false;
}
#endregion
private void Window_Loaded(object sender, RoutedEventArgs e)
{
FixupToolBarOverflowArrow(tbDraw);
if(this.DestImage != null)
{
MainInkCanvas.Width = this.DestImage.Width;
MainInkCanvas.Height = this.DestImage.Height;
img.Source = this.DestImage;
}
else if (!string.IsNullOrEmpty(ImageFile))
{
MemoryStream ms = null;
using (var stream = File.Open(ImageFile, FileMode.Open))
{
using (var reader = new BinaryReader(stream))
{
byte[] datas = reader.ReadBytes((int)stream.Length);
ms = new MemoryStream(datas);
}
}
BitmapImage imgSource = new BitmapImage();
imgSource.BeginInit();
imgSource.StreamSource = ms;
imgSource.EndInit();
MainInkCanvas.Width = imgSource.Width;
MainInkCanvas.Height = imgSource.Height;
img.Source = imgSource;
}
else
{
MainInkCanvas.Width = 500;
MainInkCanvas.Height = 400;
}
// 默认红色画笔
this.btnColorRed.IsChecked = true;
this.btnColorRed.RaiseEvent(new RoutedEventArgs(RadioButton.ClickEvent));
this.rbtnPenWidthMin.IsChecked = true;
// 默认绘图圆
this.btnCircle.IsChecked = true;
this.btnCircle.RaiseEvent(new RoutedEventArgs(RadioButton.ClickEvent));
}
private static void FixupToolBarOverflowArrow(ToolBar toolBar)
{
Action fixup = () =>
{
var overflowButton = toolBar.Template.FindName("OverflowButton", toolBar) as System.Windows.Controls.Primitives.ButtonBase;
if (overflowButton != null)
{
overflowButton.SetBinding(
VisibilityProperty,
new Binding("IsEnabled")
{
RelativeSource = RelativeSource.Self,
Converter = new BooleanToVisibilityConverter()
});
}
};
if (toolBar.IsLoaded)
{
fixup();
}
else
{
RoutedEventHandler handler = null;
handler = (sender, e) =>
{
fixup();
toolBar.Loaded -= handler;
};
toolBar.Loaded += handler;
}
}
/// <summary>
/// 选择颜色.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The e.</param>
private void ColorButton_Click(object sender, RoutedEventArgs e)
{
//要获得所选方块的颜色需要将SolidColorBrush取Color
//_selectedColor.Foreground = (SolidColorBrush)((Rectangle)(sender as RadioButton).Content).Fill;
Color color = ((SolidColorBrush)((Rectangle)(sender as RadioButton).Content).Fill).Color;
this.SetForeColor(color);
}
#region /---------Ink---------/
private readonly Stack<StrokesHistoryNode> _history;
private readonly Stack<StrokesHistoryNode> _redoHistory;
private bool _ignoreStrokesChange;
private void Undo()
{
if (!CanUndo()) return;
var last = Pop(_history);
_ignoreStrokesChange = true;
if (last.Type == StrokesHistoryNodeType.Added)
MainInkCanvas.Strokes.Remove(last.Strokes);
else
MainInkCanvas.Strokes.Add(last.Strokes);
_ignoreStrokesChange = false;
Push(_redoHistory, last);
}
private void Redo()
{
if (!CanRedo()) return;
var last = Pop(_redoHistory);
_ignoreStrokesChange = true;
if (last.Type == StrokesHistoryNodeType.Removed)
MainInkCanvas.Strokes.Remove(last.Strokes);
else
MainInkCanvas.Strokes.Add(last.Strokes);
_ignoreStrokesChange = false;
Push(_history, last);
}
private static void Push(Stack<StrokesHistoryNode> collection, StrokesHistoryNode node)
{
collection.Push(node);
}
private static StrokesHistoryNode Pop(Stack<StrokesHistoryNode> collection)
{
return collection.Count == 0 ? null : collection.Pop();
}
private bool CanUndo()
{
return _history.Count != 0;
}
private bool CanRedo()
{
return _redoHistory.Count != 0;
}
private void StrokesChanged(object sender, StrokeCollectionChangedEventArgs e)
{
if (_ignoreStrokesChange) return;
_saved = false;
if (e.Added.Count != 0)
Push(_history, new StrokesHistoryNode(e.Added, StrokesHistoryNodeType.Added));
if (e.Removed.Count != 0)
Push(_history, new StrokesHistoryNode(e.Removed, StrokesHistoryNodeType.Removed));
ClearHistory(_redoHistory);
}
private void ClearHistory()
{
ClearHistory(_history);
ClearHistory(_redoHistory);
}
private static void ClearHistory(Stack<StrokesHistoryNode> collection)
{
collection?.Clear();
}
private void Clear()
{
MainInkCanvas.Children.Clear();
MainInkCanvas.Strokes.Clear();
ClearHistory();
}
private void AnimatedClear()
{
//no need any more
//var ani = new DoubleAnimation(0, Duration3);
//ani.Completed += ClearAniComplete; ;
//MainInkCanvas.BeginAnimation(OpacityProperty, ani);
}
private void ClearAniComplete(object sender, EventArgs e)
{
Clear();
//Display("画板清除完成");
//MainInkCanvas.BeginAnimation(OpacityProperty, new DoubleAnimation(1, Duration3));
}
#endregion
/// <summary>
/// 绘制圆.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
private void BtnCircle_Click(object sender, RoutedEventArgs e)
{
SetEnable(true, DrawMode.Circle);
}
/// <summary>
/// 任意画笔.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
private void BtnPen_Click(object sender, RoutedEventArgs e)
{
SetEnable(true, DrawMode.Pen);
}
/// <summary>
/// 绘制直线
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnLine_Click(object sender, RoutedEventArgs e)
{
SetEnable(true, DrawMode.Line);
}
private void BtnRectangle_Click(object sender, RoutedEventArgs e)
{
SetEnable(true, DrawMode.Rectangle);
}
private void BtnText_Click(object sender, RoutedEventArgs e)
{
SetEnable(true, DrawMode.Text);
}
private void BtnSelect_Click(object sender, RoutedEventArgs e)
{
SetEnable(true, DrawMode.Select);
}
private void BtnArrow_Click(object sender, RoutedEventArgs e)
{
SetEnable(true, DrawMode.Arrow);
}
private void BtnNone_Click(object sender, RoutedEventArgs e)
{
SetEnable(false, DrawMode.None);
}
private void BtnFontIncrease_Click(object sender, RoutedEventArgs e)
{
_drawerTextBox.FontSize = _drawerTextBox.FontSize + 2;
_drawerTextBox.FontSize = Math.Min(60, _drawerTextBox.FontSize);
}
private void BtnFontDecrease_Click(object sender, RoutedEventArgs e)
{
_drawerTextBox.FontSize = _drawerTextBox.FontSize - 2;
_drawerTextBox.FontSize = Math.Max(14, _drawerTextBox.FontSize);
}
/// <summary>
/// 撤销.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
private void BtnUndo_Click(object sender, RoutedEventArgs e)
{
Undo();
}
/// <summary>
/// 重做.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
private void BtnRedo_Click(object sender, RoutedEventArgs e)
{
Redo();
}
private void PenWidth_Checked(object sender, RoutedEventArgs e)
{
double dWidth = ((Ellipse)(sender as RadioButton).Content).Width;
SetBrushSize(dWidth);
}
/// <summary>
/// 保存.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
private void BtnSave_Click(object sender, RoutedEventArgs e)
{
if (MainInkCanvas.Strokes.Count == 0)
{
Display("没有笔迹要保存");
return;
}
QuickSave();
this.Close();
}
/// <summary>
/// 退出.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
private void BtnExit_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (IsUnsaved())
{
if (MessageBox.Show(this, "尚未保存,是否退出?", "退出"
, MessageBoxButton.YesNo, MessageBoxImage.Question
, MessageBoxResult.No) == MessageBoxResult.Yes)
{
//Application.Current.Shutdown();
//MessageBox.Show("退出");
return;
}
else
{
e.Cancel = true;
}
}
}
}
}