WPF使用VisualTreeHelper进行复杂命中测试

WPF使用VisualTreeHelper进行复杂命中测试

一、简介

接上篇的简单命中测试,添加VisualTreeHelper复杂命中测试。

二、代码案例

我在一个画板上在不同的位置放了3个圆形。给他们放置了不同的位置和填充不同的颜色,我们通过命中测试判断如果鼠标在圆上抬起了,我们读取当前圆的填充颜色。 

XAML:

<Grid  MouseLeftButtonUp="Grid_MouseLeftButtonUp"   MouseRightButtonUp="Grid_MouseRightButtonUp">
        <Canvas>
            <Ellipse Canvas.Left="30" Canvas.Top="200"  Width="130" Height="130" Fill="Blue"/>
            <Ellipse  Opacity="0.6" Canvas.Left="70" Canvas.Top="50"  Width="130" Height="130" Fill="Violet"/>
            <Ellipse  Opacity="0.6"   Canvas.Left="150" Canvas.Top="50"  Width="130" Height="130" Fill="Orange"/>
            <Ellipse  Opacity="0.6"  Canvas.Left="110" Canvas.Top="0"  Width="130" Height="130" Fill="Red"/>
            <Ellipse  Canvas.Left="220" Canvas.Top="100"  Width="130" Height="130" Fill="Yellow"/>
            <TextBlock  Canvas.Left="0" Canvas.Top="0" Text="抬起鼠标左右键,开始对鼠标所在点进行命中测试" />
        </Canvas>
    </Grid>

后台逻辑:

 #region 左键简单命中测试
        private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            //最上层颜色
            var ellipse = GetVisual(e.GetPosition(this));
            MessageBox.Show(ellipse?.Fill?.ToString());
        }
        private Ellipse GetVisual(Point point)
        {
            HitTestResult hitResult = VisualTreeHelper.HitTest(this, point);
            var ellipse = hitResult.VisualHit as Ellipse;
            return ellipse;
        }
        #endregion

        #region 右键复杂命中测试 
        private void Grid_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            Point pt = e.GetPosition((UIElement)sender);
            //我们定义一个10*10大小的几何
            EllipseGeometry expandedHitTestArea = new EllipseGeometry(pt, 10.0, 10.0);
            var ellipses = GetVisual(expandedHitTestArea);
            StringBuilder stringBuilder = new StringBuilder();
            foreach (var item in ellipses)
            {
                //右击弹出所有层叠的颜色
                stringBuilder.Append(item.Fill.ToString() + ",");
            }
            MessageBox.Show(stringBuilder.ToString());
        }

        private HitTestResultBehavior HitTestCallback(HitTestResult result)
        {
            GeometryHitTestResult geometryResult = (GeometryHitTestResult)result;
            Ellipse visual = result.VisualHit as Ellipse;
            if (visual != null)
            {
                hits.Add(visual);
            }
            return HitTestResultBehavior.Continue;
        }
        List<Ellipse> hits = new List<Ellipse>();
        private List<Ellipse> GetVisual(Geometry region)
        {
            hits.Clear();
            GeometryHitTestParameters parameters = new GeometryHitTestParameters(region);
            HitTestResultCallback callback = new HitTestResultCallback(this.HitTestCallback);
            //第一个参数是我们要在什么容器内查找(我们现在是在整个window)。
            //第二个参数是筛选回调值的方法,我们目前不需要。
            //第三个参数是命中测试回调结果。
            //第四个参数是需要检测的区域。
            VisualTreeHelper.HitTest(this, null, callback, parameters);
            return hits;
        }
        #endregion

三、运行效果

如下图右键点击小星星处,弹出三种HTML颜色:

如下图左键点击小星星处,仅弹出一种HTML颜色:

posted @ 2021-06-29 15:13  码农阿亮  阅读(291)  评论(1编辑  收藏  举报