ShowDialog로 호출되던 폼을 Show로 바꾸면서 화면비표시를 하고싶다.


프로젝트는 C#으로 이루어져 있으며, VB6.0과 연동되어 실행되고 있었다.

구성은 아래와 같다.


문제는 해당폼이 Modal 기동된다는 점이다.
Modal 띄워놓고, 화면은 보여주면 안된다.
이것을 어떻게 해결할것인가…
나는 이번 수정을 두가지 방법으로 생각해보았다.
1. 해당폼을 생성하지않고, Load / Shown 이벤트의 내용을 그대로 메소드1에서 수행한다.
2. 해당폼을 보여주지않도록 수정하고, 그냥 진행한다.

일단, 비동기 형식으로 접근을 생각해보았다.
솔류션을 새로생성하고,폼을 두개가 되도록 배치한다.

그리고, 폼1은 다음과같이 디자인하였다.

결국 버튼2만 사용하여 해결하였지만,
여기서 중요한것은 폼의 객체는 생성하지만, 유져에게 보여주어서는 안된다는점.
그리고 Load / Shown 이벤트는 그대로 진행되어야 한다는점.
두가지의 미션이 가장 중요한 부분이다.
해당 이벤트가 불리어지는지는 어떻게 확인할까?
아래와 같이 확인해보았다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Windows.Forms;
 
namespace ApcEventControl
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }
 
        private void Form2_Load(object sender, EventArgs e)
        {
            MessageBox.Show("Form2_Load");
        }
 
        private void Form2_FormClosing(object sender, FormClosingEventArgs e)
        {
            MessageBox.Show("Form2_FormClosing");
        }
 
        private void Form2_Shown(object sender, EventArgs e)
        {
            MessageBox.Show("Form2_Shown");
        }
 
        private void Form2_FormClosed(object sender, FormClosedEventArgs e)
        {
            MessageBox.Show("Form2_FormClosed");
        }
    }
}
 
cs

폼2에 각각의 이벤트를 생성해서, 메세지박스로 표시
가장 단순하면서, 가장 알아보기 쉬운방법이다.
뭐, 로그로 표현할수도 있었지만, 이번에는 그냥 메세지박스로 표시하기로 한다.

폼1은 아래와같이 구현하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace ApcEventControl
{
    public partial class Form1 : Form
    {
        Form2 fm2;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            fm2 = new Form2();
            fm2.WindowState = FormWindowState.Minimized;
            fm2.ShowDialog();
 
            fm2.ShowInTaskbar = false;
 
            fm2.Hide();
        }
 
        private int XXX()
        {
            fm2 = new Form2();
            fm2.FormClosed += Fm2_FormClosed;
            fm2.WindowState = FormWindowState.Minimized;
            fm2.ShowInTaskbar = false;
            fm2.Show();
 
            var task = Task.Run(() =>
            {
                while (fm2 != null)
                {
                    System.Threading.Thread.Sleep(100);
                }
 
                string a = "";
 
                MessageBox.Show("1");
                MessageBox.Show("2");
                MessageBox.Show("3");
                
                if (a == string.Empty)
                {
                    return 0;
                }
                else
                {
                    return 1;
                }
            });
 
            return 9;
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            MessageBox.Show(XXX().ToString());
        }
        
        private void Fm2_FormClosed(object sender, FormClosedEventArgs e)
        {
            fm2 = null;
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            fm2 = new Form2();
            fm2.WindowState = FormWindowState.Minimized;
            fm2.Hide();
            fm2.ShowInTaskbar = false;
            fm2.Show();
 
            MessageBox.Show("1");
            MessageBox.Show("2");
            MessageBox.Show("3");
        }
        
        private void button4_Click(object sender, EventArgs e)
        {
            fm2.Close();
        }
    }
}
 
cs

버튼2에서의 처리프로세스
즉, XXX 라고 지칭해둔 함수를 통한 작업이 수행된다.
여기서 중요한것은 Form2 의 인스턴스를 Form1에 private 선언해두고, 해당 인스턴스를 감시한다는점이다.

1
2
            fm2 = new Form2();
            fm2.FormClosed += Fm2_FormClosed;
cs

formClosed 이벤트를 확장해두었다.


1
2
3
4
        private void Fm2_FormClosed(object sender, FormClosedEventArgs e)
        {
            fm2 = null;
        }
cs

내부처리는 위와같다.
form2의 private 객체를 null로 변환한다.


XXX 메소드에서 Task 를 발행해서, 해당객체가 null이 될때까지 감시하도록 하였으니,
이 객체값으로 null이 지정되는 순간, 해당 루프처리까지 탈출하면서 후반부의 처리가 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
            var task = Task.Run(() =>
            {
                while (fm2 != null)
                {
                    System.Threading.Thread.Sleep(100);
                }
 
                string a = "";
 
                MessageBox.Show("1");
                MessageBox.Show("2");
                MessageBox.Show("3");
                
                if (a == string.Empty)
                {
                    return 0;
                }
                else
                {
                    return 1;
                }
            });
cs

위의소스에서 while 부분이 탈출된다는점이다.
그리고 메세지박스로 1, 메세지박스로 2, 메세지박스로 3 이 순서대로 출력되고,
마지막으로 리턴값이 0으로 돌아오게된다.


버튼4에서 fm2 를 종료하는 처리를 하게해 두었으니, 실행순서는 아래와같이 되겠다.

1. 샘플 프로그램을 실행한다.

2. 버튼2를 클릭한다.

Form2_Load가 출력

Form2_Shown가 출력

9가출력 <- Task.Run의 결과는 돌아오지 않았으므로, 후속처리는 그대로 실행되었기에 9가 돌아온다.

그리고, 여기서 버튼4를 누른순간, 아래와 같은 결과가 출력된다.

Form2_FormClosing가 출력

Form2_FormClosed가 출력

1 이 출력

2 가 출력

3 이 출력

- 끝 -


위의 소스를 이용해서 ShowDialog 로 되어있던 폼을 Show 로 불러오면서, 해당결과를 그대로 얻기위한 방법을 연구해보았다.

혹시나 같은 문제에 봉착한 사람들이 있다면, 조그마한 도움이라도 되고자 이 글을 남겨둔다.


소스는 아래의 링크를 참고하세요.

https://github.com/sungmanko/ApcEventControl

+ Recent posts