質問

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から派生する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top