OnFormClosing和e.CloseReason

时间:2015-06-17 12:48:36

标签: c# winforms

我有一个表单上有两个按钮“取消”和“确定”。在“取消”按钮的处理程序中,我做了我需要做的任何回滚,然后调用this.Close()。在“确定”按钮的处理程序中,我做了我需要做的任何事情,然后调用this.Close()

所以我现在意识到用户也可以点击表单右上角的“X”图标来关闭表单。我应该像处理“取消”按钮一样对待它,但是我无法覆盖“X”按钮。我能做的最好的事情是为OnFormClosing事件添加一个处理程序。

我仍然感到困惑,并且不确定处理这个问题的最佳方法是什么。表单也可以关闭还有许多其他原因(如ALT-F4或Windows关闭)我想将所有这些视为“取消”按钮。

但是,是否通过单击“X”,“关闭”(最终调用this.Close())或“确定”(最终调用this.Close())来关闭表单,{{ 1}}是相同的(e.CloseReason),UserClosing的值也是相同的,所以我无法区分。

如果表单因单击“确定”按钮以外的任何原因而关闭,那么实现回滚的最佳方法是什么?

3 个答案:

答案 0 :(得分:2)

你只需要在你的OK按钮处理程序中设置一个布尔值,并检查你的OnFormClosing()覆盖中的布尔值,如下所示:

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

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        base.OnFormClosing(e);

        if (!this.isClosingViaOkButton)
        {
            // ...do your rollback here.

            MessageBox.Show("Rolling back");
        }
    }

    private void okButton_Click(object sender, EventArgs e)
    {
        // ...do your committing here.

        this.isClosingViaOkButton = true;
        this.Close();
    }

    private bool isClosingViaOkButton;
}

作为替代方案,您可以在OnFormClosing()中执行这两项操作,而不是在OK按钮处理程序中提交并在OnFormClosing()中回滚,如下所示:

protected override void OnFormClosing(FormClosingEventArgs e)
{
    base.OnFormClosing(e);

    if (this.isClosingViaOkButton)
    {
        // ...do your committing.
    }
    else
    {
        // ...do your rollback.
    }
}

我自己更喜欢这种方法。

答案 1 :(得分:1)

你真的不需要CloseReason,是吗?

private bool _closing;
private void Form1_FormClosing( object sender, FormClosingEventArgs e )
{
    e.Cancel = !_closing; // prevent form from being closed
}

// inside OK and Cancel button handler
...
_closing = true;
Close();

答案 2 :(得分:0)

在某些表单中,我通过使用Win32函数隐藏X按钮来解决问题 - 不知道它是否适合您的情况,但代码如下。

/// <summary>
/// Win32 function to get window information
/// </summary>
/// <param name="hWnd">Window handle</param>
/// <param name="nIndex">Information to get</param>
/// <returns>Required Window Information</returns>
[DllImport("user32.dll")]
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
/// <summary>
/// Code to get/set Style for window
/// </summary>
private const int GWL_STYLE = -16;
/// <summary>
/// System menu bit
/// </summary>
private const int WS_SYSMENU = 0x80000;

/// <summary>
/// Hide close button on window
/// </summary>
/// <param name="w">Window to set</param>
/// <remarks>Actually removes all of system menu from window title bar</remarks>
public static void HideCloseButton(Window w)
{
  var hwnd = new WindowInteropHelper(w).Handle;
  NativeMethods.SetWindowLong(hwnd, GWL_STYLE, NativeMethods.GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
}
/// <summary>
/// Show close button on window
/// </summary>
/// <param name="w">Window to set</param>
/// <remarks>Actually shows all of system menu from window title bar</remarks>
public static void ShowCloseButton(Window w)
{
  var hwnd = new WindowInteropHelper(w).Handle;
  NativeMethods.SetWindowLong(hwnd, GWL_STYLE, NativeMethods.GetWindowLong(hwnd, GWL_STYLE) | WS_SYSMENU);
}