WPF学习笔记二 WPF命中测试

摘要:
命中测试筛选器回调函数的返回值决定可视对象枚举应执行的操作类型。这意味着命中测试结果回调函数不会在其枚举中看到这些对象。Continue对当前Visual及其后代执行命中测试。从名称中还可以看出,PointHitTestParameters主要用于点测试,而GeometryHitTestParameter可以用于区域中的命中测试。有关此类型的详细信息,请查询MSDN。
概述: 

WPF中的Canvas是常用的一个绘图控件,可以方便地在Canvas中添加我们需要处理的各种元素如:图片、文字等。但Canvas中元素增加到一定数量,并且有重合的时候,我们如何通过在Canvas中点击鼠标,获得我们想要的元素,然后再对该元素做出相应的控制?

命中测试,可以很好地解决这个问题

本文目的: 

使用命中测试,选取Canvas中相应Element。

正文: 

可视化树如何影响命中测试

可视化树中的起始点确定在对象的命中测试枚举过程中返回哪些对象。如果有多个要执行命中测试的对象,则可视化树中用作起始点的可视化对象必须是所有相关对象的公共上级。例如,如果您希望对以下关系图中的按钮元素和绘图可视化对象执行命中测试,则必须将可视化树中的起始点设置为两者的公共上级。在本例中,画布元素是按钮元素和绘图可视化对象的公共上级。

可视化树层次结构的关系图

image

即要在命中测试的结果中,包含Button及Drawing Visual,就必须在他们的公共上级Canvas中做命中测试。

示例程序

如下图所示:

image

Canvas中放置了底层放置了一张图片,顶层放置了一个文本框,我们想实现点击文本框区域时,命中测试的返回结果为下层的Image,先贴上代码,然后再解释。

private void canvasMain_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            GetCurrentElement(e.GetPosition(canvasMain));
        }

        private void GetCurrentElement(Point point)
        {
            PointHitTestParameters parameters = new PointHitTestParameters(point);
            VisualTreeHelper.HitTest(canvasMain, HitTestFilter, HitTestCallback, parameters);
        }

        private HitTestResultBehavior HitTestCallback(HitTestResult result)
        {
            Image image = result.VisualHit as Image;
            if (image != null) {
                _currentElement = image;
                return HitTestResultBehavior.Stop;
            } else
                return HitTestResultBehavior.Continue;
        }

        private HitTestFilterBehavior HitTestFilter(DependencyObject o)
        {
            Type type = o.GetType();
            switch (type.Name) {
                case "Canvas":
                    return HitTestFilterBehavior.ContinueSkipSelf;
                default:
                    return HitTestFilterBehavior.Continue;
            }
        }

其中VisualTreeHelper.HitTest方法是最主要的方法,其有三种重载形式,我们使用的是第二种重载形式,参数及其含义如下:

参数名称

类型

说明

reference

System.Windows.Media.Visual

要进行命中测试的 Visual

filterCallback

System.Windows.Media.HitTestFilterCallback

表示命中测试筛选回调值的方法

resultCallback

System.Windows.Media.HitTestResultCallback

表示命中测试结果回调值的方法

hitTestParameters

System.Windows.Media.HitTestParameters

要进行命中测试的参数值

1. reference

这个参数不用多说,就是我们要进行命中测试元素的公共上级,即他们在WPF树结构的上级,在这里为“canvasMain”;

2. filterCallback

使用命中测试筛选回调函数可以枚举呈现内容包含指定坐标的所有可视化对象。但是,您可能要忽略不希望在命中测试结果回调函数中处理的可视化树的某些分支。命中测试筛选回调函数的返回值确定可视化对象的枚举应执行的操作类型。例如,如果返回值 ContinueSkipSelfAndChildren,则可从命中测试结果枚举中移除当前可视化对象及其子对象。 这意味着命中测试结果回调函数在其枚举中将看不到这些对象。修剪可视化对象树会减少命中测试结果枚举过程中的处理量。其效果如下所示:

image

示例代码中我们并不想对Canvas进行命中测试,所以我们就判断如果枚举的命中测试结果为Canvas,则返回HitTestFilterBehavior.ContinueSkipSelf,这样将忽略它,而对其子对象进行命中测试。

下面是HitTestFilterBehavior的成员列表,我们可以根据需要,返回不用的值,以筛选命中测试结果。

成员名称

说明

ContinueSkipChildren

针对当前的 Visual(但不包括其子代)进行命中测试。

ContinueSkipSelfAndChildren

不要针对当前的 Visual 或其子代进行命中测试。

ContinueSkipSelf

不要针对当前的 Visual 进行命中测试,但要针对其子代进行命中测试。

