我将具有多个元素(按钮,文本框,...)的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);
答案 0 :(得分:0)
您可以通过PostMessage(..)win32方法将Windows消息(如WM_MOUSEMOVE)发送到WPF窗口的HWND。我相信这些消息将由WPF读取并执行,就像它来自用户一样。
答案 1 :(得分:0)
如果你真的很勇敢,可以试试my hack to get access to the WPF IDirect3DDevice9Ex。从那里你可以将swapshchain中的backbuffer复制到你的d3d场景。如果您使用的是9Ex(Vista D3D9),您可以利用共享资源(在设备和进程之间共享表面/纹理/等)功能来帮助提高性能。
您可能仍需要使用Windows消息进行交互性操作。