1

我正在将具有多个元素(按钮、文本框等)的 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);
4

2 回答 2

0

You might be able to send windows messages (like WM_MOUSEMOVE) to the WPF window's HWND, via the PostMessage(..) win32 method. I believe these messages would be read by WPF and executed as if it came from a user.

于 2009-12-18T08:13:36.943 回答
0

如果您真的很勇敢,可以尝试我的 hack 来访问 WPF IDirect3DDevice9Ex。从那里您可以将交换链中的后台缓冲区复制到您的 d3d 场景中。如果您使用的是 9Ex (Vista D3D9),您可以利用共享资源(在设备和进程之间共享表面/纹理/等)功能来帮助提高性能。

您可能仍然需要对 Windows 消息进行一些技巧以实现交互性。

于 2009-12-19T10:57:15.883 回答