WinForms应用程序中第二次未检测到任务管理器关闭。

5
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.UserClosing)
    {
        if (MessageBox.Show(this, "Do you really want to close?", "Close?", 
                            MessageBoxButtons.YesNo) == DialogResult.No)
        {
            e.Cancel = true;
        }
    }
}

当我点击关闭按钮时,消息框弹出,然后我选择“否”,接着执行了“e.Cancel = true”这一行代码,导致窗体没有被关闭。现在的问题是,如果我在任务管理器中关闭应用程序,关闭原因显示为“UserClosing”!为什么?不应该是“TaskManagerClosing”吗?

哇,我完全能够复现这个问题:如果任务管理器在用户取消关闭操作后尝试关闭窗体,则任务管理器的关闭尝试将被传递为CloseReason中的UserClosing,而不是通常的TaskManagerClosing。这是一个bug吗?还是预期行为?好问题,+1! - M.A. Hanin
3个回答

4

我在线程中发现了一个答案,由我们自己的nobugz提供:

Windows Forms无法检测到关闭原因来自任务管理器。因此,它会自动将CloseReason.None转换为CloseReason.TaskManagerClosing。问题是,一旦你尝试使用“X”关闭,CloseReason就设置为UserClosing,并且如果你取消关闭,它不会被重置回None。这很粗糙。

旁边还有另一个用户的解释,说明如何使用反射将e.CloseReason的值更改为None(因为它是只读的),以解决这个问题(当设置e.Cancel为True时应用此方法):

FieldInfo fi = typeof(Form).GetField("closeReason", BindingFlags.Instance | BindingFlags.NonPublic);

fi.SetValue(this, CloseReason.None);

1

链接中的代码可以检测到关闭是由按钮点击还是由Windows X按钮点击引起的。在这里使用bool属性来检测是可以的。但如何检测TaskManager的关闭呢? - Samir

1

这是您VB代码的翻译:

Imports System.Reflection
Private Sub ResetCloseReason()
  Dim myFieldInfo As FieldInfo
  Dim myType As Type = GetType(Form)
  myFieldInfo = myType.GetField("closeReason", BindingFlags.NonPublic Or _
                    BindingFlags.Instance Or BindingFlags.Public)
  myFieldInfo.SetValue(Me, CloseReason.None)

结束子程序


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接