可视化命中测试

在可视化容器里通常需要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);
        }
    }
}
相关推荐
程序员黑豆7 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
To_OC8 小时前
踩了个 TS 的坑之后,我终于把 type 和 interface 掰明白了
前端·react.js·typescript
GreenTea8 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
风流 少年8 小时前
Spring AI 2.0:Memory
java·后端·spring
码匠许师傅8 小时前
【C++ 面试真题】聊聊 C++ 的移动语义与右值引用
java·c++·面试
浮生望8 小时前
前端API工程化:用 Mock 数据与 Axios 配置实现独立于后端的并行开发
前端
万少9 小时前
给 DeepSeek Harness 装个"应用商店":一条命令,595 个插件随你逛
前端·javascript·后端
小席是个热心肠9 小时前
AI相关的自我学习
java·人工智能·学习
波波0079 小时前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
Brown.alexis10 小时前
es6知识点1-自备使用
前端·ecmascript·es6