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
{
///
/// Window1.xaml 的交互逻辑
///
public partial class Window1 : Window
{
public delegate void ImageSaveEventHandler(BitmapSource image);
public ImageSaveEventHandler ImageSaveEvent;
private ColorPicker DefaultColorPicker;
public string ImageFile { get; set; }
///
/// 目标图片
///
public BitmapSource DestImage { get; set; } = null;
private static Mutex mutex = new Mutex(true, "alldream-WpfSketch");
public Window1()
{
_history = new Stack();
_redoHistory = new Stack();
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 = System.Windows.Media.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 System.Windows.Input.Cursor(new MemoryStream(WpfSketch.Properties.Resources.激光));
}
else
{
MainInkCanvas.Cursor = System.Windows.Input.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 System.Windows.Controls.TextBox _drawerTextBox = new System.Windows.Controls.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, System.Windows.Input.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 pointList = new List
{
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 pointList = new List
{
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 pointList = new List
{
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 pointList = new List
{
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 pointList = new List
{
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 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 GenerateEclipseGeometry(Point st, Point ed)
{
double a = 0.5 * (ed.X - st.X);
double b = 0.5 * (ed.Y - st.Y);
List pointList = new List();
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)
{
System.Windows.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)
{
System.Windows.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)
{
System.Windows.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(box => InfoBox.Text = box));
}
private Task InfoDisplayTimeUp(IProgress 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 = System.Windows.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(System.Windows.Controls.RadioButton.ClickEvent));
this.rbtnPenWidthMin.IsChecked = true;
// 默认绘图圆
this.btnCircle.IsChecked = true;
this.btnCircle.RaiseEvent(new RoutedEventArgs(System.Windows.Controls.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 System.Windows.Data.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;
}
}
///
/// 选择颜色.
///
/// The sender.
/// The e.
private void ColorButton_Click(object sender, RoutedEventArgs e)
{
//要获得所选方块的颜色,需要将SolidColorBrush取Color
//_selectedColor.Foreground = (SolidColorBrush)((Rectangle)(sender as RadioButton).Content).Fill;
Color color = ((SolidColorBrush)((System.Windows.Shapes.Rectangle)(sender as System.Windows.Controls.RadioButton).Content).Fill).Color;
this.SetForeColor(color);
}
#region /---------Ink---------/
private readonly Stack _history;
private readonly Stack _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 collection, StrokesHistoryNode node)
{
collection.Push(node);
}
private static StrokesHistoryNode Pop(Stack 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 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
///
/// 绘制圆.
///
/// The source of the event.
/// The instance containing the event data.
private void BtnCircle_Click(object sender, RoutedEventArgs e)
{
SetEnable(true, DrawMode.Circle);
}
///
/// 任意画笔.
///
/// The source of the event.
/// The instance containing the event data.
private void BtnPen_Click(object sender, RoutedEventArgs e)
{
SetEnable(true, DrawMode.Pen);
}
///
/// 绘制直线
///
///
///
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);
}
///
/// 撤销.
///
/// The source of the event.
/// The instance containing the event data.
private void BtnUndo_Click(object sender, RoutedEventArgs e)
{
Undo();
}
///
/// 重做.
///
/// The source of the event.
/// The instance containing the event data.
private void BtnRedo_Click(object sender, RoutedEventArgs e)
{
Redo();
}
private void PenWidth_Checked(object sender, RoutedEventArgs e)
{
double dWidth = ((Ellipse)(sender as System.Windows.Controls.RadioButton).Content).Width;
SetBrushSize(dWidth);
}
///
/// 保存.
///
/// The source of the event.
/// The instance containing the event data.
private void BtnSave_Click(object sender, RoutedEventArgs e)
{
if (MainInkCanvas.Strokes.Count == 0)
{
Display("没有笔迹要保存");
return;
}
QuickSave();
this.Close();
}
///
/// 退出.
///
/// The source of the event.
/// The instance containing the event data.
private void BtnExit_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (IsUnsaved())
{
if (System.Windows.MessageBox.Show(this, "尚未保存,是否退出?", "退出"
, MessageBoxButton.YesNo, MessageBoxImage.Question
, MessageBoxResult.No) == MessageBoxResult.Yes)
{
//Application.Current.Shutdown();
//MessageBox.Show("退出");
return;
}
else
{
e.Cancel = true;
}
}
}
}
}