본문 바로가기
Windows/MFC 강좌 & Tips

MFC Dialog 호출 시 실행되는 메세지 순서

by 미티치 2017. 1. 3.
  1. DoModal()
  2. PreSubclassWindow()
  3. OnNcCreate()
  4. OnNcCalcSize()
  5. OnCreate()
  6. OnSize()
  7. OnMove()
  8. OnSetFont()
  9. OnInitDialog()
  10. OnWindowPosChanging()
  11. OnMove()
  12. OnWindowPosChanged()
  13. OnWindowPosChanging()
  14. OnNcActivate()
  15. OnActivate()
  16. OnShowWindow()
  17. OnWindowPosChanging()
  18. OnNcPaint()
  19. OnEraseBkgnd()
  20. OnChildNotify()
  21. OnCtlColor()
  22. OnWindowPosChanged()
  23. OnPaint()
  24. OnCtlColor()
  25. OnCtlColor()
  26. OnNcHitTest()
  27. OnSetCursor()
  28. PreTranslateMessage()
  29. OnMouseMove()
  30. OnNcHitTest()
  31. OnSetCursor()
  32. PreTranslateMessage() 

 

 

MFC 프로젝트를 Dialog 기반으로 생성하면 기본적으로 MyApp.cpp 와 MyAppDlg.cpp가 생성된다.

MyApp.cpp 는 어플리케이션 클래스, MyAppDlg.cpp는 화면에 보이는 다이얼로그 클래스이다.

MyAppDlg.cpp 의 InitInstance() 함수가 main함수라고 생각하면 되는데, 이 함수에서 다이얼로그 객체 CMyAppDlg dlg;를 생성하고 dlg.DoModal() 함수로 다이얼로그를 생성하여 보여주고 있다. 위의 순서는 이렇게 다이얼로그를 객체로 선언해서 DoModal 함수로 다이얼로그를 화면에 보여주는 작업을 동작시켰을 때 실행되는 함수의 순서이다.

 

MFC

 

이 순서가 왜 중요하냐고?

윈도우에서 다이얼로그 창을 하나 띄우기 위해서는 내부적으로 저 모든 함수들이 호출된다.
우리가 다이얼로그 기반 MFC 프로젝트 하나 만들어서 다이얼로그 클래스의 DoModal 함수 호출해주면 다이얼로그가 뿅!하고 그려지는 것 같지만, 실제로는 이 다이얼로그 클래스에 override 해놓지 않은 저 많은 함수들이 순서대로 호출되면서 윈도우 (여기서 윈도우는 OS 윈도우가 아니라 '다이얼로그 창'을 의미합니다.) 를 그려주는 것 입니다.

 

쉽게 예를 들어보겠습니다.
다이얼로그 배경색을 지우려면 배경색을 지우려는 윈도우의 OnEraseBkgnd 함수를 오버라이딩해서 현재 윈도우의 배경색을 바꾸는 작업을 할 수 있습니다. 이런식으로 말이죠.

BOOL MainWnd::OnEraseBkgnd(CDC* pDC)
{
    CRect r;
    GetClientRect(r);

    // 배경색을 파란색으로 변경한다. 흰색은 RGB(255,255,255)
    pDC->FillSolidRect(r, RGB(0,0,255));
    
    return TRUE;
}

 

 

 

좀 더 예를 들어서 MyAppDlg를 보여주기 전에 로그인 다이얼로그를 먼저 보여주고 싶다고 가정해봅시다.

 

(1) 첫번째 방법으로는 MyApp.cpp 의 InitInstance()에서 CMyAppDlg객체를 생성하지 않고 개발자가 새로 만든 로그인 다이얼로그 CLoginDlg 객체를 생성해서 DoModal() 함수를 실행시키는 방법이 있습니다.

 

(2) 두번째 방법으로는 다른 소스는 그대로 두고, MyApp.cpp의 InitInstance()에서 dlg.DoModal()해서 실행되는 위의 많은 함수들 중에 OnInitDialog()함수가 보일 것이다. OnInitDialog()는 MyAppDlg.cpp에서 이 다이얼로그 객체를 생성할 때 초기화해주는 함수인데, 여기에서 로그인 다이얼로그 CLoginDlg 객체를 생성해주면된다. 그러면 내부적으로는 기존의 프로젝트를 처음 생성했을 때의 소스코드에서 실행 순서가 다음과 같다.

 

 

 

MyApp.cpp 에서 InitInstance() 가 실행

=> InitInstance() : CMyAppDlg 객체 생성, DoModal() 함수 실행

=> 위의 함수들 순서대로 실행... CMyAppDlg의 OnInitDialog() 함수 실행

=> OnInitDialog() : 로그인 다이얼로그 CLoginDialog  객체 생성, DoModal() 함수 실행

=> CLoginDlg 도 CMyAppDlg과 마찬가지로 다이얼로그 생성을 위한 함수들 실행 

 

이러한 순서로 진행되어 마침내 우리가 dlg.DoModal(); 하나로 띄운 다이얼로그가 화면에 뜨는 것입니다.

 

요약하자면, CMyAppDlg 객체가 생성되어 화면에 보여지는 함수들이 순서대로 실행되어 모든 함수들의 실행이 다 마치기 전에 CLoginDlg 객체를 생성하여 DoModal() 로 띄워주기 때문에 MyAppDlg를 보여주기 전에 로그인 다이얼로그를 먼저 보여줄 수 있는 것 입니다.