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;
}
}