silverlight   发布时间:2022-05-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了My Silverlight系列(10)—— Silverlight中的InkCanvas大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

有许多人喜欢手写板或者涂鸦板之类的东西,而并不怎么喜欢输入法,因此Microsoft专门有Ink这个东西用于处理鼠标画图。不得不说这个东西功能十分的强大,也让许多用户使用起来非常方便,用微软开发出来的很多Ink与Bitmap结合的API,即使不会用Photoshop的人也能轻松打开一张图片,然后在自己喜欢的地方写上一段话或者签个名什么的。这个功能,Winform上面有,WPF上面也有,当然Silv

有许多人喜欢手写板或者涂鸦板之类的东西,而并不怎么喜欢输入法,因此Microsoft专门有Ink这个东西用于处理鼠标画图。不得不说这个东西功能十分的强大,也让许多用户使用起来非常方便,用微软开发出来的很多Ink与Bitmap结合的API,即使不会用Photoshop的人也能轻松打开一张图片,然后在自己喜欢的地方写上一段话或者签个名什么的。这个功能,Winform上面有,WPF上面也有,当然Silverlight上也有,只不过作为起步不久的Silverlight版Ink,功能尚不够强大,目前能够开放给我们使用的,只有InkPresenter这一个控件。

也许开发WPF的人都没怎么听说过这个控件而只听说过InkCanvas——那是一个在WPF上对Ink功能封装得非常完善的控件,我们可以使用它进行画图和橡皮擦等一系列的事情。当然,如果你去研究过这个控件,你就可以发现其实它其实是通过DataBinding在InkPresenter上进行了进一步的封装。由于WPF与Silverlight不同的继承结构,恐怕在Silverlight上很难照搬WPF上那一套,即我们不能对其进行一对一的Port,所以如果要在Silverlight上实现一个InkCanvas,就要另辟蹊径。

如果你使用过WPF的InkCanvas控件,你将会发现它支持EraseByPoint,EraseBystroke,Ink三种模式,而且支持复制、粘贴,而且可以轻松地扩展出撤销与重做两个功能。但是后面的一系列功能,不是InkCanvas的核心功能,只要前三者得以实现,那么这个InkCanvas就可以正常的运作了。那么,我们首先从这三种模式中用于画图的Ink模式说起。

InkCanvas的核心,其实在于它内部的InkPresenter,在Silverlight中InkPresenter仅仅是Canvas的子类,只不过它多了strokes这么一个属性用于存储和展示画上去的所有stroke。因此,它把如何生成一个stroke的问题完全留给了我们。先来看一下stroke的定义:

My Silverlight系列(10)—— Silverlight中的InkCanvas

My Silverlight系列(10)—— Silverlight中的InkCanvas

  //  SumMary:

My Silverlight系列(10)—— Silverlight中的InkCanvas

    
     represents a collection of points that correspond to a stylus-down, move,

My Silverlight系列(10)—— Silverlight中的InkCanvas

    
     and stylus-up sequence.

My Silverlight系列(10)—— Silverlight中的InkCanvas

     public   sealed   class  stroke : DependencyObject

My Silverlight系列(10)—— Silverlight中的InkCanvas

    
{

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
// SumMary:

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     initializes a new instance of the System.Windows.Ink.stroke class.

My Silverlight系列(10)—— Silverlight中的InkCanvas

        public stroke();

My Silverlight系列(10)—— Silverlight中的InkCanvas

        

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     initializes a new instance of the System.Windows.Ink.stroke class with the

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     specified System.Windows.Input.StylusPointCollection.

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
 Parameters:

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
   stylusPoints:

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     A System.Windows.Input.StylusPointCollection that represents the System.Windows.Ink.stroke.public stroke(StylusPointCollection stylusPoints);

My Silverlight系列(10)—— Silverlight中的InkCanvas


My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     Gets or sets the properties of the stroke, such as System.Windows.Ink.DrawingAttributes.Height,

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     System.Windows.Ink.DrawingAttributes.Width, System.Windows.Ink.DrawingAttributes.Color,0)">     or System.Windows.Ink.DrawingAttributes.OutlineColor.

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
 returns:

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     The System.Windows.Ink.DrawingAttributes of the stroke.

My Silverlight系列(10)—— Silverlight中的InkCanvas

        public DrawingAttributes DrawingAttributes { getset; }

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     Gets or sets the stylus points of the System.Windows.Ink.stroke.

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     The System.Windows.Input.StylusPointCollection that contains the stylus points

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     that represent the current System.Windows.Ink.stroke.

