我正在将具有多个元素(按钮、文本框等)的 WPF 网格渲染为位图,然后将其用作 Direct3D 场景中 3D 表面的纹理。对于用户交互,我创建了一条从 2D 鼠标光标位置到 3D 场景的 3D 射线,找到与 gui 表面的交点。所以我知道用户在 WPF 网格上单击的位置,但从那里我被卡住了:
如何在 WPF 元素上模拟鼠标事件,而它们实际上并未显示在打开的窗口中而是呈现在屏幕外?
最近,我正在研究 UIAutomation 和 RaiseEvent 但它们用于将事件发送到单个元素,而不是整个可视化树。手动遍历树并在光标位置查找元素将是一种选择,但我还没有找到一种方法来准确地做到这一点。VisualTreeHelper.HitTest 是一个好的开始,但它没有找到 TextBox,而是找到了 TextBoxView,而不是 ListBox,它找到了 Border。
编辑:在 HitTest 的结果回调中返回 HitTestResultBehavior.Continue 让我可以遍历给定点的所有元素。我现在可以将鼠标事件发送到所有这些元素,但 MouseEventArgs 对象的值是真实鼠标的值。所以我必须创建一个显然是不可能的自定义 MouseDevice。
PointHitTestParameters p = new PointHitTestParameters(new Point(
((Vector2)hit).X * sourceElement.ActualWidth,
(1 - ((Vector2)hit).Y) * sourceElement.ActualHeight));
VisualTreeHelper.HitTest(sourceElement,
new HitTestFilterCallback(delegate(DependencyObject o)
{
return HitTestFilterBehavior.Continue;
}),
new HitTestResultCallback(delegate(HitTestResult r)
{
UIElement el = r.VisualHit as UIElement;
if (el != null)
{
MouseButtonEventArgs e = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left);
if (leftMouseDown) e.RoutedEvent = Mouse.MouseDownEvent;
else e.RoutedEvent = Mouse.MouseUpEvent;
el.RaiseEvent(e);
}
return HitTestResultBehavior.Continue;
}), p);