ใน MSDN ฉันพบCloseReason.UserClosing
ว่าผู้ใช้ตัดสินใจปิดแบบฟอร์ม แต่ฉันคิดว่ามันเหมือนกันสำหรับทั้งการคลิกปุ่ม X หรือคลิกปุ่มปิด แล้วฉันจะแยกความแตกต่างระหว่างสองสิ่งนี้ในรหัสของฉันได้อย่างไร
ขอบคุณทุกคน
ใน MSDN ฉันพบCloseReason.UserClosing
ว่าผู้ใช้ตัดสินใจปิดแบบฟอร์ม แต่ฉันคิดว่ามันเหมือนกันสำหรับทั้งการคลิกปุ่ม X หรือคลิกปุ่มปิด แล้วฉันจะแยกความแตกต่างระหว่างสองสิ่งนี้ในรหัสของฉันได้อย่างไร
ขอบคุณทุกคน
คำตอบ:
สมมติว่าคุณขอ WinForms คุณอาจใช้FormClosing () เหตุการณ์ เหตุการณ์ FormClosing () จะถูกทริกเกอร์ทุกครั้งที่มีการปิดฟอร์ม
หากต้องการตรวจสอบว่าผู้ใช้คลิก X หรือ CloseButton ของคุณหรือไม่คุณอาจได้รับผ่านวัตถุผู้ส่ง พยายามแคสผู้ส่งเป็นตัวควบคุมปุ่มและอาจตรวจสอบชื่อ "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 เช่นการปิด MdiChildren ทั้งหมดก่อนที่จะปิด MDIContainerForm หรือการตรวจสอบเหตุการณ์สำหรับการเปลี่ยนแปลงที่ไม่ได้บันทึก ภายใต้สถานการณ์เหล่านี้เราไม่จำเป็นต้องตามฉันเพื่อแยกความแตกต่างจากปุ่มใดปุ่มหนึ่ง
การปิดโดยALT+ F4จะทริกเกอร์เหตุการณ์ FormClosing () ด้วยเนื่องจากจะส่งข้อความไปยังแบบฟอร์มที่แจ้งว่าจะปิด คุณสามารถยกเลิกกิจกรรมได้โดยตั้งค่า
FormClosingEventArgs.Cancel = true.
ในตัวอย่างของเราสิ่งนี้จะแปลว่าเป็น
e.Cancel = true.
เห็นความแตกต่างระหว่าง FormClosing () และที่FormClosed ()เหตุการณ์
FormClosing เกิดขึ้นเมื่อแบบฟอร์มได้รับข้อความที่จะปิดและตรวจสอบว่ามีสิ่งที่ต้องทำก่อนที่จะปิดหรือไม่
FormClosed เกิดขึ้นเมื่อปิดฟอร์มจริงดังนั้นหลังจากปิดแล้ว
สิ่งนี้ช่วยได้หรือไม่?
การCloseReason
แจงนับที่คุณพบใน MSDN เป็นเพียงจุดประสงค์ในการตรวจสอบว่าผู้ใช้ปิดแอปหรือเกิดจากการปิดหรือปิดโดยตัวจัดการงาน ฯลฯ ...
คุณสามารถดำเนินการต่างๆได้ตามเหตุผลเช่น:
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 หรือการคลิกขวาบนทาสก์บาร์และการคลิก 'ปิด' หรือการกดAlt F4ฯลฯ ทุกอย่างลงเอยCloseReason.UserClosing
ด้วยเหตุผล
ปุ่ม "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
ให้กับปุ่มปิดแบบฟอร์มทั้งหมดของคุณเท่านั้นที่จะช่วยให้คุณสร้างความแตกต่างที่ต้องการได้
Close()
รหัส?คุณไม่สามารถพึ่งพาเหตุผลปิดของอาร์กิวเมนต์เหตุการณ์การปิดฟอร์มได้เนื่องจากหากผู้ใช้คลิกปุ่ม X บนแถบหัวเรื่องหรือปิดแบบฟอร์มโดยใช้ Alt + F4 หรือใช้เมนูระบบเพื่อปิดแบบฟอร์มหรือปิดฟอร์มโดยClose()
วิธีการเรียกทั้งหมด กรณีข้างต้นเหตุผลในการปิดจะถูกปิดโดยผู้ใช้ซึ่งไม่ใช่ผลลัพธ์ที่ต้องการ
หากต้องการแยกแยะว่าฟอร์มปิดด้วยปุ่ม 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");
}
StackTrace()
และมันแก้ปัญหาได้
กำหนดว่าจะปิดแอปพลิเคชันเมื่อใดหากปิดแบบฟอร์ม (หากใบสมัครของคุณไม่ได้แนบกับแบบฟอร์มเฉพาะ)
private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (Application.OpenForms.Count == 0) Application.Exit();
}
ฉันมักจะใช้วิธีการปิดฟอร์มในแอปพลิเคชันของฉันที่จับ alt + x จากปุ่มออกของฉัน, alt + f4หรือเหตุการณ์ปิดฟอร์มอื่นเริ่มต้นขึ้น คลาสทั้งหมดของฉันมีชื่อคลาสที่กำหนดเป็นสตริงส่วนตัว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;
}
}
}
}
}
คุณสามารถลองเพิ่มตัวจัดการเหตุการณ์จากการออกแบบเช่นนี้: เปิดฟอร์มในมุมมองออกแบบเปิดหน้าต่างคุณสมบัติหรือกด F4 คลิกปุ่มแถบเครื่องมือเหตุการณ์เพื่อดูเหตุการณ์บนวัตถุแบบฟอร์มค้นหาเหตุการณ์ FormClosing ในกลุ่มพฤติกรรมและดับเบิลคลิก อ้างอิง: https://social.msdn.microsoft.com/Forums/vstudio/en-US/9bdee708-db4b-4e46-a99c-99726fa25cfb/how-do-i-add-formclosing-event?forum=csharpgeneral
if (this.DialogResult == DialogResult.Cancel)
{
}
else
{
switch (e.CloseReason)
{
case CloseReason.UserClosing:
e.Cancel = true;
break;
}
}
หากเงื่อนไขจะดำเนินการเมื่อผู้ใช้คลิก 'X' หรือปุ่มปิดในแบบฟอร์ม อื่น ๆ สามารถใช้ได้เมื่อผู้ใช้คลิก Alt + f4 เพื่อวัตถุประสงค์อื่นใด
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
}
}
}
}
ฉันเห็นด้วยกับDialogResult
-Solution ว่าตรงไปตรงมามากกว่า
อย่างไรก็ตามใน VB.NET จำเป็นต้องใช้ typecast เพื่อรับCloseReason
-Property
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
ฉันต้องลงทะเบียนฟังก์ชันการปิดภายในเมธอด "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
}
}