Continue

针对当前的 Visual 及其子代进行命中测试。

Stop

在当前 Visual 处停止命中测试。

3. resultCallback

表示命中测试结果回调值的方法。result.VisualHit即为本次命中测试的结果,可以根据其类型判断其是否符合我们的测试要求,如果不符合则返回HitTestResultBehavior.Continue,继续枚举命中测试的下一个结果,如果符合要求则可以使用变量来接受这个结果,然后直接调用HitTestResultBehavior.Stop来结束整个命中测试。

4. hitTestParameters

定义命中测试的参数。从此公共基类派生出来的可用于实际命中测试的类包括 PointHitTestParameters 和 GeometryHitTestParameters。根据名称亦可以看出PointHitTestParameters主要用于点测试,而GeometryHitTestParameters则可以用于区域内的命中测试,该类型的详细信息请查询MSDN。

PointHitTestParameters的初始化也很简单,只需传入我们需要进行命中测试的点(Point)即可。

OK,主要的方法及其含义都解释完毕,想必大家都已能看明白示例代码,对命中测试也有了一个初步的了解。实际情况中可以根据情况,灵活运用filterCallback和resultCallback这两个回调函数,做到复杂的命中测试。

注意事项:

1. WPF大多控件都有IsHitTestVisible 属性,其可获取或设置一个值,该值声明某个 UIElement 派生对象是否可以作为其呈现内容某部分的命中测试结果返回。 这样,您便可以选择性地更改可视化树,以确定命中测试中涉及哪些可视化对象。

2. 在命中测试结果枚举过程中,不应执行修改可视化树的任何操作。在遍历可视化树的过程中,在可视化树中添加或移除对象会导致不可预知的行为。您可以在 HitTest 方法返回之后安全地修改可视化树。 您可能想要提供一个数据结构(例如 ArrayList),以便在命中测试结果枚举期间存储值。

3. 命中的可视化对象按 Z 顺序进行枚举。Z 顺序中位于最顶层的可视化对象最先进行枚举。所有其他可视化对象按递减的 Z 顺序级别进行枚举。此枚举顺序对应于可视化对象的呈现顺序。

(部分内容摘自MSDN)

免责声明:文章转载自《WPF学习笔记二 WPF命中测试》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇LaTeX技巧22:LaTeX文档中的参考文献初级在沙盒中创建文件方法1下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【STM32H7】第21章 ThreadX定时器组

论坛原始地址(持续更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99514 第21章 ThreadX定时器组 本章节为大家讲解ThreadX支持的定时器组,或者叫软件定时器,又或者叫用户定时器均可。软件定时器的功能比较简单,也容易掌握。被称为定时器组是因为用户可以创建多个定时器,创建的个...

springboot mybatis自定义枚举enum转换

原文链接:https://blog.csdn.net/u014527058/article/details/62883573 一、概述 在利用Spring进行Web后台开发时,经常会遇到枚举类型的绑定问题。一般情况下,如果Spring接收到的参数值为字符串类型,Spring会根据枚举的值与传入的字符串进行对应。假设有如下枚举 清单1:枚举定义 public...

前端调用api接口方法总结

我用得最多的大概就是jquery中的ajax了吧,就从ajax总结起走: 一、ajax: 参数解释:(主要就用到url、type、data、dataType、success、error等,其他的看需求而定) $.ajax({   url:" ", //请求的地址,类型为string type:" ", //请求方式,两种“get”或者“...

WPF控件

什么是控件 WPF中是数据驱动UI,数据是核心、是主动的;UI从属与数据并表达数据、是被动的。UI的功能是让用户观察和操作数据,为了让用户观察数据,我们需要用UI元素来显示数据;为了让用户操作数据,我们需要用UI元素响应用户的操作。WPF中把那些能够显示数据、响应用户操作的UI元素称为控件。 控件所显示的数据,我们称之为“数据内容”,控件在响应用户的操作后...

WPF 设置Frame中Page的DataContext

WPF窗体MainWindow中有 Frame控件,名为 MainFrame, MainFrame 通过ViewModel绑定Source属性来设置显示的Page页,其中的Page页需要与MainWindow 共用一个ViewModel对象做DataContext MainWindow.xaml <Border Margin="5" Backgrou...

android 自定义控件属性获取bitmap和drawable的绘制

1. 在定义一个属性的格式的时在attrs属性文件中定义如下,reference表示图片等引用类型,color就是颜色。中间用一个竖线分割开 2. 获取格式为reference|color类型的在xml中的数据为drawable文件 为了将这个drawable对象绘制到view上面,需要将drawable转换为bitmap对象,转换代码 pub...