【发布时间】:2016-10-10 03:45:05
【问题描述】:
如下自定义控件
public class DummyControl : FrameworkElement
{
private Visual visual;
protected override Visual GetVisualChild(int index)
{
return visual;
}
protected override int VisualChildrenCount { get; } = 1;
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
var pt = hitTestParameters.HitPoint;
return new PointHitTestResult(visual, pt);
}
public DummyControl()
{
var dv = new DrawingVisual();
using (var ctx = dv.RenderOpen())
{
var penTransparent = new Pen(Brushes.Transparent, 0);
ctx.DrawRectangle(Brushes.Green, penTransparent, new Rect(0, 0, 1000, 1000));
ctx.DrawLine(new Pen(Brushes.Red, 3), new Point(0, 500), new Point(1000, 500));
ctx.DrawLine(new Pen(Brushes.Red, 3), new Point(500, 0), new Point(500, 1000));
}
var m = new Matrix();
m.Scale(0.5, 0.5);
RenderTransform = new MatrixTransform(m);
//Does work; but only the left top quater enters hit test
//var hv = new HostVisual();
//var vt = new VisualTarget(hv);
//vt.RootVisual = dv;
//visual = hv;
//Never enters hit test
visual = dv;
}
}
xaml
<Window x:Class="MyNamespace.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyNamespace"
mc:Ignorable="d">
<Border Width="500" Height="500">
<local:DummyControl />
</Border>
</Window>
显示一个绿色区域,其中两条红色坐标线穿过中心。但它的命中测试行为对我来说是无法理解的。
我在方法
HitTestCore中设置了一个断点,但它从未命中。
1234563
如何解释上述内容以及如何使其按预期工作(进入全范围命中测试)?
(最初,我只是想在自定义控件上处理鼠标事件。一些现有的解决方案指向我重写 HitTestCore 方法。因此,如果您能提供任何可以让我处理鼠标事件的想法,我不会必须使HitTestCore 方法工作。)
更新
如果我决定使用DrawingVisual,Clemen 的回答很好。但是,当我使用HostVisual 和VisualTarget 时,如果不覆盖HitTestCore,它就无法工作,即使我这样做了,仍然只有左上角会接收鼠标事件。
原始问题还包括解释。此外,HostVisual 的使用允许我在另一个线程中运行渲染(在我的实际情况下很耗时)。
(让我使用上面的HostVisual 突出显示代码)
//Does work; but only the left top quater enters hit test
//var hv = new HostVisual();
//var vt = new VisualTarget(hv);
//vt.RootVisual = dv;
//visual = hv;
有什么想法吗?
更新 #2
克莱门的新答案仍然不符合我的目的。是的,所有的视觉区域都接受了命中测试。但是,我想要的是拥有完整的视口来接收命中测试。在他的例子中,当他将整个视觉缩放到视觉区域时,这是空白区域。
【问题讨论】: