【问题标题】:Improve hit testing in the visual layer in WPF改进 WPF 可视层中的命中测试
【发布时间】:2023-03-27 22:45:01
【问题描述】:

我在可视层中为Hit Testing 使用下面的代码。当我单击Drawing 视觉中绘制的线条时,我想获得点击。但由于线条很窄,我没有得到好的结果。

我想到的一个解决方案是在单击时增加鼠标覆盖的区域。这样,即使我在离线稍远的地方单击,我也会确保鼠标击中线。

我怎样才能做到这一点?或者您还有什么建议可以改善这种情况?

var x = MousePos.RightDown.X;
var y = MousePos.RightDown.Y;

var drawing = MyCanvas.GetRebarsVisual();

var pt = new Point(x,y);

var result = VisualTreeHelper.HitTest(drawing, pt);

if (result != null)
{
    MessageBox.Show("You clicked on the line!");
}

【问题讨论】:

  • 使用VisualTreeHelper.HitTest 可以指定HitTestParameters,使用以pt 为中心但大于GeometryHitTestParameters 传递的一个点:VisualTreeHelper.HitTest(drawing, null, null, new GeometryHitTestParameters(...))
  • @AdrianoRepetti 谢谢,我只是在探索这个选项。你能帮我写一篇文章或例子吗?
  • 在评论中添加,将... 替换为new RectangleGeometry(new Rect(x - 2, y - 2, 4, 4))。嗯……举个例子。矩形是最简单的一种,但特别是如果您打算将应用程序与触摸屏一起使用,圆形将更好地代表更大的命中测试区域。
  • @AdrianoRepetti 非常感谢阿德里亚诺,我到了那里,但我的问题是我应该在哪里分配 VisualTreeHelper...,正如您在我的示例中看到的那样,我将其分配给结果.我对此完全陌生。

标签: c# .net wpf hittest


【解决方案1】:

使用VisualTreeHelper.HitTest() 重载函数,您可以在其中指定HitTestParameters:使用以pt(但大于一个点)为中心的矩形几何图形,并通过GeometryHitTestParameters

var hitRect = new Rect(x - 2, y - 2, 4, 4);
VisualTreeHelper.HitTest(drawing, null, null,
    new GeometryHitTestParameters(new RectangleGeometry(hitRect)));

请注意,我们在此示例中使用了矩形几何形状,但更好的近似值(尤其是对于触摸屏)是圆形 (EllipseGeometry)。

现在您知道要调用什么,但您需要一个结果,该重载没有返回值,而是使用一个回调函数,您可以在其中累积多个命中(根据更复杂的规则选择一个)。在我们的示例中,我们不需要它,所以我们只是在第一次命中时停止:

bool result = false;
var hitRect = new Rect(x - 2, y - 2, 4, 4);
VisualTreeHelper.HitTest(drawing, null,
    htr => { result = true; return  HitTestResultBehavior.Stop; },
    new GeometryHitTestParameters(new RectangleGeometry(hitRect)));

请注意,您甚至可以直接执行代码:

    htr => {
        MessageBox.Show("You clicked on the line!");
        return  HitTestResultBehavior.Stop;
    },

如果您经常使用它,您可以为此编写一个更通用的方法(例如,使用矩形大小的可选参数)。

如果您只是不想知道是否有命中(但您也想知道哪个对象),那么您可以使用第二个回调函数(HitTestResultCallback),它的参数(称为@987654336 @ 在我前面的例子中)是一个派生自 HitTestResult 的类,甚至在基类中也有一个名为 VisualHit 的属性,它是你正在寻找的可视对象(作为通用 DependencyObject 那么你可能需要强制转换) .

【讨论】:

  • 代码运行良好,非常感谢。我猜只有found = true 需要更改为result = true。非常感谢您的帮助,我在 MSDN 中进行了很多搜索,但找不到完整的工作示例。你能指导我举一些例子吗?
  • 你是对的,已修复! IMO MSDN 有关该方法的示例非常好(即使很短)。首先看看thisthis
  • 感谢阿德里亚诺,这些文章帮助我更好地理解了答案。
  • 你已经帮了我很多了。还有一个问题,如果需要,请告诉我,我将把它作为一个单独的问题发布。在倾向于 HitTest 之前,我是按照自己的方式做的。我的意思是我正在手动搜索行的定义并搜索我的指针所在的特定行。这样我就可以改变它的颜色和类似的东西。现在我正在使用 HitTesting 如何获得我所指向的确切线。我怎样才能获得参考或类似的东西,以便我可以对其进行更改。
  • 是的,你可以在回调函数中做到这一点。我在 lambda 中调用 htr 的参数(好吧,我没有太多幻想)是 HitTestResult(它的派生类之一)。即使在基本抽象类中,也有一个属性VisualHit 是匹配的DependencyObject
猜你喜欢
  • 1970-01-01
  • 2023-03-10
  • 2015-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多