C# 如何将鼠标滚轮消息从一个窗口重定向到另一个窗口?
C# 如何将鼠标滚轮消息从一个窗口重定向到另一个窗口?,c#,winforms,imessagefilter,C#,Winforms,Imessagefilter,WM_鼠标滚轮消息通过焦点发送到控件。我的应用程序有一个复杂的控件层次结构,控件包含其他控件,其中一些控件不可见或重叠。我希望鼠标滚轮滚动特定的ScrollableControl 有一个带有捕获WM_鼠标滚轮消息的IMessageFilter实现的答案。这很有效,我看到消息被捕获。我试图通过更改VerticalScroll.value的值,操纵ScrollableControl的VerticalScroll属性来滚动其内容。不幸的是,有一些不良的副作用,如滚动条中的鼠标拇指与Scrollable
WM_鼠标滚轮
消息通过焦点发送到控件。我的应用程序有一个复杂的控件层次结构,控件包含其他控件,其中一些控件不可见或重叠。我希望鼠标滚轮滚动特定的ScrollableControl
有一个带有捕获WM_鼠标滚轮
消息的IMessageFilter
实现的答案。这很有效,我看到消息被捕获。我试图通过更改VerticalScroll.value
的值,操纵ScrollableControl的VerticalScroll
属性来滚动其内容。不幸的是,有一些不良的副作用,如滚动条中的鼠标拇指与ScrollableControl的内容不同步。这可能是因为这项工作是在消息泵内部完成的,而不是在事件处理程序中完成的
描述一种将WM_鼠标滚轮消息重新发布到另一个窗口的技术。我想实现一个IMessageFilter
,它捕获WM_mouseweel
消息,并将它们转发给指定的收件人
我创建了下面的IMessageFilter
,尝试这样做。我可以看到转发的消息被我的筛选器捕获,我从筛选器返回false
,告诉控件处理该消息。目标控件未接收到onmouseheel
事件
是否可以修改此筛选器以允许使用重定向消息滚动mytargetControl
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;
}
}
我只是做了同样的事。以下是我所做的:
public bool PreFilterMessage(ref Message m)
{
if ((WM)m.Msg == WM.MOUSEWHEEL)
{
// if mouse is over a certain component, prevent scrolling
if (comboBoxVendors.Bounds.Contains(PointToClient(Cursor.Position)))
{
// return true which says the message is already processed
return true;
}
// which direction did they scroll?
int delta = 0;
if ((long)m.WParam >= (long)Int32.MaxValue)
{
var wParam = new IntPtr((long)m.WParam << 32 >> 32);
delta = wParam.ToInt32() >> 16;
}
else
{
delta = m.WParam.ToInt32() >> 16;
}
delta = delta*-1;
var direction = delta > 0 ? 1 : 0;
// post message to the control I want scrolled (I am converting the vertical scroll to a horizontal, bu you could just re-send the same message to the control you wanted
PostMessage(splitContainerWorkArea.Panel2.Handle, Convert.ToInt32(WM.HSCROLL), (IntPtr) direction, IntPtr.Zero);
// return true to say that I handled the message
return true;
}
// message was something other than scroll, so ignore it
return false;
}
我只是做了同样的事。以下是我所做的:
public bool PreFilterMessage(ref Message m)
{
if ((WM)m.Msg == WM.MOUSEWHEEL)
{
// if mouse is over a certain component, prevent scrolling
if (comboBoxVendors.Bounds.Contains(PointToClient(Cursor.Position)))
{
// return true which says the message is already processed
return true;
}
// which direction did they scroll?
int delta = 0;
if ((long)m.WParam >= (long)Int32.MaxValue)
{
var wParam = new IntPtr((long)m.WParam << 32 >> 32);
delta = wParam.ToInt32() >> 16;
}
else
{
delta = m.WParam.ToInt32() >> 16;
}
delta = delta*-1;
var direction = delta > 0 ? 1 : 0;
// post message to the control I want scrolled (I am converting the vertical scroll to a horizontal, bu you could just re-send the same message to the control you wanted
PostMessage(splitContainerWorkArea.Panel2.Handle, Convert.ToInt32(WM.HSCROLL), (IntPtr) direction, IntPtr.Zero);
// return true to say that I handled the message
return true;
}
// message was something other than scroll, so ignore it
return false;
}