返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >详解WPF的InkCanvas选择模式
  • 847
分享到

详解WPF的InkCanvas选择模式

2024-04-02 19:04:59 847人浏览 安东尼
摘要

目录Inkcanvas的选择效果InkCanvas选择模式的实现InkCanvas是WPF中进行墨迹绘制的控件,本文介绍下InkCanvas控件是如何进行选择操作的。文中有误的地方希

InkCanvas是WPF中进行墨迹绘制的控件,本文介绍下InkCanvas控件是如何进行选择操作的。文中有误的地方希望大家进行批评指正。

InkCanvas的选择效果

使用WPF可以轻松实现白板功能,只需要添加一个InkCanvas控件。修改InkCanvas的EditingMode属性可以控制InkCanvas的操作模式,如书写、选择、擦除等模式。
如下demo在窗口中添加一个InkCanvas,然后添加一个Button实现书写与选择模式的切换。


// xaml
<Grid>
  <InkCanvas x:Name="inkCanvas"/>
  <Button x:Name="btnChangeMode" Content="select" Click="Button_Click"
      Width="50" Height="30" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="10"/>
</Grid>

// cs
private void Button_Click(object sender, RoutedEventArgs e)
{
	if(btnChangeMode.Content == "select")
	{
    inkCanvas.EditingMode = InkCanvasEditingMode.Select;
    btnChangeMode.Content = "write";
	}
	else
	{
    inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
    btnChangeMode.Content = "select";
	}
}

运行demo,书写后点击按钮进行选择,可以看到InkCanvas的选择操作如下图所示:

从图中可以看出,InkCanvas的选择效果有如下特点:

  1. 选中后笔迹高亮;
  2. 选中后显示选择框;
  3. 拖动选择框,选择框随着鼠标移动,但选择的笔迹并未移动。

接下来看下WPF是如何实现这种选择操作的。

InkCanvas选择模式的实现

首先,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;
  }
}

// InkCanvasFeedbackAdorner
internal 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选择模式的资料请关注编程网其它相关文章!

--结束END--

本文标题: 详解WPF的InkCanvas选择模式

