[c#] 사용자가 “X”또는 “닫기”버튼을 클릭했는지 어떻게 알 수 있습니까?

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;
            }
        }
    }


답변

X 버튼을 클릭하거나 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