当托管在 WinForms 容器中时,WPF ScrollViewer 不会接收鼠标事件

发布于 2024-11-02 22:44:18 字数 321 浏览 1 评论 0原文

我们有一个 WinForms 应用程序,我们正在逐步将其转换为 WPF。此时,应用程序的主窗体是一个 Form (WinForms),其中包含 WPF 中内置的垂直侧边栏。侧边栏托管在 ElementHost 控件中。

侧边栏由包含其他控件的 ScrollViewer 组成。问题是,当焦点位于 WinForms 领域的某个位置并且我在 ScrollViewer 上使用鼠标滚轮时,它不会滚动。

这与 WPF/WinForms 集成有关,因为在 100% WPF 项目中,即使焦点位于另一个控件上,ScrollViewer 也会对鼠标滚轮做出反应。

解决这个问题的正确方法是什么?

We have a WinForms application that we are progressively converting to WPF. At this point the application's main form is a Form (WinForms) that contains a vertical sidebar built in WPF. The sidebar is hosted in an ElementHost control.

The sidebar is made of a ScrollViewer that contains other controls. The problem is that when the focus is somewhere in the WinForms aera and I use the mouse wheel over the ScrollViewer, it does not scroll.

This is related to the WPF/WinForms integration because in a 100% WPF project, the ScrollViewer reacts to the mouse wheel even if the focus is on another control.

What is the correct way to fix this?

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

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

发布评论

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

评论(2

夜夜流光相皎洁 2024-11-09 22:44:18

考虑执行消息过滤器,当您收到 WM_MOUSEWHEEL 时,确定鼠标是否位于 WPF 控件上方。如果是这样,则将消息直接发送到您的元素窗口句柄。

像这样的事情:

System.Windows.Forms.Application.AddMessageFilter( new MouseWheelMessageFilter( YourElementInsideAnElementHost ) );

当你超出范围时不要忘记调用RemoveMessageFilter

public class MouseWheelMessageFilter : IMessageFilter
{
   private const int WM_MOUSEWHEEL = 0x020A;
   private FrameworkElement _element;

   [DllImport("user32.dll")]
   public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

   public MouseWheelMessageFilter(FrameworkElement element)
   {
       _element = element;
   }

   public bool PreFilterMessage(ref Message m)
   {
       if (m.Msg == WM_MOUSEWHEEL)
       {
           Rect rect = new Rect(0, 0, _element.ActualWidth, _element.ActualHeight);
           Point pt = Mouse.GetPosition(_element);

           if (rect.Contains(pt))
           {
               HwndSource hwndSource = (HwndSource)HwndSource.FromVisual(_element);
               SendMessage(hwndSource.Handle, m.Msg, m.WParam, m.LParam);
               return true;
           }
       }

       return false;
   }
}

consider doing a message filter and when you receive WM_MOUSEWHEEL, determine if the mouse is over your WPF control. If so then send the message directly to your Element window handle.

Something like this:

System.Windows.Forms.Application.AddMessageFilter( new MouseWheelMessageFilter( YourElementInsideAnElementHost ) );

Dont forget to call RemoveMessageFilter when you go out of scope

public class MouseWheelMessageFilter : IMessageFilter
{
   private const int WM_MOUSEWHEEL = 0x020A;
   private FrameworkElement _element;

   [DllImport("user32.dll")]
   public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

   public MouseWheelMessageFilter(FrameworkElement element)
   {
       _element = element;
   }

   public bool PreFilterMessage(ref Message m)
   {
       if (m.Msg == WM_MOUSEWHEEL)
       {
           Rect rect = new Rect(0, 0, _element.ActualWidth, _element.ActualHeight);
           Point pt = Mouse.GetPosition(_element);

           if (rect.Contains(pt))
           {
               HwndSource hwndSource = (HwndSource)HwndSource.FromVisual(_element);
               SendMessage(hwndSource.Handle, m.Msg, m.WParam, m.LParam);
               return true;
           }
       }

       return false;
   }
}
执手闯天涯 2024-11-09 22:44:18

尝试通过调用 elementHost.Select() 将焦点设置到 ElementHost
这使得 MouseWheel 事件对我有用。

Try setting the focus to the ElementHost by calling elementHost.Select()
This made the MouseWheel event work for me.

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