using Common.system; using System; using System.Collections.Generic; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using TStudyDigitalPen.HID; using XHWK.Model; namespace XHWK.WKTool { /// /// 录屏画板 /// public partial class PracticeWindow : Window { //声明一个 DrawingAttributes 类型的变量 private DrawingAttributes drawingAttributes; private DrawingAttributes drawing; private ViewModel viewModel; /// /// 0 画笔 1 矩形 2 圆形 /// private int flg = 0; /// /// 当前画笔颜色 /// private Color Colour = Colors.Red; /// /// 当前画笔宽 /// private int Wit = 2; /// /// 当前画笔高 /// private int Hei = 2; public PracticeWindow() { InitializeComponent(); InitPen(); } public void Initialize(string _imgPath = null) { flg = 0; blackboard_canvas.Strokes.Clear(); blackboard_canvas.UseCustomCursor = true; //blackboard_canvas.EditingMode = InkCanvasEditingMode.EraseByStroke; //加背景 废弃更利于讲解ppt //if (File.Exists(_imgPath)) //{ // imgCanvas.Source = new BitmapImage(new Uri(_imgPath)); //} //创建 DrawingAttributes 类的一个实例 drawingAttributes = new DrawingAttributes(); //drawingAttributes.StylusTip = StylusTip.Rectangle; //drawingAttributes.IsHighlighter = false; //drawingAttributes.IgnorePressure = true; ////将 InkCanvas 的 DefaultDrawingAttributes 属性的值赋成创建的 DrawingAttributes 类的对象的引用 ////InkCanvas 通过 DefaultDrawingAttributes 属性来获取墨迹的各种设置,该属性的类型为 DrawingAttributes 型 blackboard_canvas.DefaultDrawingAttributes = drawingAttributes; Pen(); //blackboard_canvas.Cursor = Cursors.Pen; //Cursor cus = new Cursor(@"G:\06.cur"); //blackboard_canvas.Cursor = cus; viewModel = new ViewModel { InkStrokes = new StrokeCollection(), }; DataContext = viewModel; //APP.W_ScreenRecordingToolbarWindow.Owner = this; //APP.W_ScreenRecordingToolbarWindow.Topmost = true; } /// /// 画笔颜色事件 白色 /// /// /// public void White() { //flg = 0; drawingAttributes.Color = Colors.White; Colour = Colors.White; } /// /// 画笔颜色事件 红色 /// /// /// public void Red() { drawingAttributes.Color = Colors.Red; Colour = Colors.Red; } /// /// 画笔颜色事件 黑色 /// /// /// public void Gray() { //flg = 0; drawingAttributes.Color = Colors.Black; Colour = Colors.Black; } /// /// 画笔颜色事件 青色 /// /// /// public void CyanBlue() { //flg = 0; drawingAttributes.Color = Colors.LimeGreen; Colour = Colors.LimeGreen; } /// /// 画笔颜色事件 黄色 /// /// /// public void Yellow() { //flg = 0; drawingAttributes.Color = Colors.Gold; Colour = Colors.Gold; } /// /// 画笔颜色事件 蓝色 /// /// /// public void Blue() { //flg = 0; drawingAttributes.Color = Colors.DeepSkyBlue; Colour = Colors.DeepSkyBlue; } /// /// 画笔粗细事件 细 /// /// /// public void Fine() { //flg = 0; drawingAttributes.Width = 1; drawingAttributes.Height = 1; Wit = 1; Hei = 1; } /// /// 画笔粗细事件 中 /// /// /// public void In() { //flg = 0; drawingAttributes.Width = 3; drawingAttributes.Height = 3; Wit = 3; Hei = 3; } /// /// 画笔粗细事件 粗 /// /// /// public void Crude() { //flg = 0; drawingAttributes.Width = 5; drawingAttributes.Height = 5; Wit = 5; Hei = 5; } /// /// 橡皮 /// public void Eraser() { flg = 0; //this.type = ZPenType.Erase; blackboard_canvas.UseCustomCursor = false; blackboard_canvas.EditingMode = InkCanvasEditingMode.EraseByPoint; blackboard_canvas.EraserShape = new EllipseStylusShape(64, 64, 0); } /// /// 画笔 /// public void Pen() { flg = 0; blackboard_canvas.EditingMode = InkCanvasEditingMode.Ink; blackboard_canvas.UseCustomCursor = true; drawingAttributes.FitToCurve = true; drawingAttributes.IgnorePressure = false; blackboard_canvas.Cursor = Cursors.Pen; } /// /// 圆 /// public void Round() { flg = 2; drawingAttributes = new DrawingAttributes { Color = Colour, Width = Wit, Height = Hei, StylusTip = StylusTip.Rectangle, //FitToCurve = true, IsHighlighter = false, IgnorePressure = true, }; blackboard_canvas.DefaultDrawingAttributes = drawingAttributes; blackboard_canvas.EditingMode = InkCanvasEditingMode.None; blackboard_canvas.Cursor = Cursors.Cross; } /// /// 矩形 /// public void Rectangle() { flg = 1; drawingAttributes = new DrawingAttributes { Color = Colour, Width = Wit, Height = Hei, StylusTip = StylusTip.Rectangle, //FitToCurve = true, IsHighlighter = false, IgnorePressure = true, }; blackboard_canvas.DefaultDrawingAttributes = drawingAttributes; blackboard_canvas.EditingMode = InkCanvasEditingMode.None; blackboard_canvas.Cursor = Cursors.Cross; } private System.Windows.Point iniP; private void blackboard_canvas_MouseDown(object sender, MouseButtonEventArgs e) { if (flg != 0) { if (e.LeftButton == MouseButtonState.Pressed) { iniP = e.GetPosition(blackboard_canvas); } } } private Stroke StrokeRound; private Stroke StrokeRectangle; private void blackboard_canvas_MouseMove(object sender, MouseEventArgs e) { if (flg != 0) { if (e.LeftButton == MouseButtonState.Pressed) { // Draw square if (flg == 1) { System.Windows.Point endP = e.GetPosition(blackboard_canvas); List pointList = new List { new System.Windows.Point(iniP.X, iniP.Y), new System.Windows.Point(iniP.X, endP.Y), new System.Windows.Point(endP.X, endP.Y), new System.Windows.Point(endP.X, iniP.Y), new System.Windows.Point(iniP.X, iniP.Y), }; //Stroke stroke1 = new Stroke(drawingAttributesRound); StylusPointCollection point = new StylusPointCollection(pointList); Stroke stroke = new Stroke(point) { DrawingAttributes = blackboard_canvas.DefaultDrawingAttributes.Clone() }; if (StrokeRectangle != null) { viewModel.InkStrokes.Remove(StrokeRectangle); } StrokeRectangle = stroke; viewModel.InkStrokes.Add(stroke); } // Draw Eclipse else if (flg == 2) { System.Windows.Point endP = e.GetPosition(blackboard_canvas); List pointList = GenerateEclipseGeometry(iniP, endP); StylusPointCollection point = new StylusPointCollection(pointList); Stroke stroke = new Stroke(point) { DrawingAttributes = blackboard_canvas.DefaultDrawingAttributes.Clone() }; //viewModel.InkStrokes.Clear(); if (StrokeRound != null) { viewModel.InkStrokes.Remove(StrokeRound); } StrokeRound = stroke; viewModel.InkStrokes.Add(stroke); } } } } private List GenerateEclipseGeometry(System.Windows.Point st, System.Windows.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 System.Windows.Point(0.5 * (st.X + ed.X) + a * Math.Cos(r), 0.5 * (st.Y + ed.Y) + b * Math.Sin(r))); } return pointList; } /// /// 鼠标松开时 /// /// /// private void blackboard_canvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { StrokeRound = null; StrokeRectangle = null; } /// /// 鼠标右键 /// /// /// private void Window_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { if (APP.W_ScreenRecordingToolbarWindow.flg == 10) { APP.W_ScreenRecordingToolbarWindow.flg = 0; } else { APP.W_ScreenRecordingToolbarWindow.flg = 1; } Hide(); } /// /// 鼠标中建点击 /// void SwitchPages() { try { new Thread(() => { Thread.Sleep(500); MouseEventCommon.MouseMiddleClickEvent(0); }).Start(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void blackboard_canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { if (APP.W_ScreenRecordingToolbarWindow.flg == 10) { APP.W_ScreenRecordingToolbarWindow.flg = 0; } else { APP.W_ScreenRecordingToolbarWindow.flg = 1; } Hide(); } private void blackboard_canvas_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { if (APP.W_ScreenRecordingToolbarWindow.flg == 10) { APP.W_ScreenRecordingToolbarWindow.flg = 0; } else { APP.W_ScreenRecordingToolbarWindow.flg = 1; } ReturnPractice(); //模拟切到ppt SwitchPages(); //Hide(); } /// /// 退出批注并清空画板 /// public void ReturnPractice() { blackboard_canvas.Strokes.Clear(); new Thread(new ThreadStart(new Action(() => { Dispatcher.Invoke(() => { APP.W_ScreenRecordingToolbarWindow.ModifyState(); }); flg = 0; Thread.Sleep(500); Dispatcher.Invoke(() => { Owner = null; APP.W_PracticeWindow.Hide(); }); }))).Start(); } #region 点阵笔相关 #region 值初始化 // 不同尺寸点阵纸点阵宽高尺寸计算方法为:纸张物理尺寸(毫米)/0.3 *8,详见 开发必读.pdf 文档 /// /// A4点阵纸点阵宽度 /// private const int A4_WIDTH = 5600; /// /// A4点阵纸点阵高度 /// private const int A4_HEIGHT = 7920; ///// ///// 画板 ///// //private Graphics graphics; /// /// 笔画坐标数组 /// private List stroke; /// /// 笔序列号 /// private string penSerial; /// /// 笔是否在点 /// private bool isPenDown; //当前点阵地址 private string currentPageSerial = string.Empty; //不同点阵地址对应的笔迹绘制图片,用于实现在不同点阵地址书写切换时,显示书写内容自动切换 //本例图片放在内存中存储,对于大量或者需要在多个点阵地址对应图片进行切换演示,建议将图片存储到文件,以免内存溢出 private Dictionary pagesDic = new Dictionary(); #endregion public void InitPen() { stroke = new List(); //获取点阵笔实例,并绑定点阵笔事件 //将授权文件内容传入,获取点阵笔对象实例 APP.digitalPen = DigitalPenHID.GetInstance(certificates.MyLicense.Bytes); //绑定笔连接事件 APP.digitalPen.PenConnected += OnPenConnect; //绑定笔断开事件 APP.digitalPen.PenDisconnect += OnPenDisconnect; //绑定笔书写输出坐标事件 APP.digitalPen.PenCoordinate += OnPenCoordinate; //绑定抬笔事件 APP.digitalPen.PenUp += OnPenUp; //绑定落笔事件 APP.digitalPen.PenDown += OnPenDown; APP.digitalPen.PenBatteryCapacity += OnBatteryCapacity; APP.digitalPen.PenMemoryFillLevel += OnMemoryFillLevel; //完成初始化点阵笔,开始与点阵笔通信 ERROR_CODE ER = APP.digitalPen.Start(); ////绑定笔在新的点阵地址页面书写事件 //APP.digitalPen.PenNewPage += APP.digitalPen_OnPenNewPage; ////绑定笔信息事件 //APP.digitalPen.PenInfo += APP.digitalPen_OnPenInfo; //启动接收笔数据,完成初始化工作 //ERROR_CODE rc = APP.digitalPen.Start(); //判断是否成功 if (ER != ERROR_CODE.ERROR_OK) { MessageWindow.Show("初始化失败,授权过期,返回值:" + ER.ToString()); } } /// /// 落笔 /// /// 时间戳,1970年1月1日到现在的总毫秒数 /// 点阵笔序列号 /// 点阵笔型号编号 private void OnPenDown(ulong time, string penSerial, int penType) { if (CheckAccess()) { Action action = new Action(OnPenDown); Dispatcher.Invoke(action, new object[] { time, penSerial, penType }); } else { isPenDown = true; } } /// /// 抬笔 /// /// 时间戳,1970年1月1日到现在的总毫秒数 /// 点阵笔序列号 /// 点阵笔型号编号 private void OnPenUp(ulong time, string penSerial, int penType) { if (CheckAccess()) { Action action = new Action(OnPenUp); Dispatcher.Invoke(action, new object[] { time, penSerial, penType }); } else { isPenDown = false; APP.PenSerial = penSerial; stroke.Clear(); } //if (APP.pageData.currpage > 0) //{ // Dispatcher.Invoke(new Action(() => // { // myblackboard.changepages(0, 0, true, Color, PenSize, APP.pageData.currpage - 1, 0); // })); //} if (strokes != null && strokes.StylusPoints.Count > 1) { isFirst = true; } stylusPoints = new StylusPointCollection(); stylusPoint = new StylusPoint(); strokes = null; } /// /// 笔断开 /// /// 时间戳,1970年1月1日到现在的总毫秒数 /// 点阵笔序列号 /// 点阵笔型号编号 private void OnPenDisconnect(ulong time, string penSerial, int penType) { if (CheckAccess()) { Action action = new Action(OnPenDisconnect); Dispatcher.Invoke(action, new object[] { time, penSerial, penType }); } else { APP.PenSerial = penSerial; APP.PenStatus = false; //UpdateDevStatus(); ////Dispatcher.Invoke(new Action(() => ////{ //// txbNotConnected.Text = "未连接"; //// txbNotConnecteds.Text = "未连接"; ////})); } } /// /// 笔连接 /// /// 时间戳,1970年1月1日到现在的总毫秒数 /// 点阵笔序列号 /// 点阵笔型号编号 private void OnPenConnect(ulong time, string penSerial, int penType) { if (CheckAccess()) { Action action = new Action(OnPenConnect); Dispatcher.Invoke(action, new object[] { time, penSerial, penType }); } else { APP.PenSerial = penSerial; APP.PenStatus = true; this.penSerial = penSerial; //连接后,在获取笔数据前,可以清除笔内的历史数据 //APP.digitalPen.ClearMemory(penSerial); //开始接收笔数据 APP.digitalPen.GetPenData(penSerial); //UpdateDevStatus(); ////Dispatcher.Invoke(new Action(() => ////{ //// txbNotConnected.Text = "已连接"; //// txbNotConnecteds.Text = "已连接"; ////})); } } /// /// 电池电量 /// /// /// /// /// private void OnBatteryCapacity(ulong time, string penSerial, int penType, byte capacity) { if (CheckAccess()) { Action action = new Action(OnBatteryCapacity); Dispatcher.Invoke(action, new object[] { time, penSerial, penType, capacity }); } else { //System.Windows.MessageWindow.Show("电池电量:" + capacity.ToString()); } } /// /// 已用存储 /// /// /// /// /// private void OnMemoryFillLevel(ulong time, string penSerial, int penType, byte fillLevel) { if (CheckAccess()) { Action action = new Action(OnMemoryFillLevel); Dispatcher.Invoke(action, new object[] { time, penSerial, penType, fillLevel }); } else { //System.Windows.MessageWindow.Show("存储:" + fillLevel.ToString()); } } /// /// 笔书写,收到坐标 /// /// 时间戳,1970年1月1日到现在的总毫秒数 /// 点阵笔序列号 /// 点阵笔型号编号 /// 点阵地址 /// x坐标 /// y坐标 /// 压力值 private void OnPenCoordinate(ulong time, string penSerial, int penType, string pageSerial, int cx, int cy, byte force) { if (CheckAccess()) { Action ac = new Action(OnPenCoordinate); Dispatcher.Invoke(ac, new object[] { time, pageSerial, penType, pageSerial, cx, cy, force }); } else { //判断是否是落笔后输出的坐标,在设置悬浮模式下,落笔前的悬浮坐标不绘制 if (!isPenDown) { return; } stroke.Add(new System.Drawing.Point(cx, cy)); double PropW = blackboard_canvas.ActualWidth / A4_HEIGHT; double PropH = blackboard_canvas.ActualHeight / A4_WIDTH; //点 double testX = cy * PropW; double testY = (A4_WIDTH - cx) * PropH; //pageSerial //点阵IP地址 与打印的页面关联 if (true) { Dispatcher.Invoke(new Action(() => { float Pressure = force / 100f; ////添加笔画 //myblackboard.changepages(testX, testY, false, Color, PenSize, APP.pageData.currpage - 1, Pressure); if (isFirst) { stylusPoint.X = testX; stylusPoint.Y = testY; //_color.A = (byte)(Pressure * 255f); //stylusPoint.PressureFactor = Pressure; //for(int i=0;i<100;i++) //{ // stylusPoint.X--; // stylusPoint.Y--; // stylusPoints.Add(stylusPoint); //} stylusPoints.Add(stylusPoint); if (stylusPoints.Count > 1) { drawing = new DrawingAttributes { Color = Colour, Width = Wit * 4.5, Height = Wit * 4.5, FitToCurve = true, IgnorePressure = false }; //blackboard_canvas.Strokes = new StrokeCollection(); strokes = new Stroke(stylusPoints); strokes.DrawingAttributes = drawing; //blackboard_canvas.Strokes.Add(strokes); blackboard_canvas.Strokes.Add(strokes); isFirst = false; } } else { if (blackboard_canvas.Strokes.Count>0) { stylusPoint.X = testX; stylusPoint.Y = testY; stylusPoints.Add(stylusPoint); strokes = new Stroke(stylusPoints); drawing = new DrawingAttributes { Color = Colour, Width = Wit * 4.5, Height = Wit * 4.5, FitToCurve = true, IgnorePressure = false }; strokes.DrawingAttributes = drawing; //viewModel.InkStrokes.Add(strokes); blackboard_canvas.Strokes[blackboard_canvas.Strokes.Count - 1] = strokes; } } //设置鼠标位置 if (testX > 0 && testY > 0) { //System.Windows.Point getP = scroMain.PointToScreen(new System.Windows.Point(testX, testY - scroMain.VerticalOffset)); SetCursorPos((int)((float)testX* (PrimaryScreen.DpiX / 96f)), (int)((float)testY* (PrimaryScreen.DpiY / 96f))); } })); } } } bool isFirst = true; private StylusPointCollection stylusPoints = new StylusPointCollection(); private StylusPoint stylusPoint = new StylusPoint(); private Stroke strokes; /// /// 停止笔 /// public void StopDigitalPen() { //停止,释放资源 APP.digitalPen.Stop(); } /// /// 清空笔内存储 /// public void ClearPenStorage() { if (!string.IsNullOrEmpty(penSerial)) { APP.digitalPen.ClearMemory(penSerial); } } /// /// 获取剩余电量 /// public void GetPenElectricityQuantity() { if (!string.IsNullOrEmpty(penSerial)) { APP.digitalPen.GetBatteryCapacity(penSerial); } } /// /// 获取存储空间 /// public void GetUsedStorage() { if (!string.IsNullOrEmpty(penSerial)) { APP.digitalPen.GetMemoryFillLevel(penSerial); } } /// /// 开启悬浮 /// public void 开启悬浮() { if (!string.IsNullOrEmpty(penSerial)) { APP.digitalPen.SetPenHoverMode(true, penSerial); } } /// /// 关闭悬浮 /// public void 关闭悬浮() { if (!string.IsNullOrEmpty(penSerial)) { APP.digitalPen.SetPenHoverMode(false, penSerial); } } /// /// 引用user32.dll动态链接库(windows api), /// 使用库中定义 API:SetCursorPos /// 设置光标位置 /// [System.Runtime.InteropServices.DllImport("user32.dll")] private static extern int SetCursorPos(int x, int y); #endregion } }