WinForm C#アプリケーションでMouseEventsに問題があります。
アプリケーションでallマウスクリックを取得したいのですが、すべての子コンポーネントにリスナーを配置し、Windowsマウスフックを使用したくありません。
Flashでは、リスナーをステージに配置して、映画のすべてのMouseEventを取得できます。
C#にそのようなものはありますか?グローバルなMouseListener?
編集:
このクラスはIMessageFilterから作成し、Application.AddMessageFilterを使用しました。
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
、MouseMove
およびMouseUp
イベントではなく、WM\_LBUTTONDOWN, WM\_MOUSEMOVE
、WM\_LBUTTONUP
などに関するWin32ドキュメントを参照することを意味します。
サンプルクラス
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から派生する必要があります。