2

MouseLeave イベントを使用して、ユーザーがフォームを離れたかどうかを確認し、ウィンドウを閉じますが、使用 this.MouseLeave += new System.EventHandler(this.InvisibleForm_Leave); が遅すぎます。フォームをゆっくり離れる場合にのみ、イベントが発生し、通常の方法で移動します /少し速くなると、休暇イベントは発生しません。

したがって、マウスがフォームを離れたかどうかを自分で確認しようとしました。

private void checkPos()
    {
        Rectangle rec = this.Bounds;
        while (true)
        {
            Point point = new Point(Cursor.Position.X, Cursor.Position.Y);
            if (!rec.Contains(point))
            {
                Console.WriteLine("leaving");
                this.Close();                    
            }
            Thread.Sleep(100);
        }
    }

フォームを作成した後、独自のスレッドで開始しました:

public MyForm()
    {
        InitializeComponent();
        Thread m_mouseListenerThread = new Thread(new ThreadStart(this.checkPos));
        m_mouseListenerThread.Start();            
    }

しかし、これで私は多かれ少なかれ同じ問題を抱えています。エリアを離れるとrec.Contains(point)、ifコードを実行しようとしている1秒後にチェックした後でもtrueが返されますが、時々彼はそれを瞬時に取得します。

これに関する 2 番目の問題は、メソッドのthis.Close();行でスレッド例外が発生することです。checkPost()

クロススレッド操作が無効です: コントロール 'MyForm' は、それが作成されたスレッド以外のスレッドからアクセスされました。

今、マウスを離す部分を別の方法で実装する方法がよくわかりません。

4

3 に答える 3

3

ここでは、MouseLeaveのパフォーマンスが問題になるとは思いません。私はMouseLeave(MouseEnterおよびMouseMoveと組み合わせて)を使用して、フォームを自動的にフェードイン/フェードアウトしました。できます :)。ラベルだけのサンプルフォームは次のとおりです。

MouseLeaveがラベルとフォームの両方で処理される場合、マウスの移動速度に関係なく、イベントハンドラーは常に起動します。例えば:

this.label1.MouseLeave += new System.EventHandler(this.HandleMouseLeave);
this.MouseLeave += new System.EventHandler(this.HandleMouseLeave);

private void HandleMouseLeave(object sender, EventArgs e)
{
   Debug.WriteLine(string.Format("MouseLeave: {0}", DateTime.Now));
}

ただし、label1のMouseLeaveハンドラーを削除すると、表示されている動作を再現できます。マウスをlabel1(オレンジ)からフォーム(緑)にゆっくりと移動すると、イベントが発生します。マウスをlabel1からフォームの外側にすばやく移動すると、イベントは発生しません。

つまり、私が考えているのは、フォームの子コントロールがMouseLeaveイベントを発生させており、そのイベントを処理していないということです。マウスをゆっくり動かすとイベントが発生するのを見る理由は、イベントを生成するのに十分な時間、フォーム領域にカーソルを合わせているためです。

さらに、MouseLeaveイベントを監視するために別のスレッドを生成することは、適切なアプローチではありません。このスレッドが(イベントを待機するのではなく)イベント状態をポーリングするため、パフォーマンスが低下し、スレッドの開始/停止という不必要な頭痛の種が発生します。また、必要なときにいつでもUIスレッドを呼び出す必要があります。 (あなたが学んだように)フォームで何でもします。MouseLeaveイベントのアプローチを再検討する時間があれば、そうすることを強くお勧めします。幸運を!

于 2012-04-20T12:42:13.117 に答える
2
  1. マウスを残す部分については、よくわかりません。たぶん、MouseMoveイベントでそれを処理しようとすることができますか?
  2. 無効なクロススレッド操作の問題の場合、別のスレッド(この場合はUIスレッド)が所有するコントロールにアクセスできません。代わりに、 Control.BeginInvokeまたはControl.Invokeを使用してください。
于 2012-04-20T11:45:34.280 に答える