1

使用以下代码,当我将鼠标移入按钮并单击它时,结果的最终值为2 而不是 1。

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. 使用MouseEnter而不是MouseHover给出结果 = 1

  2. 只有将 FlatStyle 更改为 System 才会在单击按钮后再触发一次 MouseHover。如果按钮的FlatStyle原来是FlatStyle.System,给result = 1;如果将 FlatStyle 更改为其他 Style(popup, flat),则给出result = 1

所以我想问题在于将 FlatStyle 设置为 FlatStyle.System,任何人都可以向我解释一下吗?

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 会尽力恢复新窗口的状态,但有一些它无法恢复。“窗口悬停”状态就是其中之一。显然,新窗口的内部状态标志设置为 false。这就是您再次获得 MouseHover 事件的原因。你需要解决这个怪癖。

于 2012-12-28T09:21:05.767 回答