以编程方式引发 WPF MouseLeftButtonDownEvent 事件

发布于 2024-08-24 06:34:42 字数 345 浏览 10 评论 0原文

我试图通过在视觉树上冒泡来引发 MouseLeftButtonDownEvent 使用以下代码。

var args = new MouseButtonEventArgs(Mouse.PrimaryDevice,0,MouseButton.Left);
args.RoutedEvent = UIElement.MouseLeftButtonDownEvent;
args.Source = this;
RaiseEvent(args);

由于某种原因,更高级别的组件没有接收到此冒泡事件。 我是否忽略了某些事情,或者是否无法引发此鼠标事件

I am trying to raise a MouseLeftButtonDownEvent by bubbling it up the Visual tree
with the following code.

var args = new MouseButtonEventArgs(Mouse.PrimaryDevice,0,MouseButton.Left);
args.RoutedEvent = UIElement.MouseLeftButtonDownEvent;
args.Source = this;
RaiseEvent(args);

For some reason the higher level components are not receiving this bubbled event.
Am I overlooking something or is it not possible to raise this Mouse event

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅浅淡淡 2024-08-31 06:34:42

你的问题是你正在引发一个不会冒泡的事件。

MouseLeftButtonDownEvent 定义为 RoutingStrategy.Direct,这意味着它仅路由到接收事件的控件。

您想改用 Mouse.MouseDownEvent 事件。 UIElement 和其他类在内部将其转换为 MouseLeftButtonDownEvent。确保将 e.ChangedButton 设置为 MouseButton.Left

RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left)
{
  RoutedEvent = Mouse.MouseDownEvent,
  Source = this,
});

Your problem is that you are raising an event that does not bubble.

MouseLeftButtonDownEvent is defined as RoutingStrategy.Direct, which means it is routed to only the control receiving the event.

You want to use Mouse.MouseDownEvent event instead. UIElement and other classes internally convert this into a MouseLeftButtonDownEvent. Make sure you set e.ChangedButton to MouseButton.Left:

RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left)
{
  RoutedEvent = Mouse.MouseDownEvent,
  Source = this,
});
望笑 2024-08-31 06:34:42

我的观点可能是错误的 - 但至少我不久前对 InputManager 进行了相当长的研究。

我的简历是:冒泡和隧道是由 InputManager 完成的。然而,调用 uielement.Raise() 只会直接传递事件(无论 Ray Burns 提到的 RoutingStrategy 是什么)。

但是(猜测)根据 RoutingStrategyInputManagerCompositionRootVisualTreeHlper.Hittest() 之间的可视化树中上下移动 -编辑视觉并提供隧道和冒泡事件。

有一种方法可以通过 InputManager 引发事件,但它不是官方的,需要反射(我从另一个 Stackoverflow 帖子中得到了它):

    void RaiseMouseInputReportEvent(Visual eventSource, int timestamp, int pointX, int pointY, int wheel)
    {
        Assembly targetAssembly = Assembly.GetAssembly(typeof(InputEventArgs));
        Type mouseInputReportType = targetAssembly.GetType("System.Windows.Input.RawMouseInputReport");

        Object mouseInputReport = mouseInputReportType.GetConstructors()[0].Invoke(new Object[] {
        InputMode.Foreground, timestamp, PresentationSource.FromVisual(eventSource),
        RawMouseActions.AbsoluteMove | RawMouseActions.Activate,
        pointX, pointY, wheel, IntPtr.Zero });

        mouseInputReportType.GetField("_isSynchronize", BindingFlags.NonPublic | BindingFlags.Instance)
            .SetValue(mouseInputReport, true);

        InputEventArgs inputReportEventArgs = (InputEventArgs)targetAssembly
            .GetType("System.Windows.Input.InputReportEventArgs")
            .GetConstructors()[0]
            .Invoke(new Object[] {
            Mouse.PrimaryDevice,
            mouseInputReport });

        inputReportEventArgs.RoutedEvent = (RoutedEvent)typeof(InputManager)
            .GetField("PreviewInputReportEvent", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
            .GetValue(null);

        bool handled = InputManager.Current.ProcessInput((InputEventArgs)inputReportEventArgs);
    }

I might be wrong in my opinion - but at least I looked some time ago for quite some length into InputManager.

My resume from that is: The bubbling and tunneling is done by InputManager. However calling uielement.Raise() will only ever deliver the event directly (regardless of the RoutingStrategy as Ray Burns mentioed).

But (guessing) depending on RoutingStrategy the InputManager goes up and down the visual tree between CompositionRoot and the VisualTreeHlper.Hittest()-ed Visual and delivers tunneling and bublling events.

There is a way to raise Events via the InputManager, but it is not official and needs reflection (I have it from another Stackoverflow post):

    void RaiseMouseInputReportEvent(Visual eventSource, int timestamp, int pointX, int pointY, int wheel)
    {
        Assembly targetAssembly = Assembly.GetAssembly(typeof(InputEventArgs));
        Type mouseInputReportType = targetAssembly.GetType("System.Windows.Input.RawMouseInputReport");

        Object mouseInputReport = mouseInputReportType.GetConstructors()[0].Invoke(new Object[] {
        InputMode.Foreground, timestamp, PresentationSource.FromVisual(eventSource),
        RawMouseActions.AbsoluteMove | RawMouseActions.Activate,
        pointX, pointY, wheel, IntPtr.Zero });

        mouseInputReportType.GetField("_isSynchronize", BindingFlags.NonPublic | BindingFlags.Instance)
            .SetValue(mouseInputReport, true);

        InputEventArgs inputReportEventArgs = (InputEventArgs)targetAssembly
            .GetType("System.Windows.Input.InputReportEventArgs")
            .GetConstructors()[0]
            .Invoke(new Object[] {
            Mouse.PrimaryDevice,
            mouseInputReport });

        inputReportEventArgs.RoutedEvent = (RoutedEvent)typeof(InputManager)
            .GetField("PreviewInputReportEvent", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
            .GetValue(null);

        bool handled = InputManager.Current.ProcessInput((InputEventArgs)inputReportEventArgs);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文