【发布时间】:2016-04-15 15:13:27
【问题描述】:
WM_MOUSEWHEEL 消息被发送到具有焦点的控件。我的应用程序有一个复杂的控件层次结构,其中包含其他控件的控件,其中一些是不可见的或重叠的。我希望鼠标滚轮滚动特定的ScrollableControl。
This question 有一个IMessageFilter 实现的答案,它捕获WM_MOUSEWHEEL 消息。这很好用,我看到消息被捕获。我尝试通过更改VerticalScroll.Value 的值来操作ScrollableControl 的VerticalScroll 属性来滚动其内容。不幸的是,有一些不良副作用,例如滚动条中的鼠标拇指与 ScrollableControl 的内容不同步。这可能是因为这项工作是在消息泵中完成的,而不是在事件处理程序中。
This post 描述了一种将 WM_MOUSEWHEEL 消息重新发布到另一个窗口的技术。我想实现一个IMessageFilter 来捕获WM_MOUSEWHEEL 消息,并将它们转发给指定的收件人。
我创建了以下IMessageFilter 来尝试执行此操作。我可以看到转发的消息被我的过滤器捕获,我从过滤器返回false 以告诉控件处理该消息。目标控件没有收到OnMouseWheel 事件。
是否可以修改此过滤器以允许使用重定向消息滚动我的targetControl?
public static class MouseWheelMessageRedirector
{
public static void Add(Control rootControl, ScrollableControl targetControl)
{
var filter = new MouseWheelMessageFilter(rootControl, targetControl);
Application.AddMessageFilter(filter);
rootControl.Disposed += (sender, args) => Application.RemoveMessageFilter(filter);
targetControl.MouseWheel += (sender, args) =>
{
// ... this code never executes
System.Diagnostics.Trace.WriteLine("WHEEL ON TARGET");
};
}
private class MouseWheelMessageFilter : IMessageFilter
{
const int WM_MOUSEWHEEL = 0x020A;
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
public MouseWheelMessageFilter(Control rootControl, ScrollableControl targetControl)
{
_rootControl = rootControl;
_targetControl = targetControl;
_targetWindowHandle = _targetControl.Handle;
}
public bool PreFilterMessage(ref Message m)
{
if (m.Msg != WM_MOUSEWHEEL)
return false;
if (m.HWnd == _targetWindowHandle)
return false;
// ... get the control that the mouse is over
// ... determine if this is a control that we want to handle the message for
// ... (omitted)
PostMessage(_targetWindowHandle, m.Msg, m.WParam, m.LParam);
return true;
}
private Control _rootControl;
private ScrollableControl _targetControl;
private IntPtr _targetWindowHandle;
}
}
【问题讨论】:
标签: c# winforms imessagefilter