提问人:Bohn 提问时间:4/21/2010 最后编辑:CronoBohn 更新时间:6/26/2023 访问量:383777
如何知道用户已点击“X”或“关闭”按钮?
How to know user has clicked "X" or the "Close" button?
问:
在MSDN中,我发现用户已决定关闭表单
但我想单击 X 按钮或单击关闭按钮都是一样的。
那么,如何在代码中区分这两者呢?CloseReason.UserClosing
谢谢大家。
答:
假设您要求 WinForms,则可以使用 FormClosing() 事件。每当窗体关闭时,都会触发事件 FormClosing()。
若要检测用户是否单击了 X 或 CloseButton,可以通过发送方对象获取它。例如,尝试将发送方强制转换为 Button 控件,并验证其名称“CloseButton”。
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
if (string.Equals((sender as Button).Name, @"CloseButton"))
// Do something proper to CloseButton.
else
// Then assume that X has been clicked and act accordingly.
}
否则,我从不需要区分是单击了 X 还是 CloseButton,因为我想对 FormClosing 事件执行特定操作,例如在关闭 MDIContainerForm 之前关闭所有 MdiChildren,或者检查未保存的更改。在这种情况下,根据我的说法,我们不需要与任何一个按钮区分开来。
关闭方式 + 也会触发 FormClosing() 事件,因为它会向 Form 发送一条消息,提示关闭。您可以通过设置ALTF4
FormClosingEventArgs.Cancel = true.
在我们的示例中,这将翻译为
e.Cancel = true.
请注意 FormClosing() 和 FormClosed() 事件之间的区别。
当窗体收到要关闭的消息时,将发生 FormClosure,并在关闭之前验证它是否有事情要做。
FormClosed 发生在窗体实际关闭时,因此在窗体关闭之后。
这有帮助吗?
评论
您在 MSDN 上找到的枚举只是为了检查用户是否关闭了应用程序,或者是由于关机,还是被任务管理器关闭等......CloseReason
您可以根据原因执行不同的操作,例如:
void Form_FormClosing(object sender, FormClosingEventArgs e)
{
if(e.CloseReason == CloseReason.UserClosing)
// Prompt user to save his data
if(e.CloseReason == CloseReason.WindowsShutDown)
// Autosave and clear up ressources
}
但就像你猜到的,单击x按钮,或右键单击任务栏并单击“关闭”,或按,等等,这两者之间没有区别。这一切都以 CloseReason.UserClosing
原因告终。AltF4
评论
“X”按钮注册,因此另一个选项是评估 .DialogResult.Cancel
DialogResult
如果您的窗体上有多个按钮,您可能已经将不同的按钮与每个按钮相关联,这将为您提供区分每个按钮的方法。DialogResult
(例如: ,btnSubmit.DialogResult = DialogResult.OK
btnClose.DialogResult = Dialogresult.Abort
)
public Form1()
{
InitializeComponent();
this.FormClosing += Form1_FormClosing;
}
/// <summary>
/// Override the Close Form event
/// Do something
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
//In case windows is trying to shut down, don't hold the process up
if (e.CloseReason == CloseReason.WindowsShutDown) return;
if (this.DialogResult == DialogResult.Cancel)
{
// Assume that X has been clicked and act accordingly.
// Confirm user wants to close
switch (MessageBox.Show(this, "Are you sure?", "Do you still want ... ?", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
//Stay on this form
case DialogResult.No:
e.Cancel = true;
break;
default:
break;
}
}
}
评论
DialogResult
None
X
DialogResult
Cancel
None
None
.DialogResult
form.Close()
form.DialogResult
Cancel
None
Cancel
if (this.DialogResult == DialogResult.Cancel)
{
}
else
{
switch (e.CloseReason)
{
case CloseReason.UserClosing:
e.Cancel = true;
break;
}
}
如果条件将在用户单击表单上的“X”或关闭按钮时执行。当用户出于任何其他目的单击 Alt+f4 时,可以使用 else
它确定在窗体关闭时何时关闭应用程序(如果您的应用程序未附加到特定窗体)。
private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (Application.OpenForms.Count == 0) Application.Exit();
}
您可以尝试从设计中添加事件处理程序,如下所示:在设计视图中打开窗体,打开属性窗口或按 F4,单击事件工具栏按钮查看 Form 对象上的事件,在“行为”组中找到 FormClosing 事件,然后双击它。 参考: https://social.msdn.microsoft.com/Forums/vstudio/en-US/9bdee708-db4b-4e46-a99c-99726fa25cfb/how-do-i-add-formclosing-event?forum=csharpgeneral
我总是在我的应用程序中使用 Form Close 方法,该方法从我的退出按钮、alt + f4 或其他表单关闭事件中捕获 alt + x。在本例中,我的所有类都具有定义为 Private string 的类名,即调用 Form Closing 方法和 Form Closing 方法的 Exit 方法。我还有一个关于表单关闭方法的声明 - 。mstrClsTitle = "grmRexcel"
this.FormClosing = My Form Closing Form Closing method name
代码如下:
namespace Rexcel_II
{
public partial class frmRexcel : Form
{
private string mstrClsTitle = "frmRexcel";
public frmRexcel()
{
InitializeComponent();
this.FormClosing += frmRexcel_FormClosing;
}
/// <summary>
/// Handles the Button Exit Event executed by the Exit Button Click
/// or Alt + x
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
/// <summary>
/// Handles the Form Closing event
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void frmRexcel_FormClosing(object sender, FormClosingEventArgs e)
{
// ---- If windows is shutting down,
// ---- I don't want to hold up the process
if (e.CloseReason == CloseReason.WindowsShutDown) return;
{
// ---- Ok, Windows is not shutting down so
// ---- either btnExit or Alt + x or Alt + f4 has been clicked or
// ---- another form closing event was intiated
// *) Confirm user wants to close the application
switch (MessageBox.Show(this,
"Are you sure you want to close the Application?",
mstrClsTitle + ".frmRexcel_FormClosing",
MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
// ---- *) if No keep the application alive
//---- *) else close the application
case DialogResult.No:
e.Cancel = true;
break;
default:
break;
}
}
}
}
}
namespace Test
{
public partial class Member : Form
{
public Member()
{
InitializeComponent();
}
private bool xClicked = true;
private void btnClose_Click(object sender, EventArgs e)
{
xClicked = false;
Close();
}
private void Member_FormClosing(object sender, FormClosingEventArgs e)
{
if (xClicked)
{
// user click the X
}
else
{
// user click the close button
}
}
}
}
我同意 -Solution 作为更直接的解决方案。DialogResult
但是,在 VB.NET 中,需要类型转换才能获取 -PropertyCloseReason
Private Sub MyForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
Dim eCast As System.Windows.Forms.FormClosingEventArgs
eCast = TryCast(e, System.Windows.Forms.FormClosingEventArgs)
If eCast.CloseReason = Windows.Forms.CloseReason.None Then
MsgBox("Button Pressed")
Else
MsgBox("ALT+F4 or [x] or other reason")
End If
End Sub
如何通过单击 X 按钮或调用代码来检测表单是否关闭?Close()
您不能依赖表单关闭事件参数的关闭原因,因为:
如果用户单击标题栏上的 X 按钮或使用 Alt + F4 关闭表单或使用系统菜单关闭表单或
通过调用 Close()
方法关闭表单,
对于上述所有情况,关闭原因将是 Closed by User (),这不是期望的结果。CloseReason.UserClosing
若要区分窗体是按 X 按钮关闭还是按方法关闭,可以使用以下任一选项:Close
- 处理
WM_SYSCOMMAND
并检查并设置标志。SC_CLOSE
- 检查
StackTrace
以查看是否有任何帧包含方法调用。Close
示例 1 - 句柄WM_SYSCOMMAND
public bool ClosedByXButtonOrAltF4 {get; private set;}
private const int SC_CLOSE = 0xF060;
private const int WM_SYSCOMMAND = 0x0112;
protected override void WndProc(ref Message msg)
{
if (msg.Msg == WM_SYSCOMMAND && msg.WParam.ToInt32() == SC_CLOSE)
ClosedByXButtonOrAltF4 = true;
base.WndProc(ref msg);
}
protected override void OnShown(EventArgs e)
{
ClosedByXButtonOrAltF4 = false;
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (ClosedByXButtonOrAltF4)
MessageBox.Show("Closed by X or Alt+F4");
else
MessageBox.Show("Closed by calling Close()");
}
示例 2 - 检查 StackTrace
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (new StackTrace().GetFrames().Any(x => x.GetMethod().Name == "Close"))
MessageBox.Show("Closed by calling Close()");
else
MessageBox.Show("Closed by X or Alt+F4");
}
我还必须在表单的“InitializeComponent()”方法中注册关闭函数:
private void InitializeComponent() {
// ...
this.FormClosing += FrmMain_FormClosing;
// ...
}
我的“FormClosing”函数看起来类似于给定的答案(https://stackoverflow.com/a/2683846/3323790):
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e) {
if (e.CloseReason == CloseReason.UserClosing){
MessageBox.Show("Closed by User", "UserClosing");
}
if (e.CloseReason == CloseReason.WindowsShutDown){
MessageBox.Show("Closed by Windows shutdown", "WindowsShutDown");
}
}
还有一件事要提:还有一个“FormClosed”函数,它发生在“FormClosing”之后。要使用此功能,请按如下所示进行注册:
this.FormClosed += MainPage_FormClosed;
private void MainPage_FormClosing(object sender, FormClosingEventArgs e)
{
// your code after the form is closed
}
我做过这样的事情。
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
if ((sender as Form).ActiveControl is Button)
{
//CloseButton
}
else
{
//The X has been clicked
}
}
评论
这种方法是无效的。
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (new StackTrace().GetFrames().Any(x => x.GetMethod().Name == "Close"))
MessageBox.Show("Closed by calling Close()");
else
MessageBox.Show("Closed by X or Alt+F4");
}
本页参考。
评论