可视化命中测试

在可视化容器里通常需要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);
        }
    }
}
相关推荐
雨中飘荡的记忆2 小时前
ElasticJob分布式调度从入门到实战
java·后端
掘金安东尼3 小时前
让 JavaScript 更容易「善后」的新能力
前端·javascript·面试
掘金安东尼3 小时前
用 HTMX 为 React Data Grid 加速实时更新
前端·javascript·面试
灵感__idea5 小时前
Hello 算法:众里寻她千“百度”
前端·javascript·算法
yinuo5 小时前
轻松接入大语言模型API -04
前端
袋鼠云数栈UED团队6 小时前
基于 Lexical 实现变量输入编辑器
前端·javascript·架构
cipher6 小时前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
UrbanJazzerati6 小时前
非常友好的Vue 3 生命周期详解
前端·面试
AAA阿giao6 小时前
从零构建一个现代登录页:深入解析 Tailwind CSS + Vite + Lucide React 的完整技术栈
前端·css·react.js
兆子龙7 小时前
像 React Hook 一样「自动触发」:用 Git Hook 拦住忘删的测试代码与其它翻车现场
前端·架构