MFC

SDI 기반 MFC 응용 프로그램의 종료과정 - 순차적 정리 자료...읽어볼만하다.

디버그정 2008. 9. 3. 20:36
1.5.3 SDI 기반 MFC 응용 프로그램의 종료 MFC

2008/06/26 21:49

복사 http://blog.naver.com/ndkarn/120053354648

 메시지 루프가 끝나는 떄가 바로 윈도우 응용 프로그램이 종료되는 시점이라고 했었다. 따라서 응용 프로그램이 종료되는 과정의 첫 번째는 WN_CLOSE 메시지를 받고, 그 메시지 핸들러가 호출되는 시점부터 시작한다. 내용을 하나씩 살펴보자.


1] CMainFrame::OnClose() - Call


 닫기 버튼을 눌르거나 혹은 [Alt + F4] 키를 입력하면 WM_CLOSE 메시지가 발생한다. OnClose() 함수는 WM_CLOSE 메시지에 대한 핸들러이다. OnClose() 함수가 리턴하기 전에 내부적으로 아래의 함수들이 연이어 호출되는데, 응용 프로그램이 시작될 때와 동일한 부분들이 일부있다. 이들에 대한 설명은 따로 하지 않겠다.

 CMainFrame::OnShowWindow() - Call

 CMainFrame::OnShoWindow() - Return

 CMainFrame::OnActivate() - Call

 CMainFrame::OnActivate() - Return

 CMainFrame::OnActivateApp() - Call

 CMainFrame::OnActivateApp() - Return


 아무튼 OnClose() 함수가 호출될 때 코딩할 만한 것들은 자원의 반납이나, 차일드 윈도우의 내용을 저장하는 정도이다. 가급적 사용자 인터페이스와 관련된 잡다한 처리들을 하는 것이 괜찮지 않나 생각한다. 예를들어 윈도우의 현재 위치와 같은것들ㅇ르 저장하는 일을 할 수 있을 것이다.


 그리고 중요한 것은 최상위 윈도우인 프레임 윈도우에 붙어 있는 차일드 윈도우들은 이 시점에서 하나씩 파괴된다. 그리고 모든 차일드 윈도우가 다 파괴되고 난 후에 메인 프레임 윈도우가 파괴된다.


[1] CMainFrame::DestroyWindow() - Call


 OnClose() 함수는 실제로 윈도우를 파괴하기 위해서 DestroyWindow() 함수를 호출하게 되는데, 이 함수가 호출되고 나면 윈도우가 파괴되므로 그 전에 차일드 윈도우를 모두 파괴하여야 한다.



 이를 알리기 위해서 내부적으로 WM_DESTROY와 WM_NCDESTROY 메시지가 연이어 전달된다. WM_DESTROY는 윈도우 전체가 파괴되는 신호라면, WM_NCDESTROY는 프레임의 테두리가 파괴되는 신호이다.


CMainFrame::OnDestroy() - Call, Return

 프레임 윈도우는 DestroyWindow() 함수가 보낸 WM_DESTROY 메시지를 받게 되므로 이에 대한 메시지 핸들러가 호출된다. OnClose()나 OnDestroy() 함수에 코딩하는 내용은 어쩌면 좀 비슷하다. 결과적으로 같은 내용을 두 함수 중 아무데나 코딩해도 큰 지장은 없을 것이다.


중요한 것은 OnDestroy() 함수에서 클라이언트 뷰와 같은 차일드 윈도우의 파괴가 시작된다. 역시 차일드 윈도우에 WM_DESTROY 메시지를 보내서 파괴되어야 함을 알린다.


●CSDI_SequenceView::OnDestroy() - Call, Return

 WM_DESTROY 메시지를 받은 클라이언트 뷰 윈도우 객체는 자신이파괴되기에 앞서서 OnDestroy() 메시지 핸들러를 호출한다.

 

●CSDI_SequenceView::PostNcDestroy() - Call

 PostNcDestroy() 함수는 비클라이언트(Non-client) 영역을 파괴하게 되는데, 이 함수에서 재미있는 사실은 "delete this;"가 허용된다는 것이다. 이것에 대한 예제도 나중에 보게 될 것이니 지금은 그렇다는 사실만 알아두면 되겠다.

 필자는 이 함수를 오버라이드시켜서 'delete this;'를 코딩할 것이 아니라면, 이 함수를 오버라이드 시킨 적이 없다. 여기 말고도 마무리를 위한 코드가 들어갈 곳은 많다.

 

