可视化命中测试

在可视化容器里通常需要DrawVisual对象画东西

如果需要知道是否选择了DrawVisual需要使用可视化树的命中测试

简单案例

cs 复制代码
如果点中了可视化对象
public DrawingVisual? GetVisual(Point point)
{
    HitTestResult result = VisualTreeHelper.HitTest(this, point);
    return result.VisualHit as DrawingVisual;
}

获取区域中的可视化对象

cs 复制代码
public List<DrawingVisual> GetVisuals(Geometry region)
{
    hits.Clear();

    HitTestResultCallback callback = new HitTestResultCallback(HitTestCallback);//回调
    GeometryHitTestParameters parameters = new GeometryHitTestParameters(region);
    
    //命中测试
    VisualTreeHelper.HitTest(this,null, callback, parameters);

    return hits;
}

/// <summary>
/// 回调方法。命中到的小方格添加到hits
/// </summary>
/// <param name="result">命中测试结果</param>
/// <returns></returns>
private HitTestResultBehavior HitTestCallback(HitTestResult result)
{
    GeometryHitTestResult geometryResult = (GeometryHitTestResult)result;
    DrawingVisual visual= result.VisualHit as DrawingVisual;
    if (visual != null && geometryResult.IntersectionDetail== IntersectionDetail.FullyInside)
    {
        hits.Add(visual);
        return HitTestResultBehavior.Stop;
    }
    return HitTestResultBehavior.Continue;
}

VisualTreeHelper.HitTest(this,null, callback, parameters);

这里主要讲筛选回调

cs 复制代码
//如果是Canvas跳过 
private HitTestFilterBehavior HitTestFilter(DependencyObject o)
        {
            Type type = o.GetType();
            switch (type.Name) {
                case "Canvas":
                    return HitTestFilterBehavior.ContinueSkipSelf;
                default:
                    return HitTestFilterBehavior.Continue;
            }
        }

重写默认命中测试

可以通过重写 HitTestCore 方法重写视觉对象的默认命中测试支持。 这意味着,在调用 HitTest 方法时,将调用 HitTestCore 的替代实现。 当命中测试落在视觉对象的边框内时,将调用重写的方法,即使坐标落在视觉对象呈现内容之外也是如此。

cs 复制代码
// Override default hit test support in visual object.
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
    // Perform actions based on hit test of bounding rectangle.
    // ...

    // Return results of base class hit testing,
    // which only returns hit on the geometry of visual objects.
    return base.HitTestCore(hitTestParameters);//使用默认的
    //return new PointHitTestResult(this, pt);
}

例子 自定义return new PointHitTestResult(this, pt);
public class MyCircleButton : Button
{
    protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
    {
        // 1. 获取命中点(相对当前控件)
        Point pt = hitTestParameters.HitPoint;
        // 2. 自定义命中判断:是否在圆形区域内(控件中心为圆心,半径为控件最小边长的一半)
        Point center = new Point(this.ActualWidth / 2, this.ActualHeight / 2);
        double radius = Math.Min(this.ActualWidth, this.ActualHeight) / 2;
        double distance = Math.Sqrt(Math.Pow(pt.X - center.X, 2) + Math.Pow(pt.Y - center.Y, 2));

        // 3. 满足自定义条件,强制返回命中结果;否则沿用默认逻辑(或返回null)
        if (distance <= radius)
        {
            // 强制指定当前圆形按钮为命中目标
            return new PointHitTestResult(this, pt);
        }
        else
        {
            // 不满足条件时,沿用默认逻辑(或返回null表示未命中)
            return base.HitTestCore(hitTestParameters);
        }
    }
}
相关推荐
小白鸽i8 分钟前
【LINUX】将源码驱动文件编译并生效
linux·运维·服务器
XiYang-DING14 分钟前
【Java SE】数据类型、变量、类型转换、运算符以及程序逻辑控制
java·开发语言
闻哥26 分钟前
Redis 避坑指南:从命令到主从的全链路踩坑实录
java·数据库·redis·缓存·面试·springboot
Jinkxs33 分钟前
基于 Java 的消息队列选型年度总结:RabbitMQ、RocketMQ、Kafka 实战对比
java·kafka·java-rocketmq·java-rabbitmq
做萤石二次开发的哈哈36 分钟前
萤石开放平台 音视频 | 产品概述
运维·服务器·萤石云·萤石·萤石开放平台
独自破碎E1 小时前
JDK版本的区别
java·开发语言
建群新人小猿1 小时前
陀螺匠企业助手—个人简历
android·大数据·开发语言·前端·数据库
悟空码字2 小时前
SpringBoot深度整合高德地图,构建高性能位置服务
java·springboot·高德地图·编程技术·后端开发
CHU7290352 小时前
在线教学课堂APP前端功能:搭建高效线上教学生态
前端·人工智能·小程序·php
千金裘换酒2 小时前
栈和队列定义及常用语法 LeetCode
java·开发语言