웬디의 기묘한 이야기

글 작성자: WENDYS
반응형

MFC Dialog 종료 소멸 순서 정리

최근 MFC 개발을 하다보니 소멸 순서에 대해 확인할 필요가 있어져서 확인 후 정리합니다.

 

모든 객체는 생성을 했으면 소멸을 해주어야하는게 당연합니다. 포인터의 경우엔 스마트 포인터를 이용하고, Lock Object는 RAII 패턴을 통해 Auto Lock을 사용하게 됩니다.

 

Dialog based 로 개발을 하다보면 Thread를 통해 UI Control에 접근을 하여 특정 상황에 UI를 변경하는 작업을 하게 되는데, 이때 해당 Thread를 소멸자에서 제거하게 되면 UI Control.m_hwnd 가 nullptr이 되어 매번 여러 상황에서 체크를 해야 하는 상황이 발생할 수 있습니다.

그렇기 때문에 Dialog::~Dialog 소멸자가 아닌 WIndow Control이 소멸되기 전에 Thread를 먼저 Stop 처리해주어야 Thread에서 UI Control시 문제가 발생하지 않고 정상 처리할 수 있게 됩니다.

MFC Project 생성

 

//
// X 버튼을 눌러서 다이얼로그를 종료한경우
//

OnSysCommand start
    OnClose
OnSysCommand end
DestroyWindow start
    OnDestroy
DestroyWindow end
OnNcDestroy start
    PostNcDestroy
OnNcDestroy end


//
// EndDialog, OnOk, OnCance 등을 이용하여 다이얼로그를 종료한경우
//

DestroyWindow start
    OnDestroy
DestroyWindow end
OnNcDestroy start
    PostNcDestroy
OnNcDestroy end

항상 위처럼 동작할것같지만 OnSysCommand -> OnClose 동작이 일어나지 않는경우도 있습니다.

다이얼로그를 종료할 때 X 버튼을 누른경우 OnSysCommand에 SC_CLOSE가 발생하게되며, 내부적으로 WM_CLOSE (OnClose)가 발생하게되지만, EndDialog, OnOK, OnCancel 등을 이용하여 다이얼로그가 종료된경우엔 OnClose 이벤트가 발생하지 않고 바로 DestroyWindow가 호출되어 다이얼로그가 파괴되게 됩니다.

 

OnClose

MFC Application을 종료시키는 시점에 호출되게 됩니다. X 버튼 또는 WM_CLOSE 증 실제 종료할때만 호출되며 EndDialog, OnOk, OnCancel 등 다른방식으로 다이얼로그가 종료되는경우엔 호출되지 않습니다.
 

DestroyWindow

MFC 다이얼로그가 종료되는 모든 시점에 호출됩니다. 단, Modeless Dialog는 소멸시 직접 DestroyWindow를 호출해주어야 합니다.

  • CWnd 내부에 있는 윈도우를 Destroy 합니다.
  • 윈도우를 해제하기 위해 윈도우에 여러가지 Message를 전달합니다.
  • 윈도우 메뉴 제거
  • Message Queue를 비운다.
  • Timer를 비운다.
  • Clipboard의 Owner를 제거한다.
  • Destory CWnd의 Clipboard Chain을 제거
  • 다만 아직 CWnd 객체 자체는 아직 Destroy 되지 않습니다.
BOOL CmfctestDlg::DestroyWindow()
{
    // UI 사용 Thread Stop

    return CDialogEx::DestroyWindow();
}

DestroyWindow 호출 시점이 다음과 같기때문에 먼저 window handle 등을 사용하는 Thread 등을 모두 해당 시점에 해제할 수 있습니다.

반응형