My Silverlight系列(10)—— Silverlight中的InkCanvas

        public StylusPointCollection StylusPoints { set; }

My Silverlight系列(10)—— Silverlight中的InkCanvas


My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     retrieves the bounding Box for the System.Windows.Ink.stroke object.

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     A System.Windows.Rect structure defining the bounding Box for the System.Windows.Ink.stroke

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     object.public rect GetBounds();

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     inDicates whether a specified System.Windows.Input.StylusPointCollection

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     intersects with a System.Windows.Ink.stroke object.

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
   stylusPointCollection:

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     The System.Windows.Input.StylusPointCollection used to check for intersection

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     with the System.Windows.Ink.stroke object.

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     true if the specified System.Windows.Input.StylusPointCollection intersects

My Silverlight系列(10)—— Silverlight中的InkCanvas

        
     with the System.Windows.Ink.stroke object; otherwise, false.public bool HitTest(StylusPointCollection stylusPointCollection);

My Silverlight系列(10)—— Silverlight中的InkCanvas

    }

My Silverlight系列(10)—— Silverlight中的InkCanvas

其中DrawingAttributes这个属性是用于描述画笔的颜色的,而StylusPoints描述了stroke内点的集合。学过数学的人都知道,线是由点组成的,因此只要我们找到了应该插入到这个stroke中所有的点,那么生成一个新的stroke不在话下。所幸MouseEventArgs中,有一个StylusDevice只读属性,而它的一个公共方法public StylusPointCollection GetStylusPoints(UIElement relativeTo)可以在鼠标事件触发的时候,得到这些“点”的集合。我们只需要为InkPresenter@L_723_74@mouSELEftButtonDown,MouseMove,MouSELEftButtonUp三个handler,那么我们就可以在鼠标进行轨迹上把那些点加到线上,并将这条线加入到InkPresenter这个“面”里。代码比较多,最后我会把工程放在下面,就不一段一段的贴了。

其实这个Ink模式,不算什么难点,而后面这个EraseBystroke也相对简单,最笨的方法就是遍历InkPresenter内所有的stroke,然后一一检验它是否与我们的"Eraser"有交叉,如果有,则将它Remove。但是,最后这个EraseByPoint可没那么容易了,因为当橡皮将一条线拦腰截断的时候,不但要把擦掉的部分去掉,还要把余下的两段保留在strokes这个strokeCollection中,这才能达到一分为二的效果。我最初在实现这个功能的时候,由于设计的算法时间复杂度居高不下,造成如果相交的线过多,或者橡皮拖动太快,就会出现卡死的现象。在与微软silverlight开发小组的stefan swick交流之后,他决定实现这一功能,并且将其做成一个Custom Control。昨天他告诉我他把这个东西做好了,要我去他的Blog上下载。今天我仔细研究了他的算法,发现这个算法与我的算法有一个最大的不同之处就是:我在将一条线一分为二的过程中,完全是按照从前向后的顺序,将每个点一一挎贝并缓存,从前向后判断这个点是否被橡皮擦中,如果被擦中的话,马上生成一个新的stroke,把旧的加入strokes内,并对新的stroke进行上述相同的操作。而stefan的算法则分为了两个部分,首先从前向后把前面没有被擦中的点取出来存到一个新的stroke中,然后停止,再从后往前寻找后面的点,将没有被擦中的点加入到一个新的stroke中,直到遇到被擦中的点停止。这样的话,可以保证一个stroke可以被一分为二。

经过我的测试,执行并没有什么问题。但是由于我们向stroke中插入点,完全依赖于MouseMove事件,如果我们的鼠标移动速度过快,那么被插入的这些本就离散的点,它们之前的间隔会变得更大。这在Ink模式下不会有什么问题,但是在EraseByPoint模式下,就会因被去掉的点附近没有其他的点,而一次性擦掉很大的一段,这是由于我们在插入点和擦除的时候没有做任何的优化造成的,希望这个问题能得到解决

大家可以到http://blogs.msdn.com/swick/archive/2008/11/30/erasing-ink-in-silverlight-2.aspx去看stefan的原文,那里提供工程原件的下载,我就不再多此一举把它上传博客园来浪费空间了。至于上面提到的问题,如果大家有什么优化的方式和算法,希望可以告诉我们,谢谢!

---------------------------------------------------------------

大佬总结

以上是大佬教程为你收集整理的My Silverlight系列(10)—— Silverlight中的InkCanvas全部内容,希望文章能够帮你解决My Silverlight系列(10)—— Silverlight中的InkCanvas所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。