Silverlight中的InkPresenter(可以保存、加载)
InkPresenter,这个东西再熟悉不过,没错就是手写板,我们可以在它上边想怎么画怎么画,其实他的原理很简单,就是捕捉鼠标的轨迹,然后使用指定的颜色和宽度组成线条,然后不停的记录和显示。
先看个效果
就是一个简单的手写(鼠标).
下面开始详细介绍InkPresenter的使用。
首先看下要使用到的类,以及方法:
1.InkPresenter,InkPresenter成为墨迹控件,继承自Canvas类,它不单单是一个控件,而是一个可以接收SL中输入的接口;
主要属性Strokes,一个集合(StrokeCollection),表示要显示的画笔。
2.Stroke,表示单个墨迹画笔,属性DrawingAttributes表示当前画笔的属性,指定 Stroke 的外观。StylusPoints(StylusPointCollection类型集合),返回Stroke的触笔
接触点。
DrawingAttributes属性如下:
名称 | 说明 | |
---|---|---|
Color | 获取或设置 Stroke 的颜色。 | |
FitToCurve | 获取或设置一个值,该值指示是否使用贝塞尔曲线平滑法来呈现 Stroke。 | |
Height | 获取或设置用于绘制 Stroke 的触笔的高度。 | |
IgnorePressure | 获取或设置一个值,该值指示呈现的 Stroke 的粗细是否会随应用的压力而更改。 | |
IsHighlighter | 获取或设置一个值,该值指示 Stroke 看起来是否像一支荧光笔。 | |
StylusTip | 获取或设置用于绘制 Stroke 的触笔的形状。 | |
StylusTipTransform | 获取或设置 Matrix,它指定要在触笔笔尖上执行的变换。 | |
Width | 获取或设置用于绘制 Stroke 的触笔的宽度。 |
有了以上两个类,就可以完成墨迹控件的使用,下面开始看看如何在案例中使用:
<InkPresenter x:Name="inkTest" Height="400" Width="600" Background="AliceBlue" MouseMove="inkTest_MouseMove" MouseLeftButtonDown="inkTest_MouseLeftButtonDown" MouseLeftButtonUp="inkTest_MouseLeftButtonUp">
</InkPresenter>
可以看到仅仅一个标签就完成了一个InkPresenter的定义,在这里有一点要注意,有些童鞋发现拉过来一个控件之后,包括鼠标的事件代码都写了,可是就是不能画,首先
要确保当前的InkPresenter是否定义了BackGround(或者给InkPresenter添加了其他的元素),其次看看画笔的颜色问题。
下面看下在Inkpresenter中嵌套一个元素:
<InkPresenter x:Name="inkTest" Height="400" Width="600" MouseMove="inkTest_MouseMove" MouseLeftButtonDown="inkTest_MouseLeftButtonDown" MouseLeftButtonUp="inkTest_MouseLeftButtonUp"><Rectangle RadiusX="15" RadiusY="15" Margin="5" Height="400" Width="600"><Rectangle.Fill><ImageBrush ImageSource="Chrysanthemum.jpg" Opacity="0.5" ></ImageBrush></Rectangle.Fill></Rectangle></InkPresenter>
可以看到在InkPresenter中嵌套了一个Rectangle,同时指定Rectangle的背景图片,这样就可以在这个图片上进行画东西了,效果也就是本文开头的那副图片。
大家可能注意到了在Ink上定义了三个鼠标事件,没错这个事件也是重点。
MouseMove事件用于记录鼠标在移动的过程中将轨迹写入到Stroke的StylusPoints集合中去;
MouseLeftButtonDown事件,用于捕获鼠标的坐标同时记录一个新的Stroke(新的画笔)开始,标识一个状态,以便在Move事件中进行点的记录;
MouseLeftButtonUp事件用于释放当前的鼠标捕获,同时释放Stroke,标识当前的Stroke已经结束;
UIElement.CaptureMouse()方法用于鼠标捕获当前的元素;
UIElement.ReleaseMouseCapture()方法,如果该元素具有鼠标捕获,则释放鼠标捕获。
从这里开始,编写后台代码:
Color currentColor = Colors.Black;//定义默认颜色 Stroke newStroke;//定义全局的画笔,用于在MouseDown中实例化,同时在Up中清空该对象 IsolatedStorageSettings setting = IsolatedStorageSettings.ApplicationSettings;//定义独立缓存,用于保存
//Ink鼠标移动事件 private void inkTest_MouseMove(object sender, MouseEventArgs e) {//如果不为空则说明已经按下了鼠标 if (newStroke != null) {//将鼠标移动中的点的轨迹添加到Stroke的StylusPoints newStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(inkTest)); } }
//Ink鼠标左键按下事件private void inkTest_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {//捕获鼠标(必须的) inkTest.CaptureMouse();//实例化画笔 newStroke = new Stroke();//设置画笔颜色 newStroke.DrawingAttributes.Color = currentColor;//指定轮廓的颜色 newStroke.DrawingAttributes.OutlineColor = Colors.Black;//将鼠标点下的点添加到画笔中区 newStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(inkTest));//将画笔添加到InkPresenter的Strokes(画笔集合) inkTest.Strokes.Add(newStroke); }
//Ink鼠标左键松开事件private void inkTest_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { newStroke = null;
//释放鼠标捕获 inkTest.ReleaseMouseCapture(); }
以上代码已经完成了,画图的显示,其实整个原理很简单
在鼠标左键按下时候开始进行鼠标的捕获,同时创建Stroke(画笔),并且将点放到Stroke的StylusPoints中,在此还可以设置Stroke的DrawingAttributes,然后将Stroke添加
到Ink的Strokes中去。
在鼠标的移动事件中,记录这些鼠标经过的点,添加到Stroked的StylusPoints中去。
在鼠标左键放开事件中的任务很简单就是将Stroke对象清空,保证Move事件中不会对空对象(未按下左键)进行操作,同时释放鼠标的捕获.
下面开始进行Ink的保存工作,保存Ink的原理也很简单,将Xaml代码通过程序转换成Xml的形式,保存的最终是将xml文件保存到独立存储中
private void SaveInk() { XElement element = ConvertStrokeToString(inkTest.Strokes);using (IsolatedStorageFile stroage = IsolatedStorageFile.GetUserStoreForApplication()) {using (IsolatedStorageFileStream fs = stroage.CreateFile("Ink.xml")) {using (StreamWriter sw = new StreamWriter(fs)) { sw.WriteLine(element); } } } HtmlPage.Window.Alert("保存成功!"); }
该方法传递一个StrokeCollection 类型的参数,也就是Ink的Strokes属性,通过循环处理形成Xml节点
private XElement ConvertStrokeToString(StrokeCollection originStrokes) {//添加命名空间 string xmlnsString = ""; XNamespace xmls = xmlnsString; XElement XStroke = new XElement(xmls + "StrokeCollection", new XAttribute("xmlns", xmlnsString));//创建笔画 XElement mystroke;//遍历当前Ink上的所有Stroke foreach (Stroke item in originStrokes) {//实例化XElement对象,并且把Stroke的属性一一对应放到XElement节点中去 mystroke = new XElement(xmls + "Stroke",new XElement(xmls + "Stroke.DrawingAttributes",new XElement(xmls + "DrawingAttributes",new XAttribute("Color", item.DrawingAttributes.Color),new XAttribute("OutlineColor", item.DrawingAttributes.OutlineColor),new XAttribute("Width", item.DrawingAttributes.Width),new XAttribute("Height", item.DrawingAttributes.Height))));//定义StylusPoint节点 XElement mypoints = new XElement(xmls + "Stroke.StylusPoints");//遍历Stroke的StylusPoints foreach (StylusPoint sp in item.StylusPoints) { XElement mypoint = new XElement(xmls + "StylusPoint",new XAttribute("X", sp.X),new XAttribute("Y", sp.Y)); mypoints.Add(mypoint); }//StylusPoint节点添加到Stroke节点中 mystroke.Add(mypoints);//将Stroke节点添加到根节点中 XStroke.Add(mystroke); }return XStroke; }
下面这个方法用于加载Xml(从独立存储中),将Xml转换为Ink所需的对象,返回Ink的Strokes对象所需的StrokeCollection类型
private StrokeCollection ConvertStringToStroke(string xmlName) { StrokeCollection strokeCollection = new StrokeCollection(); XNamespace xmlnsString = "";//使用独立存储来得到保存的Ink文件xml using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication()) {//打开指定的文件 using (IsolatedStorageFileStream fs = storage.OpenFile(xmlName, FileMode.Open, FileAccess.Read)) {//得到读取流 using (StreamReader sr = new StreamReader(fs)) {string content = sr.ReadToEnd();//加载xml XElement document = XElement.Parse(content);//得到所有的Stroke标签 var strokes = from stroke in document.Elements(xmlnsString + "Stroke") select stroke;//遍历Stroke节点 foreach (XElement item in strokes) {//得到DrawingAttribute节点 XElement drawingAttribute = item.Element(xmlnsString + "Stroke.DrawingAttributes").Element(xmlnsString + "DrawingAttributes");//实例化Stroke Stroke newStroke = new Stroke();//实例化Stroke的StylusPoint StylusPoint point = new StylusPoint();//实例化 StylusPointCollection StylusPointCollection pointCollection = new StylusPointCollection();//实例化DrawingAttributes DrawingAttributes attribute = new DrawingAttributes();//赋值给DrawingAttributes对象 attribute.Color = ReturnColorFromString(drawingAttribute.Attributes("Color").First().Value); attribute.OutlineColor = ReturnColorFromString(drawingAttribute.Attributes("OutlineColor").First().Value); attribute.Width = Convert.ToDouble(drawingAttribute.Attributes("Width").First().Value); attribute.Height = Convert.ToDouble(drawingAttribute.Attributes("Height").First().Value); newStroke.DrawingAttributes = attribute; //得到StylusPointCollection集合 var styluspoints = from p in item.Element(xmlnsString + "Stroke.StylusPoints").Elements(xmlnsString + "StylusPoint") select p;//遍历StylusPointCollection节点 foreach (XElement pointElement in styluspoints) { point.X = Convert.ToDouble(pointElement.Attribute("X").Value); point.Y = Convert.ToDouble(pointElement.Attribute("Y").Value); pointCollection.Add(point); }//赋值给Stroke的StylusPoints newStroke.StylusPoints = pointCollection;//将Stroke添加到strokeCollection strokeCollection.Add(newStroke); } } } }return strokeCollection; }
由于需要保存颜色则写了自定义方法:
将RGB码转换为Color类型对象
public Color ReturnColorFromString(string color) {string alpha = color.Substring(1, 2);string red = color.Substring(3, 2);string green = color.Substring(5, 2);string blue = color.Substring(7, 2); byte alphaByte = Convert.ToByte(alpha, 16);byte redByte = Convert.ToByte(red, 16);byte greenByte = Convert.ToByte(green, 16);byte blueByte = Convert.ToByte(blue, 16);return Color.FromArgb(alphaByte, redByte, greenByte, blueByte); }
到这里简单的Ink操作,保存以及加载都已ok,望多多指教,另附上源码下载
[InkDemo]
转载于:https://www.cnblogs.com/ListenFly/archive/2011/10/23/2219672.html
Silverlight中的InkPresenter(可以保存、加载)相关推荐
- Matlab停在载入界面,试图在Matlab用户界面中实现保存/加载对象功能时遇到了困难...
我尝试在Matlab(R2009A)用户界面中实现保存/加载函数.我的对象实现了一个布局函数,它为对象生成一个用户界面.我正在尝试实现保存/加载按钮的回调."保存"按钮起作用,并将 ...
- unity保存加载慢_掌握Unity 5中的保存和加载功能
unity保存加载慢 Thanks to Vincent Quarles for kindly helping to peer review this article. 感谢Vincent Quarl ...
- 【GDScript】保存/加载物品装备数据
> Godot 3.3 rc6 接着上个文章 [Godot]加载文件数据 我们开始给装备栏和物品栏制作保存数据的功能.(文末有文件项目链接) 我们在 FileManager.gd 脚本里添加如下 ...
- word2vec模型训练保存加载及简单使用
目录 word2vec模型训练保存加载及简单使用 一 word2vec简介 二.模型训练和保存及加载 模型训练 模型保存和加载 模型的增量训练 三.模型常用API 四.文本相似度计算--文档级别 wo ...
- orb_slam3实现保存/加载地图功能and发布位姿功能
1.保存/加载地图 先说方法:在加载的相机参数文件.yaml的最前面加上下面两行就行. System.LoadAtlasFromFile: "MH01_to_MH05_stereo_iner ...
- Unity中使用代码将预制加载到场景
Unity中使用代码将预制加载到场景 大家知道, 在日常修改预制的时候很方便, 我们将预制从资源文件夹往场景上"一拖", 然后就可以进行修改, 然后应用保存即可. 但是如果某些需求 ...
- android progressdialog 背景色,怎么在android中利用ProgressDialog实现一个加载效果
怎么在android中利用ProgressDialog实现一个加载效果 发布时间:2020-12-07 17:00:07 来源:亿速云 阅读:77 作者:Leah 怎么在android中利用Progr ...
- docker保存linux镜像,docker导入导出容器和保存加载镜像
系统环境:centos7.4 版本: # docker -v 1.docker容器导入导出 (1)查看:# docker ps -a (2)导出---export # docker export we ...
- R语言保存加载工作空间或者工作空间数据对象实战(Save Load RData Workspace)
R语言保存加载工作空间或者工作空间数据对象实战(Save & Load RData Workspace) 目录 R语言保存加载工作空间或者工作空间数据对象实战(Save & Load ...
最新文章
- 使用ROS和TensorFlow进行深度学习
- sqlserver ADO.net 查询数据库加锁,事务提交
- OpenCASCADE绘制测试线束:数据交换命令之XDE 图层命令
- JavaScript通过 new FileReader() 获取图片base64 无组件上传图片
- ASP.NET MVC3 系列教程 - 部署你的WEB应用到IIS 6.0
- 深入java虚拟机(二) 对象的创建
- hash算法_hash一致性算法
- SDOI2017 树点涂色
- oracle 没有debug权限,开启Oracle的debug级别日志
- 计算机桌面图标损坏,win7系统的电脑桌面图标受到损坏要如何修复
- Raid5数据恢复算法原理- raid5数据恢复案例
- 用数据分析头部微信公众号到底有多牛
- Arduino的控制(一):Arduino步进电机六轴机械手(油管搬)
- 链接、图像、列表、计数器
- 商务英语基础: 口语 | Essential Business English: Speaking
- 两台电脑共享鼠标键盘
- python字符串常用方法变量名命名规范
- python用来初始化对象属性的是_猪行天下之Python基础——8.1 类与对象
- 什么是邓宁-克鲁格效应(The Dunning-Kruger Effect)?
- 老吕架构-2022~2021年文章索引
热门文章
- Java面向对象基础学习笔记(构造、重载、继承、多态、抽象类、接口、模块)
- 力扣有没有java_力扣题解
- 一键开启微信“开关头像”,快试试!
- 翁恺老师C语言学习笔记(十一)字符串
- 今日恐慌与贪婪指数为70 贪婪程度有所缓解
- 观点:比特币新一轮突破“即将到来”
- SAP License:SAP RKE_HZSTMP标准时间转EXCEL日期方法
- 那些机器学习中无法衍生的强规则变量有吗?
- 风控人最容易被误解的一个风险管理板块
- 「BZOJ2190」[SDOI2008] 仪仗队 - 欧拉函数