基于InkCanvas实现的桌面涂鸦工具-[ WPF开发 ]
首先简单的介绍下InkCanvas,简单的来说,InkCanvas就是在WPF中实现允许使用墨迹的布局控件。实际上,InkCanvas有着更多层面上的应用,它的主要目的是(通过鼠标或者和指示笔)捕捉笔迹。InkCanvas从技术上说不是一个控件,因为它直接从FrameworkElement继承而来,但是它的行为和控件非常像(但不能用一个新的模板来改变它的样式)。
默认模式下,InkCanvas允许在它的表面上进行简单的书写和画图。当使用指示笔时,笔尖用来写、笔端用来擦。每一个笔画被捕捉为一个System.Windows.Ink.Stroke对象,保存在InkCanvas的Strokes集合中。但是InkCanvas也支持在Children集合(一个内容属性)中保留任意数量的UIElement元素。这样很容易通过墨水(ink)来注释任何东西。如下面的代码,我们可以很容易的生成一个InkCanvas画板。
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="InkCanvasSample" Width="220" Height="87">
<InkCanvas>
<InkCanvas.DefaultDrawingAttributes>
<DrawingAttributes Color="Red" />
</InkCanvas.DefaultDrawingAttributes>
<Image Source="E:\Cnblogs\wwf.png"/>
</InkCanvas>
</Window>
InkCanvas 支持几种模式,它们能利用EditingMode属性被独立地应用到指示笔尖(或鼠标),并通过EditingModeInverted属性来应用于指示笔的末端(back end)。只读的ActiveEditingMode属性可以告诉你哪一个属性当前正在被使用。所有这3个属性都是InkCanvasEditingMode类型的,它有以下几种值:
1、Ink(EditingMode的默认值) —— 通过鼠标或者指示笔来绘制笔画。
2、InkAndGesture —— 和Ink一样,但同样可以识别用户的手势。手势的列表(Up、Down、Circle、ScratchOut和Tap)保存在System.Windows.Ink.ApplicationGesture枚举类型中。
3、GestureOnly —— 只识别手势,不会绘制用户输入的笔画。
4、EraseByStroke (EditingModeInverted的默认值)—— 当笔画被触及时将笔画擦掉。
5、EraseByPoint —— 只擦掉直接碰及到的笔画部分(就像传统的铅笔橡皮)。
6、Select —— 当被触及时,选择笔画或者任何UIElement,使它们能被删除、移动或者在InkCanvas范围内被调整尺寸。
7、None —— 对于鼠标或者指示笔不做任何响应。
一些普通元素与墨水没有任何关系,如果在这些元素上使用Select模式将非常有趣,因为它自动会提供一个“穷人”的运行时设计界面用来排列控件。InkCanvas还定义了15种事件,其中包括改变编辑模式、改变/移动/调整选择、收集或者擦除笔画,以及执行手势。当然,在应用程序中使用墨水比在人脸上画胡子还是要复杂些!你经常要对一个笔画集合做手写识别,如果输入的是字符你就可以分析出它。WPF拥有内建的手势识别功能,但没有手写识别引擎。
概述
程序截图如下:
大概的一个思路就是主要有两个操作窗口,一个是主窗口,可以进行新建涂鸦、调整画笔彩色、画笔形状等等,另外一个就是涂鸦的画板了。首先先截图,然后设置Inkcanvas的Background属性为该图片,然后就可以在上面进行画图了。主要要处理的细节问题在于:
- 截图的问题
- 取得窗口坐标的问题
- 窗口之间传值的问题
把这些细节处理好就很容易就可以实现了。
代码解释
首先是截图的问题。查MSDN,我找不到WPF里有现在的API可以调用,只能通过winForm来实现截图,代码如下:
02 {
03 System.Drawing.Rectangle rc = SystemInformation.WorkingArea;
04 var bitmap = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
05
06 using (Graphics g = Graphics.FromImage(bitmap))
07 {
08 g.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy);
09 }
10
11 return bitmap;
12 }
13
14 public BitmapSource ToBitmapSource(Bitmap bmp)
15 {
16 BitmapSource returnSource;
17
18 try
19 {
20 returnSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
21 }
22 catch
23 {
24 returnSource = null;
25 }
26 return returnSource;
27
28 }
29 //截取整个屏幕作为画布,并开始画画
30 private void pencil_Click(object sender, RoutedEventArgs e)
31 {
32 //初始化画布
33 PainterWindow pw = new PainterWindow();
34 System.Drawing.Rectangle rc = SystemInformation.WorkingArea;
35 pw.Width = rc.Width;
36 pw.Height = rc.Height;
37 pw.ink.Width = rc.Width;
38 pw.ink.Height = rc.Height;
39 //截图
40 this.Hide();
41 Bitmap bt = GetScreenSnapshot();
42 BitmapSource bs = ToBitmapSource(bt);
43
44 System.Windows.Controls.Image img = new System.Windows.Controls.Image();
45 img.Source = bs;
46 pw.ink.Background = new ImageBrush(bs);
47 pw.Show();
48 this.Show();
49
50 }
看到上面的代码,通过System.Drawing.Rectangle rc = SystemInformation.WorkingArea;来获取当前系统工作窗口(不包括任务栏)的信息,包括分辨率的大小,各个点的坐标信息,获取这些信息后,新建一个bitmap,通过winForm里的CopyFromScreen函数我们把屏幕绘画在新建的那个bitmap上,然后获得bitmap的地址设置为BitmapSource,并设置ink的Background为ImageBrush(bs)即可。
下面是响应颜色选择的代码:
02 {
03 ColorDialog cd = new ColorDialog();
04 //取得颜色
05 if (cd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
06 {
07 //要去了解这两种颜色的不同之处
08 inkDA.Color = System.Windows.Media.Color.FromArgb(cd.Color.A, cd.Color.R, cd.Color.G, cd.Color.B);
09 inkDA.Height = 3;
10 inkDA.Width = 3;
11 inkDA.FitToCurve = true;
12 //修改颜色
13 foreach (Window win in System.Windows.Application.Current.Windows)
14 {
15 if (win.Title == "PainterWindow")
16 {
17 PainterWindow pw = win as PainterWindow;
18 pw.ink.DefaultDrawingAttributes = inkDA;
19 pw.Show();
20 }
21 }
22
23 }
24
25
26 }
要注意的是System.Widows.Media.Color与InkCanvas定义的颜色的不同,这中间需要通过一个函数来转换。
其实想着能把它完善好的,像形状的自定义,界面的细节调整,等。最近有太多的事情要做,所以先搁置下来,待时间过后再回来看自己的代码,熟悉下。
相关资料
一些关于InkCancas的资料
- WPF中InkCanvas(墨水面板)用法
- 分享WPF实现屏幕截图程序详解
- 桌面涂鸦工具下载(需要.net支持,涂鸦过程按Esc键退出涂鸦界面。)
- 源代码
转载于:https://www.cnblogs.com/wpdev/archive/2011/04/21/inkcanvas-sample.html
基于InkCanvas实现的桌面涂鸦工具-[ WPF开发 ]相关推荐
- 基于Marlin固件库桌面3D打印机软件开发
0 系统组成 1硬件 原理框图 2 软件开发平台 Arduino
- 一个为程序员定制的、WPF开发的小巧、美观桌面快捷工具
今天给大家推荐一个基于WPF开发的,专门为程序员定制的桌面快捷工具. 项目简介 这是基于.Net+WPF开发的,一个小巧.UI美观的快捷工具.此项目发布以来就受到大家的喜欢,代码结构清晰非常适合用来学 ...
- WPF学习12:基于MVVM Light 制作图形编辑工具(3)
本文是WPF学习11:基于MVVM Light 制作图形编辑工具(2)的后续 这一次的目标是完成 两个任务. 本节完成后的效果: 本文分为三个部分: 1.对之前代码不合理的地方重新设计. 2.图形可选 ...
- secret-performance-desktop - 基于javafx的桌面个性化工具
secret-performance-desktop 介绍 基于javafx的桌面个性化工具 起初只想在做个桌面的cpu和内存监控工具,连续迭代几个版本之后,成了一个桌面的个性化工具. 功能 cpu和 ...
- 基于RT-THREAD的桌面小工具
摘要 这个桌面小盒子是之前的东西,一直放着没有整理好.最近有空了就把他整理整理. 小盒子主要用来显示时间和天气预报,功能比较简单,其实还有很多可以玩的,懒得弄,所以就把最简单的整理出来. 软件是基于r ...
- WPF开发的实用小工具 - 快捷悬浮菜单
WPF开发的实用小工具 - 快捷悬浮菜单 ❝ 本文由网友投稿,Dotnet9站长整理.站长觉得这小工具很实用,站长家里.公司也在尝试使用了. 行文目录: 这工具有什么用? 正文 源码获取及应用下载体验 ...
- 基于javaGUI的文档识别工具制作
基于javaGUI的文档识别工具制作 对于某些文本,其中富含了一些标志,需要去排除,以及去获得段落字数,以下是我个人写的一个比较简单的文档识别工具,含导入文件.导出文件以及一个简单的识别功能. 1.功 ...
- 纸上原型设计 VS 桌面原型工具设计,你更喜欢谁?
2019独角兽企业重金招聘Python工程师标准>>> 纸上原型设计,作为传统的原型设计方式,简单快速,成本低廉,为大部分设计师所喜爱.而桌面原型工具设计,作为伴随电脑科技发展而出现 ...
- Redis 桌面管理工具 RedisDesktopManager 2019.0 发布
百度智能云 云生态狂欢季 热门云产品1折起>>> RedisDesktopManager 2019.0 版本已发布,Redis Desktop Manager(RedisDesk ...
最新文章
- Linux kernel 不输出log信息
- lombok快速入门:实体类中再也不用写setter和getter,toString等方法了
- java print int_java – 在printin输入int
- 河源电大有考计算机等级的吗,河源电大有什么专业自考也有?
- 建模:确定服务的边界——《微服务设计》读书笔记
- Java面向对象编程(基础部分)
- 在Spring Boot中使用Vaadin的简介
- 前端学习(3191):react中案例
- 使用PHP对word文档进行操作的方法
- iOS开发SDWebImage源码解析之SDWebImageManager的注解
- 波特率dlm_ARM学习随笔(13)UART的理解
- Java中的移位操作——Java编程思想笔记
- 大数据教程,大数据学习线路图
- 机器学习(三):线性模型
- 科技企业捐赠武汉最新最全排名(截止2月13日)
- 安全狗技术分享|Web应用防火墙之攻击防护
- 中国股市:如果历史会重复?
- 【Unity】Rigibody——刚体加力、刚体加扭矩力、刚体加力的几种模式
- Z-Libary最新地址检测,再也不用担心找不到ZLibary了
- 计算机假期计划内容,寒假计划表内容
热门文章
- Anthem库的Google Suggest 实现
- 人际交往的“三有三避”
- ASP.NET 2.0 学习笔记 1: session 与 script 应用
- 通用的异步处理类和进度通知类及其示例
- java 统计图 mysql_java实现各种数据统计图(转)
- mysql每秒57000_MySQL 性能:使用 MySQL 5.7 实现每秒 50 万查询
- Nginx静态资源压缩实战内容介绍
- Spring如何将事件分配给专门的监听器?
- 什么时候用不到索引?
- jwt:token的解析