1. Modal / Transient , 의 개념
어플리케이션의 코드 실행 중간에, 사용자의 피드백(interaction)을 유도하는 대화상자를 띄워 사용자가 선택을 하고 대화상자가 닫힐 때까지, 코드 흐름이 멈춰 있도록 할 수 있는 기능을 말합니다.
이런 기능은 특정 상황에서 매우 유용하고, 편리한 코드 작성을 할 수 있도록 도와줍니다.
예를 들면, 아래와 같은 플로우(flow)를 작성하고 싶다고 가정 합니다.
1. 프로그램 실행
2. copy button 선택
3. copy 할 것인지 묻는 message box 를 띄움 (Do you wanna start copy?)
4. 사용자가 OK를 누르면, copy를 실행함.
Platform을 개발하면서 Windows 에서 제공하는 Modal 과 같은 기능을 어떤 방식으로 지원할까에 대해서 여러차례 고민 해봤습니다.
실제로 기능 자체의 구현은 어려운 것이 아니나, 예외 상황에 대한 처리가 항상 문제가 되더군요.
가장 기본적인 예외 상황은 UI 상 modal 과 Code상으로 Modal 상태에서 parent window가 종료된다거나, modal을 실행한 주체가 종료된다면, messagebox를 띄워서 기다리고 있는 코드의 다음 라인들은 어떻게 처리되어야 하는 가 입니다.
이 외에도 여러가지 예외상황을 만들때가 많습니다.이는 마치, multi-thread programming 과 비슷한 양상을 나타냅니다.
그래서 아래 코드의 pWind->DoModal()의 앞 과 뒤에서 내부 변수나 외부 변수들 그리고 객체의 상태가 달라질 수 있다는 의미 입니다.
즉 MyTestWindow 가 삭제되었거나 그 내부변수들의 정보가 바뀌어있을 수도 있다는 의미죠.
void MyTestWindow::KeyPressed() {
HFile hDBCopyLog = CreateFiile("Log.txt");
pWind = CreateModalMessageBox("Do you wanna start copy?");
returnValue = pWind->DoModal(); //<-- -3. Modal window가 뜨고 코드상으로 아래로 진행되지 않고 멈춰 있는 부분
if (returnValue == OK) {
CopyFile(pathDest, pathSrc);
sprintft(testBuf, "handle=%d", this->m_hWin); //< --B.this와 this->m_hWin 이 정상적이다라는 보장이 없음
WriteFile( hDBCopyLog, testBuf);
CloseFile(hDBCopyLog);
return TRUE;
}
만약 위와 같은 코드가 있다고 한다면, DoModal() 내부에서 분명 event 처리를 할수 있는 event loop 이 구현 되어있을 것입니다.
이 이벤트 loop에서 pWind를 가지고 있는 application 이나 window를 종료 했다면 User 입력을 기대하고 작성했던 OK일때 처리 부분이 수행이 안되게 될 수도 있습니다.
또 더 심각하게 본다면 this 나 m_hWin 도 정상적으로 살아있을것이라는 보장도 못하게 됩니다.
2. Modal 기능 구현
DoModal 기능은 의외로 간단한데요.
아래와 같이 platform에서 제공하는 event를 처리loop 코드를 참조하여 event queue 처리 로직을 loop로 제공하면 됩니다.
result MessageBox::DoModal() {
while (!bEixt) {
ReceiveMessage(&msg);
ProcessMsg(&msg);
}
}
WIN32 기준으로 봤을때...
Window들을 모두 종료 시키고 어플리케이션을 빠져 나가야 하는 경우라고 가정한다면,
WM_QUIT 메세지를 받게 되면, WM_QUIT에 의해 modal window가 삭제 될것 입니다. 그러나 parent window는 삭제가 되지 않기 때문에, WM_QUIT을 다시 한번 event queue에 넣어야 합니다.
이렇게 하면 Modal loop을 빠져 나가고,WM_QUIT 메세지를 재 생성해서(PostQuitMessage) 바깥에 있는 main loop에서 정리할 수 있도록 해줘야 합니다.
result MessageBox::DoModal() {
while (!bEixt) {
ReceiveMessage(&msg);
if (msg.type == WM_QUIT) {
bExit = TRUE;
PostMessageFront(&msg);
bException = TRUE;
}
if (!bException)
ProcessMsg(&msg);
}
}
platform 을 개발하는 입장에서 Modal을 구현하여 제공 해야 한다면 위와 비슷한 방법으로 application 종료 event를 받으면 우선 이 이벤트를 부모 window부터 처리하는 것이 아니라 modal window에서 먼저 처리를 하고 , modal window를 종료 시키고, 같은 event를 다시 event queue에 넣어서 modal event loop을 빠져 나간 다음에 main loop(또는 상위 event loop) 에서 처리할 수 있도록 합니다.
modal이 한개가 아니라 중첩, 3중첩 되어 있을 가능 성도 있기 때문입니다.
1. 프로그램 실행
2. delete button 선택
3. delete 할 것인지 묻는 message box 를 띄움 (Do you wanna delete this file?)
4. 진짜로 지울 것인지 묻는 message box 를 띄움 (리얼리?)
5 파일을 지움
'개발 Note > it 이야기' 카테고리의 다른 글
Design pattern -강의 메모 (0) | 2009.01.20 |
---|---|
Modal의 구현 형태 (0) | 2009.01.12 |
C++ 상에서 발생하는 name mangling 에 관한 내용 (17) | 2009.01.04 |
Feature modeling - 아직 정리되지 않은 주제. (0) | 2009.01.04 |
Refactoring (0) | 2009.01.04 |