Di MSDN saya CloseReason.UserClosing
mengetahui bahwa pengguna telah memutuskan untuk menutup formulir tetapi saya rasa itu sama untuk mengklik tombol X atau mengklik tombol tutup. Jadi bagaimana saya bisa membedakan keduanya dalam kode saya?
Terima kasih semuanya.
Jawaban:
Dengan asumsi Anda meminta WinForms, Anda dapat menggunakan acara FormClosing () . Acara FormClosing () dipicu setiap saat formulir ditutup.
Untuk mendeteksi apakah pengguna mengklik X atau CloseButton Anda, Anda mungkin mendapatkannya melalui objek pengirim. Cobalah untuk mentransmisikan pengirim sebagai kontrol Tombol, dan verifikasi mungkin untuk namanya "CloseButton", misalnya.
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. }
Jika tidak, saya tidak pernah perlu membedakan apakah X atau CloseButton diklik, karena saya ingin melakukan sesuatu yang spesifik pada acara FormClosing, seperti menutup semua MdiChildren sebelum menutup MDIContainerForm, atau memeriksa acara untuk perubahan yang belum disimpan. Dalam keadaan ini, menurut saya, kita tidak perlu membedakan tombol mana pun.
Menutup dengan ALT+ F4juga akan memicu acara FormClosing (), karena mengirimkan pesan ke Formulir yang bertuliskan tutup. Anda dapat membatalkan acara dengan menyetel
FormClosingEventArgs.Cancel = true.
Dalam contoh kami, ini akan diterjemahkan menjadi
e.Cancel = true.
Perhatikan perbedaan antara acara FormClosing () dan FormClosed () .
FormClosing terjadi ketika formulir menerima pesan untuk ditutup, dan memverifikasi apakah ada sesuatu yang harus dilakukan sebelum ditutup.
FormClosed terjadi saat formulir benar-benar ditutup, jadi setelah itu ditutup.
Apakah ini membantu?
sumber
The
CloseReason
pencacahan Anda temukan di MSDN hanya untuk tujuan memeriksa apakah pengguna ditutup aplikasi, atau itu karena shutdown, atau ditutup oleh task manager, dll ...Anda dapat melakukan berbagai tindakan, sesuai dengan alasannya, seperti:
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 }
Tapi seperti yang Anda duga, tidak ada perbedaan antara mengklik tombol x, atau mengklik kanan bilah tugas dan mengklik 'tutup', atau menekan Alt F4, dll. Semuanya berakhir dengan suatu
CloseReason.UserClosing
alasan.sumber
Tombol "X" mendaftar
DialogResult.Cancel
sehingga opsi lainnya adalah mengevaluasiDialogResult
.Jika Anda memiliki beberapa tombol pada formulir Anda, Anda mungkin sudah menghubungkan
DialogResult
tombol yang berbeda ke masing-masing tombol dan ini akan memberi Anda cara untuk membedakan setiap tombol.(Contoh:
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; } } }
sumber
DialogResult
tetap adaNone
. Apa masalahnya?X
membuatDialogResult
berisiCancel
, bukanNone
. MenetapkanNone
ke tombol Anda sama dengan tidak menyetel.DialogResult
propertinya sama sekali, dan jika Anda memanggilform.Close()
dari event handler tombol Anda,form.DialogResult
akan berisiCancel
. Hanya menetapkan nilai selainNone
atauCancel
ke semua tombol penutup formulir akan memungkinkan Anda membuat perbedaan yang diinginkan.Bagaimana cara mendeteksi jika formulir ditutup dengan mengklik tombol X atau dengan memanggil
Close()
kode?Anda tidak dapat mengandalkan alasan penutupan dari argumen acara penutupan formulir, karena jika pengguna mengklik tombol X pada bilah judul atau menutup formulir menggunakan Alt + F4 atau menggunakan menu sistem untuk menutup formulir atau formulir ditutup dengan
Close()
metode panggilan , semua kasus di atas, alasan penutupan akan ditutup oleh Pengguna yang bukan hasil yang diinginkan.Untuk membedakan apakah formulir ditutup oleh tombol X atau dengan
Close
metode, Anda dapat menggunakan salah satu opsi berikut:WM_SYSCOMMAND
dan periksaSC_CLOSE
serta setel bendera.StackTrace
untuk melihat apakah ada frame yang berisiClose
pemanggilan metode.Contoh 1 - Pegangan
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()"); }
Contoh 2 - Memeriksa 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"); }
sumber
StackTrace()
dan itu memecahkan masalah.Ini menentukan kapan harus menutup aplikasi jika formulir ditutup (jika aplikasi Anda tidak dilampirkan ke formulir tertentu).
private void MyForm_FormClosed(object sender, FormClosedEventArgs e) { if (Application.OpenForms.Count == 0) Application.Exit(); }
sumber
Saya selalu menggunakan metode Tutup Formulir dalam aplikasi saya yang menangkap alt + x dari Tombol keluar saya, alt + f4 atau acara penutupan formulir lainnya dimulai. Semua kelas saya memiliki nama kelas yang didefinisikan sebagai string pribadi
mstrClsTitle = "grmRexcel"
dalam kasus ini, metode Keluar yang memanggil Metode Penutupan Formulir dan Metode Penutupan Formulir. Saya juga memiliki pernyataan untuk Metode Penutupan Formulir -this.FormClosing = My Form Closing Form Closing method name
.Kode untuk ini:
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; } } } } }
sumber
Anda dapat mencoba menambahkan event handler dari desain seperti ini: Buka form dalam tampilan desain, buka jendela properti atau tekan F4, klik tombol event toolbar untuk melihat event pada objek Form, temukan event FormClosing di grup Behavior, dan klik dua kali. Referensi: https://social.msdn.microsoft.com/Forums/vstudio/en-US/9bdee708-db4b-4e46-a99c-99726fa25cfb/how-do-i-add-formclosing-event?forum=csharpgeneral
sumber
if (this.DialogResult == DialogResult.Cancel) { } else { switch (e.CloseReason) { case CloseReason.UserClosing: e.Cancel = true; break; } }
jika kondisi akan dieksekusi ketika pengguna mengklik 'X' atau tombol tutup pada formulir. Yang lain dapat digunakan saat pengguna mengklik Alt + f4 untuk tujuan lain
sumber
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 } } } }
sumber
Saya setuju dengan
DialogResult
-Solusi sebagai yang lebih lurus ke depan.Dalam VB.NET bagaimanapun, typecast diperlukan untuk mendapatkan
CloseReason
-PropertyPrivate 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
sumber
Saya juga harus mendaftarkan fungsi penutupan di dalam metode "InitializeComponent ()" formulir:
private void InitializeComponent() { // ... this.FormClosing += FrmMain_FormClosing; // ... }
Fungsi "FormClosing" saya terlihat mirip dengan jawaban yang diberikan ( 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"); } }
Satu hal lagi untuk disebutkan: Ada juga fungsi "FormClosed" yang muncul setelah "FormClosing". Untuk menggunakan fungsi ini, daftarkan seperti yang ditunjukkan di bawah ini:
this.FormClosed += MainPage_FormClosed; private void MainPage_FormClosing(object sender, FormClosingEventArgs e) { // your code after the form is closed }
sumber
Saya telah melakukan sesuatu seperti ini.
private void Form_FormClosing(object sender, FormClosingEventArgs e) { if ((sender as Form).ActiveControl is Button) { //CloseButton } else { //The X has been clicked } }
sumber