1

次のコードでは、マウスをボタンに移動してクリックすると、結果の最終値は 1 ではなく 2 になります。

static int result = 0;

private void button2_MouseHover(object sender, EventArgs e)
{
   result++;
}

private void button2_MouseDown(object sender, MouseEventArgs e)
{
   button2.FlatStyle = FlatStyle.System;
}

別の設定を試しました:

  1. MouseHoverの代わりにMouseEnterを使用すると、結果が 1になります

  2. FlatStyle を System に変更するだけで、ボタンがクリックされた後に MouseHover がもう一度トリガーされます。ボタンの FlatStyle が元々 FlatStyle.System である場合、result = 1を返します。FlatStyle が他の Style(popup, flat) に変更された場合、result = 1を返します。

問題はFlatStyle.Systemに設定されたFlatStyleにあると思いますが、誰でもこれを説明できますか?

4

1 に答える 1

2

これは、Winforms ではかなり一般的な癖です。このコードで何が起こっているかを視覚化できます。

    private void button1_MouseHover(object sender, EventArgs e) {
        Console.WriteLine("{0:X}, {1}", button1.Handle, DateTime.Now.TimeOfDay);
        result++;
    }

表示された診断の [出力] ウィンドウを確認します。私の場合:

12780286, 03:04:10.7619696
12780286, 03:04:16.2935137
12780286, 03:04:20.1062178
12780286, 03:04:23.9970596
Click
12845822, 03:04:28.9191911
12845822, 03:04:32.3099880

クリック後に Handle プロパティの値がどのように変化したかに注意してください。つまり、物理的な Windows ウィンドウが変更されました。これは、FlatStyle プロパティを変更したために発生しました。Winformsは、ボタン コントロール ウィンドウを破棄して再作成することでこれを実装します。よく見ると、実際にこれを見ることができます。ボタンが一瞬ちらつきます。

このように実装されているプロパティがいくつかあります。これらは、スタイル フラグが変更されたため、ウィンドウを再作成する必要がある「重い」プロパティです。ネイティブの CreateWindowEx() 呼び出しで渡されるスタイル フラグ。これらのスタイル フラグを変更するには、CreateWindowEx() をもう一度呼び出す必要があります。

これには副作用がつきものです。古いウィンドウを破棄すると、その状態が失われます。Winforms は、できる限り新しいウィンドウの状態を復元しようとしますが、復元できないものもいくつかあります。「ウィンドウがホバリングされた」状態もその 1 つです。明らかに、新しいウィンドウの内部状態フラグは false に設定されています。これが、MouseHover イベントを再度取得する理由です。この癖を回避する必要があります。

于 2012-12-28T09:21:05.767 に答える