すべてのコンポーネントからのマウスイベントのキャプチャ
-
03-07-2019 - |
質問
WinForm C#アプリケーションのMouseEventsに問題があります。
アプリケーションで all マウスクリックを取得したいが、Windowsマウスフックを使用せず、すべての子コンポーネントにリスナーを配置したくない。
Flashでは、リスナーをステージに配置して、ムービーのすべてのMouseEventを取得できます。
C#にはそのようなことがありますか?グローバルなMouseListener?
編集:
Application.AddMessageFilterを使用してIMessageFilterからこのクラスを作成します。
public class GlobalMouseHandler : IMessageFilter{
private const int WM_LBUTTONDOWN = 0x201;
public bool PreFilterMessage(ref Message m){
if (m.Msg == WM_LBUTTONDOWN) {
// Do stuffs
}
return false;
}
}
さらに、グローバルクリックをリッスンする必要があるコントロールに次のコードを配置します:
GlobalMouseHandler globalClick = new GlobalMouseHandler();
Application.AddMessageFilter(globalClick);
解決
これを行う簡単な方法の1つは、 Application.AddMessageFilter
を呼び出して、 IMessageFilter
インターフェイスを実装するクラスを記述することにより、メッセージループフィルターを追加することです。
IMessageFilter.PreFilterMessage
を介して、クラスはアプリケーションのメッセージループを通過する入力メッセージを表示します。 PreFilterMessage
は、これらのメッセージを宛先の特定のコントロールに渡すかどうかも決定します。
このアプローチがもたらす複雑さの1つは、 PreFilterMessage
メソッドに渡されるMessage構造体を介してWindowsメッセージを処理する必要があることです。これは、従来の MouseDown
、 WM \ _LBUTTONDOWN、WM \ _MOUSEMOVE
、 WM \ _LBUTTONUP
などのWin32ドキュメントを参照することを意味します。 > MouseMove および MouseUp
イベント。
他のヒント
サンプルクラス
class CaptureEvents : IMessageFilter
{
#region IMessageFilter Members
public delegate void Callback(int message);
public event Callback MessageReceived;
IntPtr ownerWindow;
Hashtable interestedMessages = null;
CaptureEvents(IntPtr handle, int[] messages)
{
ownerWindow = handle;
for(int c = 0; c < messages.Length ; c++)
{
interestedMessages[messages[c]] = 0;
}
}
public bool PreFilterMessage(ref Message m)
{
if (m.HWnd == ownerWindow && interestedMessages.ContainsKey(m.Msg))
{
MessageReceived(m.Msg);
}
return true;
}
#endregion
}
この記事をご覧ください。すべての制御イベントを再帰的にフックし、ブロードキャストします。 WndProcをオーバーライドすることもできます。フォームの。
Form.PreProcessMessageまたはForm.WndProcをオーバーライドしてメッセージを処理したくない場合は、Formをサブクラス化して、イベントハンドラーをフォーム上のさまざまなコントロールからのすべてのMouseClickイベントにフックできます。
編集:フォーム上のコントロールの子コントロールを再帰するのを忘れました。
public class MousePreviewForm : Form
{
protected override void OnClosed(EventArgs e)
{
UnhookControl(this as Control);
base.OnClosed(e);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
HookControl(this as Control);
}
private void HookControl(Control controlToHook)
{
controlToHook.MouseClick += AllControlsMouseClick;
foreach (Control ctl in controlToHook.Controls)
{
HookControl(ctl);
}
}
private void UnhookControl(Control controlToUnhook)
{
controlToUnhook.MouseClick -= AllControlsMouseClick;
foreach (Control ctl in controlToUnhook.Controls)
{
UnhookControl(ctl);
}
}
void AllControlsMouseClick(object sender, MouseEventArgs e)
{
//do clever stuff here...
throw new NotImplementedException();
}
}
フォームは、System.Windows.Forms.Formではなく、MousePreviewFormから派生する必要があります。