본문으로 바로가기

C# Form Auto Closing DialogBox 만들기

category 개발언어/C# 2017. 10. 28. 23:54
C# 일정 시간지난 후 종료방법, Dialog Box 자동 종료하기!! C# 에서는 Dialog와 Form을 별도로 구분하지 않는다, 단지 Foem을 form.ShowDialog()를 호출하는 것으로 Dialog가 된다(엄밀히 말하면 Modal Dialog가 된다. Modal Dialog가 자동 졸료 되도록 하려면 어떻게 구현 하는것이 좋을까?

 위 그림의 Dialog는 프로세스를 제어하기 위한 목적으로 만들어진 Dialog의 일 부분이다, 일정 시간이 지나면 MessageBox(Dialog)가 자동으로 OK 가 눌러진 효과를 내도록 만들었다, 즉 자동으로 Dialog가 Close 된다. 물론 사용자가 임의로  동작을 실행하게 되면, 사용자가 조작한데로 동작 하지만  일정 시간이 겨과 하면 OK Button이 동작 하도록 만들어 졌다. Dialog를 호출하는 방법은 아래 예와 같이 매우 간단하다.
 RestartDlg dlg = new RestartDlg();
 dlg.Text = FileName;
 if (DialogResult.OK == dlg.ShowDialog())//this.DialogResult = DialogResult.OK;
 {
    delay = dlg.DelayMinute;
    b_launch = true;
 }
 else b_launch = false;
Dialog를 호출하는 예제

Dialog OK는 Form내에서 OK버튼의 이벤트를 받아서 this.DialogResult = DialogResult.OK; 를 처리하는 것으로 Dialog의 Return 값을 받을 수 있게 된다. Dialog를 자동으로 종료 하기 위해서는 어떻게 해야 할 까?
소스보기 1. 먼저 modal 상태에서 동작 하도록 Form의 생성자에서 Thread를 만들어 실행 시칸다. thread 내에서 시간을 계산하여 일정 시간이 되면 Form응 닫도록 처리하면 된다. 아주 간단하다.
 
public RestartDlg()
{
   InitializeComponent();       
   hThread = new Thread(delegate () { ThreadFunction(); });
   hThread.Priority = ThreadPriority.Lowest;
   hThread.IsBackground = true;
   hThread.Start();
}
void ThreadFunction()
{
   TimeSpan spn = DateTime.Now - tstart;
   while (term > spn.TotalSeconds)
   {                  
       ChangeBtnText(String.Format("확인({0:d})", term - spn.Seconds));
       Thread.Sleep(1000);
       spn = DateTime.Now - tstart;
    }
    /// 스레드가 종료 되면 폼을 닫음
    Invoke(new FnClose(OnClose), null);
}

 그런데 여기서 하나 싱경쓰야 하는 부분은 Invoke(new FnClose(OnClose), null);라고 처리된 부분이다. C#크로스 스레드 작업이 잘못 되었습니다.라는 오류를 해소하기 위해 delegate,Invoke 사용하고 있다는 점에 유의하자.
 
private void OnClose()
{
    if (this.InvokeRequired) Invoke(new FnClose(OnClose), null);
    else
    {
         this.DialogResult = DialogResult.OK;
         this.Close();
    }
}
아래의 예는 자동으로 종료되는 Dialog에 대한 전체 소스이다.
소스 전체 보기
 
using System;
using System.Threading;
using System.Windows.Forms;

namespace ProcessLauncher
{
    public partial class RestartDlg : Form
    {
        Thread hThread = null;
        DateTime tstart = DateTime.Now;
        int term = 60;
        delegate void FnShowMsg(String txt);
        delegate void FnClose();
        public long DelayMinute
        {
            get { return (long)Minute.Value; }
        }
        public RestartDlg()
        {
            InitializeComponent();       
            hThread = new Thread(delegate () { ThreadFunction(); });
            hThread.Priority = ThreadPriority.Lowest;
            hThread.IsBackground = true;
            hThread.Start();
        }
        private void OK_Click(object sender, EventArgs e)
        {
            hThread.Abort();
            this.DialogResult = DialogResult.OK;
            this.Close();
        }

        private void Cancel_Click(object sender, EventArgs e)
        {
            hThread.Abort();
            this.DialogResult = DialogResult.Abort;
            this.Close();
        }            
        private void ChangeBtnText(String txt)
        {
            if (OK.InvokeRequired)           
                Invoke(new FnShowMsg(ChangeBtnText), new Object[] { txt });        
            else   OK.Text = txt;                         
        }
        private void OnClose()
        {
            if (this.InvokeRequired) Invoke(new FnClose(OnClose), null);
            else
            {
                 this.DialogResult = DialogResult.OK;
                this.Close();
                //hThread.Abort();
            }
        }
        void ThreadFunction()
        {
           TimeSpan spn = DateTime.Now - tstart;
           while (term > spn.TotalSeconds)
           {                  
               ChangeBtnText(String.Format("확인({0:d})", term - spn.Seconds));
               Thread.Sleep(1000);
                spn = DateTime.Now - tstart;
            }
            /// 스레드가 종료 되면 폼을 닫음
            Invoke(new FnClose(OnClose), null);
        }
        
    }
}