MSDN CloseReason.UserClosing
에서 사용자가 양식을 닫기로 결정한 것을 알았지 만 X 단추를 클릭하거나 닫기 단추를 클릭하는 것이 동일하다고 생각합니다. 그렇다면 내 코드에서이 둘을 어떻게 구별 할 수 있습니까?
모두 감사합니다.
답변:
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.
}
그렇지 않으면 MDIContainerForm을 닫기 전에 모든 MdiChildren을 닫거나 저장되지 않은 변경 사항을 확인하는 이벤트와 같이 FormClosing 이벤트에 대해 특정 작업을 수행하기를 원했기 때문에 X 또는 CloseButton을 클릭했는지 구분할 필요가 없었습니다. 이러한 상황에서 우리는 두 버튼을 구별 할 필요가 없습니다.
ALT+로 닫으면 F4FormClosing () 이벤트가 트리거되어 닫으라는 메시지를 Form에 보냅니다. 이벤트를 취소 할 수 있습니다.
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");
}
양식이 닫힌 경우 애플리케이션을 닫을시기를 결정합니다 (애플리케이션이 특정 양식에 첨부되지 않은 경우).
private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (Application.OpenForms.Count == 0) Application.Exit();
}
내 응용 프로그램에서 항상 종료 버튼, alt + f4 또는 다른 양식 닫기 이벤트 에서 alt + x를 포착하는 Form Close 메서드를 사용합니다 . 내 모든 클래스에는 mstrClsTitle = "grmRexcel"
이 경우에 Private 문자열 로 정의 된 클래스 이름 이 있습니다.이 경우 Form Closing 메서드와 Form Closing 메서드를 호출하는 Exit 메서드가 있습니다. Form Closing Method에 대한 설명도 있습니다.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
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에서는 CloseReason
-Property 를 가져 오려면 typecast가 필요합니다.
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");
}
}
한 가지 더 언급 할 사항 : "FormClosing"이후에 발생하는 "FormClosed"함수도 있습니다. 이 기능을 사용하려면 아래와 같이 등록하십시오.
this.FormClosed += MainPage_FormClosed;
private void MainPage_FormClosing(object sender, FormClosingEventArgs e)
{
// your code after the form is closed
}