Study/C, C++ (MFC, UE)

[MFC] Modaless Dialog

BlueBright 2019. 12. 24. 11:15

출처 : http://psmon.x-y.net/maniwiki/doku.php?id=mfc:%EA%B8%B0%EC%B4%88:%EB%AA%A8%EB%8B%AC%EB%A6%AC%EC%8A%A4_%EB%8C%80%ED%99%94%EC%B0%BD

 

mfc:기초:모달리스_대화창 [PSMON WIKI]

모달리스 다이얼로그 와 메모리 리크(Leaks) Cdialog 즉 다이얼로그 창은. 간단하게 메시지를 주고 받을수 있는 가장 간단한 인터페이스부터 미디어 플레이어 같은 매우 복작합 인터페이스까지 쉽게 구현할수 있는 보편적인 인터페이스 입니다. 저두 처음에는 다이얼로그 모드에서 작업을 많이 했죠. 비교적 간단하고, 간편하게 짤수 있으니까요. 그러나 저러나, 다이얼로그는 모달과 모달리스가 있고, 모달 구현은 매우 간단합니다. DoModal(), EndDial

psmon.x-y.net

 

모달리스 다이얼로그 와 메모리 리크(Leaks)
Cdialog 즉 다이얼로그 창은. 간단하게 메시지를 주고 받을수 있는 가장 간단한 인터페이스부터
미디어 플레이어 같은 매우 복작합 인터페이스까지 쉽게 구현할수 있는 보편적인 인터페이스 입니다.
저두 처음에는 다이얼로그 모드에서 작업을 많이 했죠. 
비교적 간단하고, 간편하게 짤수 있으니까요.
그러나 저러나, 다이얼로그는 모달과 모달리스가 있고,
모달 구현은 매우 간단합니다.
DoModal(), EndDialog(.);
딸랑 2가지만알면 화면에 띠울수 있죠.
그러나 모달의 경우 차일드로 생성이 될경우, 부모의 인터페이스 메커니즘을 방해하는 성향이 있기 때문에.
때로는 모달리스 다이얼로그 작성이 꼭 필요한 경우가 있죠.
중요한건 이 모달리스 다이얼로그를 모달같이 메모리 운영을하면 메모리 리크가 발생한다는 것이죠.
             if (m_pModeless == NULL)
             {
                           m_pModeless = new CAdderDialog(this);
                           //m_pModeless->DoModal();
                           if (m_pModeless->Create() == TRUE)
                                        GetDlgItem(IDOK)->EnableWindow(FALSE);
             }
             else
                           m_pModeless->SetActiveWindow();

위에서와 같이 new 연산자로 동적할당해서 쓰는 경우가 많기 때문입니다.
간단하게 Delete m_pModeless;를 하면 되지 않겠느냐 할수 있지만. 
문제는 소멸자에게 있습니다.
소멸할때 메커니즘이 순수하게 Delete할때 소멸자만 호출이 되는 것이 아니죠..
CWnd의 자식 클레스들이 그렇습니다.(윈도우 헨들이 하나씩은 있죠.2개 가진건 아직 못봤어요ㅠ.ㅑ)
원어로(CleanUp phase)는 , 즉 소멸될 때 WM_NCDESTROY라는 메시지가 윈도우에 제일 마지막으로 
전달되는 메시지 입니다. 
그리고 이 메시지를 받는 CWnd 이하 클레스는 CWnd::OnNcDestroy으로 헨들링이 되는데. 
역할은 C++ 객체에서 HWND포인터를 분리하고, Virtual Function , PostNcDestroy를 호출합니다.
중요한것은 여기서 (PostNcDestroy)에서 리소스 (메모리)해제 로직을 추가하면, 아무 문제 없이 처리할수 있다는것이죠..

void CAdderDialog::PostNcDestroy()
{
 delete this;
 CDialog::PostNcDestroy();
}
이렇게요.. 
그리고 중요한 것은 부모 윈도우는 자식 모달리스 윈도우가 정확히 언제 죽을지 모르니 이 부분을 해결해야 되는데.
여기서 부모는 자식을 강제로 Delete 시키지 않고. 걍 자식 너 스스로 죽어!! 라고 할수 있게 됩니다.
즉 부모에서는 반드시 Delete m_pModeless;를 하지 않고, 
m_pModeless = NULL; 만 하구요. 메모리 해제는 자식 윈도우의 PostNcDestroy에게 위임하게 됩니다.
그러면 언제 죽을지 모르는 자식윈도우의 처리에 골머리를 쓰지 않아도 되구요.
이에 따른 메모리 리크 문제도 해결이 되지요.. 
참 소멸 할때는 DestroyWindow()를 반드시 호출해야 합니다.
모달리스는 다이얼로그가 아니라, 하나의 폼뷰(CformView)같이 뷰(CWnd drived class)이니까요..