WPF - симулировать события мыши на сетке за пределами экрана - PullRequest
1 голос
/ 17 декабря 2009

Я рендерим сетку WPF с несколькими элементами (кнопками, текстовым полем, ...) в растровое изображение, которое затем используется в качестве текстуры для трехмерной поверхности в сцене Direct3D. Для взаимодействия с пользователем я создаю 3D-луч из положения курсора 2D-мыши в 3D-сцену, находя точку пересечения с поверхностью графического интерфейса. Итак, я знаю, где пользователь нажал на сетку WPF, но оттуда я застрял:

Как я могу имитировать события мыши на элементах WPF, когда они на самом деле не отображаются в открытом окне, а отображаются вне экрана?

Недавно я изучал UIAutomation и RaiseEvent, но они используются для отправки событий отдельным элементам, а не всему визуальному дереву. Обходить дерево вручную и искать элементы в позиции курсора было бы вариантом, но я не нашел способа сделать это точно. VisualTreeHelper.HitTest - хорошее начало, но вместо поиска TextBox он находит TextBoxView и вместо ListBox находит границу.

РЕДАКТИРОВАТЬ: возвращая HitTestResultBehavior. Продолжение в результате обратного вызова HitTest позволяет мне пройти через все элементы в данной точке. Теперь я могу отправлять события мыши всем этим элементам, но значения объекта 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);

Ответы [ 2 ]

0 голосов
/ 19 декабря 2009

Если вы чувствуете себя действительно смелым, вы можете попробовать мой взлом, чтобы получить доступ к WPF IDirect3DDevice9Ex . Оттуда вы можете скопировать backbuffer в swapshchain на вашу d3d сцену. Если вы используете 9Ex (Vista D3D9), вы можете воспользоваться функцией общих ресурсов (совместно использовать поверхности / текстуры / и т. Д. Между устройствами и процессами) для повышения производительности.

Возможно, вам все еще придется поработать с сообщениями Windows для интерактивности.

0 голосов
/ 18 декабря 2009

Возможно, вы сможете отправлять сообщения Windows (например, WM_MOUSEMOVE) в HWND окна WPF с помощью метода Win32 PostMessage (..). Я полагаю, что эти сообщения будут прочитаны WPF и выполнены так, как если бы они пришли от пользователя.

...