本文链接: https://lsjlt.com/news/122789.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 详解WPF的InkCanvas选择模式
    目录InkCanvas的选择效果InkCanvas选择模式的实现InkCanvas是WPF中进行墨迹绘制的控件,本文介绍下InkCanvas控件是如何进行选择操作的。文中有误的地方希...
    99+
    2024-04-02
  • 详谈Android ListView的选择模式
    效果图: ListView 定义了choiceMode属性,描述是这样的: 用于为视图定义选择行为。默认情况下,列表时没有任何选择行为的。如果把choiceMode设置为s...
    99+
    2022-06-06
    选择 listview Android
  • 详解Java枚举为什么是单例模式的最佳选择
    目录前言示例代码有哪些优点?线程安全序列化安全防止反射攻击简单明了可读性强总结前言 单例模式,是工作中比较常见的一种设计模式,通常有两种实现方式,懒汉式和饿汉式。但是这两种实现方式存...
    99+
    2023-05-19
    Java枚举实现单例模式 Java枚举 单例模式 Java枚举 Java 单例模式
  • PHP设计模式:如何选择适合的模式
    在 php 中选择设计模式的步骤:识别问题研究设计模式匹配模式到问题实施模式通过这些步骤,可以根据具体情况选择合适的设计模式,从而提高代码质量、灵活性性和可维护性。 PHP 设计模式:...
    99+
    2024-05-13
    php 设计模式 mysql 数据访问
  • 详解Golang函数式选项(Functional Options)模式
    概览 最近阅读源码的时候看到一段不错的代码,但是当时却不是非常理解为什么这么写。 我们先来看一下源代码: type User struct { ID string N...
    99+
    2024-04-02
  • Java工厂模式用法之如何动态选择对象详解
    目录前言小菜鸟的问题有没有更好的方法呢还有什么更好的办法吗还能做得更好吗如何在 SpringBoot 中实现此技术总结前言 工厂设计模式可能是最常用的设计模式之一,我想大家在自己的项...
    99+
    2023-03-10
    Java工厂模式动态选择对象 Java工厂模式 Java动态选择对象
  • JQuery选择器详解
    目录基本选择器:层级选择器:属性选择器:过滤器选择器:表单属性选择器:总结 选择器类似于CSS的选择器,可以帮助我们获取元素 基本选择器: 选择器:类似于 CSS 的选择器,可...
    99+
    2024-04-02
  • Java中map遍历方式的选择问题详解
    1. 阐述  对于Java中Map的遍历方式,很多文章都推荐使用entrySet,认为其比keySet的效率高很多。理由是:entrySet方法一次拿到所有key和value的集合;而keySet拿到的只是key的集合,针对每个key,都要...
    99+
    2023-05-31
    java map 遍历方式
  • 选择云服务器镜像模式的建议
    1. 了解不同的镜像类型 在选择云服务器镜像模式之前,首先需要了解不同的镜像类型。一般来说,云服务器镜像分为官方镜像和自定义镜像两种类型。官方镜像是云服务提供商提供的标准镜像,包含了操作系统和一些常用软件,可以直接使用。自定义镜像则是用户...
    99+
    2023-10-27
    镜像 模式 建议
  • 云服务器配置选择什么模式的
    云服务器可以根据不同的用户需求,选择不同的模式。以下是一些常见的云服务器模式: 按需计算模式(On Demand Computing):用户可以在不需要资源的情况下使用云服务器,云服务器将计算能力分配给用户,而不需要用户支付任何费用。这...
    99+
    2023-10-26
    服务器配置 模式
  • C++ 并发编程模式的使用和选择
    c++++ 具备多种并发编程模式,包括线程、互斥体、条件变量、原子操作和异步处理。选择合适的模式取决于应用程序需求,例如同步数据访问、条件等待、原子操作和提升响应速度。通过了解模式用途和...
    99+
    2024-05-14
    c++ 并发编程 数据访问
  • 如何选择最合适的 PHP 设计模式
    选择最合适的 php 设计模式分为以下 5 个步骤:识别问题研究设计模式理解模式应用模式实战案例 如何选择最合适的 PHP 设计模式 设计模式是经过验证的、可重复使用的解决方案,用于解...
    99+
    2024-05-07
    php 设计模式
  • 怎么选择阿里云代理模式
    安全性和稳定性 选择阿里云代理模式,需要考虑安全性和稳定性。选择阿里云代理,需要确保云服务提供商提供的云服务是经过安全认证的,可以满足企业或个人的安全需求。此外,还需要关注云服务提供商的稳定性,包括服务的可靠性、性能、维护等方面,以确...
    99+
    2023-10-27
    阿里 模式
  • C++ 函数模板详解:跨平台编程的理想选择
    函数模板允许创建跨不同数据类型的通用函数代码,使其成为跨平台编程的理想选择。它使用模板参数指定函数操作的数据类型,并根据使用的特定数据类型实例化函数。例如,计算最大值的模板函数可用于整数...
    99+
    2024-04-27
    c++ 函数模板
  • JQuery选择器用法详解
    目录一、基本选择器二、层次选择器三、表单选择器四、属性选择器一、基本选择器 id选择器元素名称选择器类选择器选择所有元素组合选择器 <html> <head>...
    99+
    2024-04-02
  • Python中的文件读写模式有哪些选择?
    Python是一种功能强大的编程语言,提供了多种文件读写模式以满足不同的需求。本文将介绍Python中常用的文件读写模式,并给出相应的代码示例。读模式('r')读模式是最常用的文件读写模式,用于读取已存在的文件。在读模式下,文件指针位于文件...
    99+
    2023-10-22
    文件读写模式选择
  • 亚马逊的云服务器选择什么模式
    1. 亚马逊云服务器的模式 亚马逊云服务器(Amazon EC2)是一种基于云计算的虚拟服务器,它提供了多种不同的模式供用户选择。这些模式包括: 1.1. 按需模式 按需模式是最灵活的模式,用户只需按照实际使用的时间和资源量付费。这种模式...
    99+
    2023-10-27
    亚马逊 模式 服务器
  • 设计模式——桥接模式详解
    🚀桥接模式(抽象与实现分离) 1.1⭐桥接模式的定义 维基百科:桥接模式是软件设计模式中最复杂的模式之一,它把事物对象和其具体行为、具体特征分离开来,使它们可以各自独立的变化。 百度百...
    99+
    2023-10-11
    设计模式 桥接模式 java
  • 数码相机驱动模式怎么选择
    数码相机驱动模式选择方法是:DRIVE是驱动模式选择按钮。注视肩屏,按DRIVE按钮,转动主拨盘,可在单拍、高速连续拍摄、低速连续拍摄、10秒延时自拍/遥控和2秒延时自拍/遥控间切换。专业的相机都是有手动档的,但是一般不了解原理的人很难操作...
    99+
    2023-07-10
  • 云服务器配置选择什么模式
    云服务器可以根据不同的用户需求,选择不同的模式。以下是一些常见的云服务器模式: 公共云:通常被用作个人或企业存储数据、运行应用程序和其他工具的公共云。这种云计算的特点是可用性高、成本低,但可能不提供高可用性,并且可能需要管理和维护基础架...
    99+
    2023-10-26
    服务器配置 模式
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作