●CSDI_SequenceView::~CSDI_SequenceView()

 클라이언트 뷰의 소멸자가 호출되고 이제 윈도우들이 연이어 파괴된다.

 

●CSDI_SequenceView::PostNcDestroy() - Return

 이 함수가 최종 리턴함으로서 클라이언트 뷰는 완전히 파괴되었다.


CMinaFrame::OnNcDestroy() - Call

 차일드 윈도우인 클라이언트 뷰가 파괴도리 때와 마찬가지의 순서가 앞으로 진행된다. OnNcDestroy() 함수는 WM_NCDESTROY 메시지에 대한 핸들러로 비클라이언트 영역이 파괴되는 시작을 의미한다.


 이 함수가 호출된 후 앞서 클라이언트 뷰에서 본 것과 같은 PostNcDestroy() 함수가 호출된다. 물론 결과 역시 동일하다.

 CMainFrame::PostNcDestroy() - Call

 CMainFrame::~CMainFrame()

 CMainFrame::PostNcDestroy() - Return


CMainFrame::OnNcDestroy() - Return

 PostNcDestroy() 함수의 리턴 이후 앞서 함수들이 차례로 리턴하게 되고 결국 메인 윈도우는 파괴된다.

[2] CMainFrame::DestroyWindow() - Return

 응용 프로그램의 최상위 부모 윈도우인 메인 프레임 윈도우가 완전히 파괴되었다.


[3] CSDI_SequenceDoc::~CSDI_SequenceDoc()

 화면상에 나타나는 사용자 인터페이스, 즉 윈도우 객체들이 모두 파괴된 후 관련된 도큐먼트 객체가 소멸된다.


2] CMainFrame::OnClose() - Return

 클라이언트 뷰, 도큐먼트 객체뿐만 아니라, 자신도 이미 파괴 되었다. 이제 남은 것은 응용 프로그램이 사용한 자원들을 반납하는 일 뿐이다.


3] CSDI_SequenceApp::ExitInstance()

 모든 객체들이 소멸한 가운데, 응용 프로그램의 최종 종료에 앞서서 마지막으로 호출되는 함수이다. 따라서 이 함수에서는 응용 프로그램의 설정을 저장한다거나, 중복 실행 방지를 위해 획득했던 시스템 리소스를 반납하거나, 메모리를 해제하는 등 최종 마무리 작업을 해야한다.


4] ### CSDI_SequenceApp::Run() - Return ###

 이제 남은 것은 메시지 루프를 가진 응용 프로그램 객체뿐이다. Run() 함수가 리턴한다는 것은 메시지 루프의 종료를 의미하므로 프로그램이 최종 종료되는 것이다. 이 과정에서 우리 눈에 보이지 않는 코드가 실행되는데, MFC 응용 프로그램이 시작할 때 MFC를 초기화하는 역할을 수행한것(AfxWinInit)과 반대로 AfxWinTerm()이라는 함수가 수행되어 초기화했던 MFC 라이브러리를 해제(release)한다. 이 과정에서 마지막 객체인 응용 프로구램 객체를 소멸하고 프로그램은 환전히 종료된다.


 지금까지 MFC를 이용하여 작성된 응용 프로그램의 시작, 동작, 종료 과정을 살펴보았다. 그 과정에서 메시지 큐의 구조와 동작을 함께 알아보았다. 그리고 간단하게 어떤 코드들을 넣으면 좋을지도 공부했다. 하지만 제대로 프로그램을 제작을 한 것이 아니다보니, 아직은 감이 잘 오지 않을 것이다.


 이 부족한 부분은 직접 코딩을 해보고 프로그램을 개발해 봐야 채울 수 있을 것이다. 원이릐 이해가 끝났으므로, 이제는 본격적인 윈ㄷ우 프로그래밍을 시작할 수 있을 것으로 생각한다. 혹시라도 이해되지 않는 부분이 있다면 다시 한번 읽어보기 바란다.