时间:2021-05-19
InkCanvas是WPF中进行墨迹绘制的控件,本文介绍下InkCanvas控件是如何进行选择操作的。文中有误的地方希望大家进行批评指正。
使用WPF可以轻松实现白板功能,只需要添加一个InkCanvas控件。修改InkCanvas的EditingMode属性可以控制InkCanvas的操作模式,如书写、选择、擦除等模式。
如下demo在窗口中添加一个InkCanvas,然后添加一个Button实现书写与选择模式的切换。
运行demo,书写后点击按钮进行选择,可以看到InkCanvas的选择操作如下图所示:
从图中可以看出,InkCanvas的选择效果有如下特点:
接下来看下WPF是如何实现这种选择操作的。
首先,InkCanvas的编辑功能(书写、擦除、选择等)是通过EditingCoordinator管理的,该类包含一系列的EditingBehavior,实现选择过程的为LassoSelectionBehavior类,实现选择后对选择框操作的为SelectionEditor与SelectionEditingBehavior。本文主要介绍选择后对选择框的操作过程,选择过程以及笔迹的高亮显示打算单独写一篇文章进行介绍。
在InkCanvas中,与选择功能相关的对象有InkCanvasSelection、InkCanvasSelectionAdorner及InkCanvasFeedbackAdorner。后两者为装饰器,装饰器的介绍可参考官方文档。
先看InkCanvasSelectionAdorner类,直接看其OnRender方法,代码如下。首先绘制了选择框的背景,然后绘制了选择框(矩形虚线效果),最后绘制了选择框上的9个小矩形按钮。按钮可以进行拖动调节,具体实现逻辑可以看代码,本文不赘述。
protected override void OnRender(DrawingContext drawingContext){ DrawBackground(drawingContext); Rect rectWireFrame = GetWireFrameRect() if(!rectWireFrame.IsEmpty) { drawingContext.DrawRectangle(null, _adornerBorderPen, rectWireFrame); DrawHandles(drawingContext, rectWireFrame); }}再看InkCanvasFeedbackAdorner类,同样看OnRender方法,代码如下。其仅绘制了矩形虚线选择框,通过这两个类的OnRender方法,结合上文中的动画,可以知道选中后使用InkCanvasSelectionAdorner进行装饰,对选择框的操作(拖动)使用InkCanvasFeedbackAdorner进行装饰。
protected override void OnRender(DrawingContext drawingContext){ drawingContext.DrawRectangle(null, _adornerBorderPen, new Rect(CornerResizeHandleSize / 2, CornerResizeHandleSize / 2, _frameSize.Width - CornerResizeHandleSize, _frameSize.Height - CornerResizeHandleSize));}接下来看下这两个Adorner是对谁进行装饰的,首先看InkCanvas的OnPreApplyTemplate方法,代码如下。注释部分是InkCanvas的Visual Tree,可以了解到InkCanvas的内部结构。再看下SelectionAdorner的初始化,可以看出是对InnerCanvas进行装饰,InnerCanvas是InkCanvas的内部容器,放置笔迹及其它UIElement。SelectionAdorner添加了对ActiveEditingMode的绑定,当Mode为None时,隐藏,否则显示。FeedbackAdorner的装饰对象通过其构造函数可以看出,也是装饰的InnerCanvas。
internal override void OnPreApplyTemplate(){ base.OnPreApplyTemplate(); // Build our visual tree here. // <InkCanvas> // <AdornerDecorator> // <InkPresenter> // <InnerCanvas/> // <ContainerVisual/> // <HostVisual/> // </InkPresenter> // <AdornerLayer> // <InkCanvasSelectionAdorner/> // <InkCanvasFeedbackAdorner/> // </AdornerLayer> // </AdornerDecorator> // </InkCanvas> if(_localAdornerDecorator == null) { _localAdornerDecorator = new AdornerDecorator(); InkPresenter inkPresenter = InkPresenter; AddVisualChild(_localAdornerDecorator); _localAdornerDecorator.Child = inkPresenter; inkPresenter.Child = InnerCanvas; _localAdornerDecorator.AdornerLayer.Add(SelectionAdorner); }}internal InkCanvasSelectionAdorner SelectionAdorner{ get { if(_selectionAdorner == null) { _selectionAdorner = new InkCanvasSelectionAdorner(InnerCanvas); Binding activedEditingModeBinding = new Binding(); activedEditingModeBinding.Path = new PropertyPath(InkCanvas.ActiveEditingModeProperty); activedEditingModeBinding.Mode = BindingMode.OneWay; activedEditingModeBinding.Source = this; activedEditingModeBinding.Converter = new ActiveEditingMode2VisibilityConverter(); _selectionAdorner.SetBinding(UIElement.VisibilityProperty, activedEditingModeBinding); } return _selectionAdorner; }}// InkCanvasFeedbackAdornerinternal InkCanvasFeedbackAdorner(InkCanvas inkCanvas) : base((inkCanvas != null ? inkCanvas.InnerCanvas : null)) {...}最后,我们看下对选择框进行的操作是如何实现的。选择后会激活SelectionEditingBehavior,在其OnActivate方法中,绑定了SelectionAdorner的MouseMove/MouseUp/LostMouseCapture事件,并调用InkCanvasSelection.StartFeedbackAdorner()方法对FeedbackAdorner进行初始化,将其添加到AdornerLayer中。然后通过响应MouseMove,调用InkSelection.UpdateFeedbackAdorner()方法更新FeedbackAdorner的位置。最后在MouseUp响应中释放FeedbackAdorner。删减代码如下,具体的实现逻辑可以看WPF源码。
protected override void OnActive(){ // ... InkCanvas.InkCanvasSelection.StartFeedbackAdorner(_selectionRect, _hitResult); InkCanvas.SelectionAdorner.AddHandler(Mouse.MouseUpEvent, new MouseButtonEventHandler(OnMouseUp)); InkCanvas.SelectionAdorner.AddHandler(Mouse.MouseMoveEvent, new MouseEventHandler(OnMouseMove)); InkCanvas.SelectionAdorner.AddHandler(Mouse.LostMouseCaptureEvent, new MouseEventHandler(OnLostMouseCapture));}private void OnMouseMove(object sender, MouseEventArgs args){ // ... InkCanvas.InkCanvasSelection.UpdateFeedbackAdorner(newRect); // ...}以上就是详解WPF的InkCanvas选择模式的详细内容,更多关于WPF的InkCanvas选择模式的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
WPF的InkCanvas就是一个画板,可以在上面随意涂鸦,每写上一笔,InkCanvas的Strokes集合里就新增一个涂鸦对象,下面的代码演示了基本的操作。
如果不用VS的WPF项目模板,如何手工创建一个WPF程序呢?我们来模仿WPF模板,创建一个最简单的WPF程序。第一步:文件——新建——项目——空项目,创建一个空
MySQL设计和命令行模式下建立详解系列文章:MySQL设计和命令行模式下建立详解C++利用MySQLAPI连接和操作数据库实例详解1.数据表的设计MySQL数
C#中WPFListView绑定数据的实例详解WPF中ListView用来显示数据十分方便,我们可以将它分成几个列,每一个列用来显示一条数据,但是又是在一方之中
VS2019打包WPF安装程序最新教程,使用VisualStudio2019开发的WPF程序如果想要打包为安装程序,除了在VS2019找到WPF项目类库直接右键