Make the form implement IMessageFilter
and implement it as follows:
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == 0x20a)
{
// WM_MOUSEWHEEL, find the control at screen position m.LParam
Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
IntPtr hWnd = WindowFromPoint(pos);
if (hWnd != IntPtr.Zero && hWnd != m.HWnd)
{
var ctrl = Control.FromHandle(hWnd);
if (ctrl.IsDescendentOf(theParentPanel))
{
SendMessage(theParentPanel.Handle, m.Msg, m.WParam, m.LParam);
return true;
}
}
}
return false;
}
[DllImport("user32.dll")]
private static extern IntPtr WindowFromPoint(Point pt);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
The above code assumes that the name of the parent panel is theParentPanel
.
IsDescendentOf
is an extension method that checks whether a control is a descendent of the provided container control:
public static bool IsDescendentOf(this Control ctrl, Control parent)
{
while (true)
{
if (ctrl == null || ctrl.Parent == null)
return false;
if (ReferenceEquals(ctrl.Parent, parent))
return true;
ctrl = ctrl.Parent;
}
}
In the end register this message filter (i.e., the form itself) in the form's constructor:
private MyForm()
{
InitializeComponent();
if(!DesignMode) // VS Designer may have problems with this
Application.AddMessageFilter(this);
}
This solution is based on this forum thread.