6

マウスカーソルが一連の座標(たとえば正方形)の間にある場合に発生する特定のフォームでのmouseclickイベントを処理しようとしています。

私は、空のフォームがあれば、単にmousemoveイベントに結び付けて、離れることができることを理解しています。しかし実際には、最大10の異なる重複するコントロールが存在する可能性があり、私のテストアプリでは、カーソルが実際のフォーム自体にある場合にのみmousemoveイベントが発生し、子コントロール上にある場合には発生しません。

設計時に子コントロールの数が不明な場合に、このイベントを処理する方法を知っている人はいますか?

簡単に使えるワンライナーはありますか?

4

5 に答える 5

8

これを試して:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        AddMouseMoveHandler(this);
    }

    private void AddMouseMoveHandler(Control c)
    {
        c.MouseMove += MouseMoveHandler;
        if(c.Controls.Count>0)
        {
            foreach (Control ct in c.Controls)
                AddMouseMoveHandler(ct);
        }
    }

    private void MouseMoveHandler(object sender, MouseEventArgs e)
    {
        lblXY.Text = string.Format("X: {0}, Y:{1}", e.X, e.Y);
    }
}
于 2009-11-12T03:36:36.133 に答える
7

この投稿がかなり古いことは知っていますが、最も簡単な方法は、フォームを実装することだと思いますIMessageFilter。コンストラクター (またはOnHandleCreated) で呼び出します

Application.AddMessageFilter(this);

の実装ですべてのウィンドウのメッセージをキャッチできますIMessageFilter.PreFilterMessage

WIN32 IsChild メソッドには P/Invoke を使用する必要があるでしょう。

[DllImport("user32.dll")]
public static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);

フォームのプロパティとともにHandle、正しいメッセージを処理していることを確認してください。

于 2012-08-21T03:52:58.700 に答える
0

コントロールのマウスオーバー イベント ハンドラを使用しないのはなぜですか。

于 2009-11-12T03:30:11.497 に答える
0

ここには少しバイナリの状況があります。「ワンライナー」はありません。私が見ることができる唯一の解決策は、イベントを実装しないコントロールを、実装する .NET コンテナーに入れることです。

いずれかのコントロールがクリックされると、通常の予想される動作は、フォームのアクティブ コントロールになることです (常に this.ActivceControl からアクセスできます)。

ただし、クリックしたコントロールがマウスをキャプチャする場合は特に、.NET はイベントの「バブリング」を実装していないため (WPF のように)、何かがイベントを発生させる必要があります。

シールされたオブジェクトの拡張動作に対処する通常の方法は、拡張メソッドを作成することです。Control の拡張機能を作成するのは非常に簡単ですが、この場合に役立つかどうかはわかりません。残念ながら、私は現在母国を離れており、Visual Studio をいじることができません。

フォーム上の特定のポイントが任意のコントロールの境界内にあるかどうかを判断するために使用できる 1 つの戦略は、フォーム Control.Collection (this.Controls) の forall を介してフォーム上のすべてのコントロールの領域 (境界) を列挙することです。ただし、コントロールが重複している場合は、複数のコントロールが特定のポイントを含む可能性があるという問題があります。

最高、ビル

于 2009-11-12T04:41:42.993 に答える
0

私はパンチに少し遅れていることを知っていますが、今日パネルをタイトルバーとして使用するときにこれに問題がありました。テキストを表示するためのラベル、ピクチャ ボックス、およびいくつかのボタンをすべて Panel 内にネストしましたが、とにかく MouseMove イベントをトラップする必要がありました。

私がやろうと決めたのは、これを行うために再帰メソッド ハンドラを実装することでした。入れ子になったコントロールは 1 レベルしかないため、ばかげたレベルの入れ子に近づくと、これはあまりうまくスケーリングされない可能性があります。

これが私がそれをした方法です:

    protected virtual void NestedControl_Mousemove(object sender, MouseEventArgs e)
    {
        Control current = sender as Control;
        //you will need to edit this to identify the true parent of your top-level control. As I was writing a custom UserControl, "this" was my title-bar's parent.
        if (current.Parent != this) 
        {
            // Reconstruct the args to get a correct X/Y value.
            // you can ignore this if you never need to get e.X/e.Y accurately.
            MouseEventArgs newArgs = new MouseEventArgs
            (
                e.Button, 
                e.Clicks, 
                e.X + current.Location.X, 
                e.Y + current.Location.Y, 
                e.Delta
            );
            NestedControl_Mousemove(current.Parent, newArgs);
        }
        else
        {
            // My "true" MouseMove handler, called at last.
            TitlebarMouseMove(current, e);
        }
    }

    //helper method to basically just ensure all the child controls subscribe to the NestedControl_MouseMove event.
    protected virtual void AddNestedMouseHandler(Control root, MouseEventHandler nestedHandler)
    {
        root.MouseMove += new MouseEventHandler(nestedHandler);
        if (root.Controls.Count > 0)
            foreach (Control c in root.Controls)
                AddNestedMouseHandler(c, nestedHandler);
    }

そして、それを設定するのは比較的簡単です:

「真の」ハンドラーを定義します。

    protected virtual void TitlebarMouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            this.Text = string.Format("({0}, {1})", e.X, e.Y);
        }
    }

次に、コントロール イベント サブスクライバーをセットアップします。

//pnlDisplay is my title bar panel.
AddNestedMouseHandler(pnlDisplay, NestedControl_Mousemove);

使い方は比較的簡単で、機能するという事実を保証できます:)

于 2012-07-03T13:51:13.823 に答える