Have you ever tried to scroll a control with the mouse wheel and something else started moving instead?
The reason for that is that Windows always sends the WM_MOUSEWHEEL message to the control that has the keyboard focus and not as one might assume to the control underneath the mouse cursor.
Windows doesn't provide a means to change this behavior, but there are tools and workarounds. If you have full control over a computer, you can install small programs like "KatMouse" or "WizMouse" to bring universal scroll support to all Windows apps.
If you develop software and don't have control over the deployment machines, you might want to add universal scroll directly into your app. I did this by implementing IMessageFilter in my main window, intercepting the WM_MOUSEWHEEL message and forward it to the control under the mouse cursor:
using System;
using System.Windows.Forms;
public class MainForm : System.Windows.Forms.IMessageFilter
{
// .....
public bool PreFilterMessage(ref Message msg)
{
if (msg.Msg == (int)Win32.Msgs.WM_MOUSEWHEEL || msg.Msg == (int)Win32.Msgs.WM_MOUSEHWHEEL)
{
// redirect WM_MOUSEWHEEL to the window under the mouse cursor
int x = (int)(((long)msg.LParam) & 0xFFFF);
int y = (int)(((long)msg.LParam) >> 16);
IntPtr handle = Win32.WindowFromPoint(new Point(x, y));
if (handle != msg.HWnd)
{
Win32.SendMessage(handle, (int)msg.Msg, msg.WParam, msg.LParam);
return true; // msg won't be processed
}
}
return false; // msg will be processed normally
}
}
public static class Win32
{
public enum Msgs
{
WM_MOUSEWHEEL = 0x020A,
WM_MOUSEHWHEEL = 0x020E,
}
[System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern int PostMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern IntPtr WindowFromPoint(System.Drawing.Point screenPoint);
}
Keine Kommentare:
Kommentar veröffentlichen