1 / 48

MFC 의 메시지 처리

MFC 의 메시지 처리. 1. 4. 메시지 개요. Message 처리단계. 2. 5. Message Map 처리 기본개념. 메시지 매크로의 확장. 3. Message Map 의 구성. 목 차. 메시지 구조 메시지 종류. DECLARE_MESSAGE_MAP BEGIN_MESSAGE_MAP END_MESSAGE_MAP. 6. 사용자 정의 메시지. 8. 메시지 처리 흐름. 7. 메시지 처리방식의 종류. 목 차. 큐를 경유하는 방식

meena
Download Presentation

MFC 의 메시지 처리

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. MFC의 메시지 처리

  2. 1 4 메시지 개요 Message 처리단계 2 5 Message Map 처리 기본개념 메시지 매크로의 확장 3 Message Map의 구성 목 차 • 메시지 구조 • 메시지 종류 • DECLARE_MESSAGE_MAP • BEGIN_MESSAGE_MAP • END_MESSAGE_MAP Univ of Incheon, 고급프로그래밍

  3. 6 사용자 정의 메시지 8 메시지 처리 흐름 7 메시지 처리방식의 종류 목 차 • 큐를 경유하는 방식 • 큐를 경유하지 않는 방식 • Message Loop • Window Procedure • DefWindowProc Univ of Incheon, 고급프로그래밍

  4. 메시지 개요(1/7) • 메시지 구조 • 메시지 : 프로그램에 변화가 생겼을 때 Windows가 프로그램에게 알리는 정보 • 메시지는 MSG로 정의되는 구조체 (윈도우 핸들, 메시지 식별 번호, 추가 정보, 시간, 커서 위치 등 포함) typedef struct tagMSG { HWND hwnd; // 메시지가 발생한 윈도우 핸들 UINT message; // message id WPARAM wParam; // 추가 정보 LPARAM lParam; // 추가 정보 DWORD time; // 메시지 발생 시간 POINT pt; // 커서 위치 } MSG; <WINUSER.H> <WINDEF.H> typedef struct tagPOINT { LONG x; // 화면 좌표 LONG y; // 화면 좌표 } POINT; Univ of Incheon, 고급프로그래밍

  5. 응용 프로그램 응용 프로그램 응용 프로그램 메시지 개요(2/7) ev 메시지 큐 Device Driver Device Driver Device Driver Windows OS 입력 장치 출력 장치 사용자 입력  입력용 Device Driver(키보드, 마우스, 조이스틱)  메시지 큐  Windows 운영체제  응용 프로그램  출력용 Device Driver(모니터, 프린터, 디스크)  출력 Univ of Incheon, 고급프로그래밍

  6. 메시지 개요(3/7) • 메시지 종류 • 윈도우 메시지(Windows Message) • “WM_”으로 시작하는 메시지(WM_COMMAND 제외) • 매개 변수를 가지고 있어 어떻게 처리할 것인지 결정 • 윈도우 관리메시지, 초기화 메시지, 입력메시지 • 명령 경로 배정없이 해당 윈도우에 직접 전달 • 컨트롤 통지 메시지(Control Notification Message) • Button, Combo Box와 같은 제어객체나 자식윈도우에서 부모 윈도우로 보내는 메시지 • 명령 메시지(Command Message) • 메뉴, 툴바, 액셀레이터 키와 같은 사용자 인터페이스 객체로부터 발생되는 WM_COMMAND 메시지 • 도큐먼트, 도큐먼트 템플릿, 뷰, 다른 Application 객체에 의해 발생 가능 • 사용자 정의 메시지 • SendMessage()와 PostMessage()를 사용하여 메지시 전달 Univ of Incheon, 고급프로그래밍

  7. 메시지 유형 발생상황 메시지 핸들러 함수 WM_CREATE 윈도우가 생성될 때 OnCreate() WM_ACTIVE 윈도우가 활성화 될 때 OnActive() WM_PAINT 윈도우가 다시 그려질 때 OnPaint() WM_SIZE 윈도우 크기가 변경될 때 OnSize() WM_MOVE 윈도가 움직일 때 OnMove() WM_TIMER 설정된 타이머 시간이 됐을 때 OnTimer() WM_DESTROY 윈도우가 종료될 때 OnDestroy() WM_MOUSEMOVE 마우스를 이동 OnMouseMove() WM_LBUTTONDBlCLK 왼쪽 마우스 버튼을 더블 클릭 OnLButtonDblclk() WM_LBUTTONDOWN 왼쪽 마우스 버튼을 누름 OnLButtonDown() WM_LBUTTONUP 왼쪽 마우스 버튼을 놓음 OnLButtonUp() WM_RBUTTONDBlCLK 오른쪽 마우스 버튼을 더블 클릭 OnRButtonDblclk() WM_RBUTTONDOWN 오른쪽 마우스 버튼을 누름 OnRButtonDown() WM_RBUTTONUP 오른쪽 마우스 버튼을 놓음 OnRButtonUp() 메시지 개요(4/7) • Windows Message Univ of Incheon, 고급프로그래밍

  8. 메시지 개요(5/7) • 명령메시지(WM_COMMAND) • 메뉴의선택, 키보드 가속기 사용과 같은 사용자의 행동에 의해 발생된 메시지 • 어떤 메뉴가 눌렸는지 구별하기 위해 메뉴의 ID가 윈도우 메시지의 WPARAM을 통해 전달 • ON_COMMAND 메시지 맵 항목들을 가진 여러 응용 프로그램 구성 요소에 의해 처리 <프로젝트명.cpp> BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_COMMAND (ID_FILE_NEW, OnFileNew) ON_COMMAND (ID_FILE_OPEN, OnFileOpen) ON_COMMAND (ID_FILE_SAVE, OnFileSave) ON_COMMAND (ID_FILE_SAVE_AS, OnFileSaveAs) ON_COMMAND (ID_FILE_EXIT, OnFileExit) END_MESSAGE_MAP() void CMainWindow::OnFileExit () { PostMessage (WM_CLOSE, 0, 0); } Univ of Incheon, 고급프로그래밍

  9. 메시지 개요(6/7) • 만일 OnCommand라는 메시지 핸들러에서 모든 메시지를 처리를 하면 할 일이 너무 많아짐 • 일반적인 윈도우 메시지 처리는 CWnd 클래스를 상속받은 클래스들에서 처리 ( CWnd 클래스 상위 클래스는 윈도우 메시지 처리부분이 없음 ) • WM_COMMAND 메시지는 CCmdTarget 클래스에 구현 • CCmdTarget 클래스 하위 클래스는 모두 WM_COMMAND메시지 구현 가능 • 사용자가 메뉴 항목을 선택하여 프로그램에 명령을 내리면 WM_COMMAND 메시지가 모든 AFX 클래스에 전달 Univ of Incheon, 고급프로그래밍

  10. CView 파생 클래스 CDocument 파생 클래스 CFrameWnd 파생 클래스 CWinApp 파생 클래스 메시지 개요(7/7) • WM_COMMAND 메시지 전달순서 Univ of Incheon, 고급프로그래밍

  11. Message Map 처리 기본개념(1/5) • 메시지 맵이란 윈도우 메시지를 받아야 할 클래스가 가지는 정적 구조체 배열 • 이 정적 구조체 배열은 처리할 메시지와 메시지에 대응하는 멤버함수에 대한 포인터를 가짐 • MFC는메시지맵의코드자동화를 위해 매크로를 사용 • DECLARE_MESSAGE_MAP • BEGIN_MESSAGE_MAP, END_MESSAGE_MAP • ON_WM_LBUTTONDOWN() Univ of Incheon, 고급프로그래밍

  12. Message Map 처리 기본개념(2/5) • SDK기반에서는메시지가있는경우에만윈도우 프로시저를 호출 • 처리할 메시지가 없다면 CPU는 블록 상태가 되어 다른 응용프로그램이 CPU를 할당받아 일을 처리 • MFC의 메시지루프는GetMessage()대신PeekMessage()사용 • PeekMessage()는 블록상태가 되지 않음 • 처리할 메시지가 없는 시간(Idle Time)에 가상함수 OnIdle()이 호출됨 While ( GetMessage ( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage ( &msg ); } Univ of Incheon, 고급프로그래밍

  13. Message Map 처리 기본개념(3/5) SDK로 표현 LESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch (iMsg) { case WM_CREATE : //윈도가 만들어질 때 모듈 break; case WM_PAINT : //화면 출력 모듈 break; case WM_KEYDOWN : //키 입력시 처리 모듈 break; case WM_CHAR: //문자 입력시 처리 모듈 break; case WM_DESTROY: //윈도가 없어질 때 모듈 break; } } MFC로 표현 해당하는 모듈을 모두 switch문으로 설정 BEGIN_MESSAGE_MAP(CMyWnd, CWnd) ON_WM_CREATE( ) ON_WM_PAINT( ) ON_WM_KEYDOWN( ) ON_WM_CHAR( ) ON_WM_DESTROY( ) END_MESSAGE_MAP( ) Univ of Incheon, 고급프로그래밍

  14. Message Map 처리 기본개념(4/5) • Message Map의 이해 • API 프로그램은 윈도우의 메시지를 처리할 때 윈도우 프로시저내에 중첩된 if문과 switch 문을 사용, 각각의 메시지에 대한 처리를 하는 이벤트 핸들러 코드를 작성 • MFC 에서는 MESSAGE_MAP 매커니즘을 사용 따라서 if문이나 switch 문이 없다. • MESSAGE_MAP의 메커니즘은 메시지와 이벤트 핸들러를 일대일로 연결시켜주는 테이블의 역할 수행 • 파생 클래스의 메시지 핸들러 함수를 여기에 등록하면 기반 클래스의 함수를 무시하고, 파생 클래스의 함수를 호출하는 매크로 Univ of Incheon, 고급프로그래밍

  15. Message Map 처리 기본개념(5/5) • MFC 메시지 맵의 핵심 • 구조체는 윈도우 MESSAGE MAP에 대응하는 멤버 함수의 시작주소를 가짐 • 코드의 자동화를 위하여 메시지 맵에 메시지와 메시지 핸들러 함수를 묶는 메시지의 매크로를 추가하여 사용 Handler0() { //… } Message ID 0 Handler0 Message ID 1 Handler1 Handler1() { //… } ● ● ● ● ● ● Message ID n-1 Handler n-1 Handler n-1() { //… } 0 NULL Message Map Univ of Incheon, 고급프로그래밍

  16. Message Map 의 구성 • 선언부 • DECLARE_MESSAGE_MAP() • 정의부 • BEGIN_MESSAGE_MAP() • END_MESSAGE_MAP() Class CChildView: Public CWnd { …. DECLARE_MESSAGE_MAP( ) } BEGIN_MESSAGE_MAP(CChildView, CWnd) // 메시지 맵 엔트리 추가 END_MESSAGE_MAP() Univ of Incheon, 고급프로그래밍

  17. ChildView.h class CChildView:: public CWnd { //{{AFX_MSG(CChildView) afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnRButtonDown(UINT nFlags, CPoint point); //}}AFX_MSG DECLARE_MESSAGE_MAP( ) } 핸들러 함수 선언 Message 처리단계(1/3) • 메시지 핸들러 함수 선언 (DECLARE_MESSAGE_MAP) Univ of Incheon, 고급프로그래밍

  18. Message 처리단계(2/3) • 메시지 매크로 (BEGIN_MESSAGE_MAP, END_MESSAGE_MAP) ChildView.cpp BEGIN_MESSAGE_MAP(CChildView, CWnd) //{{AFX_MSG_MAP(CChildView) ON_WM_LBUTTONDOWN( ) ON_WM_KEYDOWN( ) ON_WM_RBUTTONDOWN ( ) //}}AFX_MSG END_MESSAGE_MAP( ) Univ of Incheon, 고급프로그래밍

  19. Message 처리단계(3/3) • 핸들러 구현(함수) : 메시지를 처리하는 함수 구현 ChildView.cpp void CChildView::OnLButtonDown(UINT nFlag, Cpoint point) { CWnd::OnLButtonDown(nFlags, point); } void CChildView::OnKeyDown(UINT nFlag, Cpoint point) { CWnd::OnKeyDown(nFlags, point); } void CChildView::OnRButtonDown(UINT nFlag, Cpoint point) { CWnd::OnRButtonDown(nFlags, point); } Univ of Incheon, 고급프로그래밍

  20. 메시지 매크로의 확장(1/8) • DECLARE_MESSAGE_MAP() AFXWIN.H Univ of Incheon, 고급프로그래밍

  21. // 윈도우 메시지 ID // 통지코드 // 개체 식별 번호 // 개체범위의 마지막 식별 번호 // 메시지 핸들러 유형 // 메시지 핸들러 메시지 매크로의 확장(2/8) • AFX_MSGMAP_ENTRY • 메시지 맵 항목은 AFX_MSGMAP_ENTRY로 정의 • 메시지 식별번호, 통지코드, 개체식별 번호 등이 포함된 구조체 Univ of Incheon, 고급프로그래밍

  22. 메시지 매크로의 확장(3/8) • AFX_MSGMAP • 메시지 처리를 위해 메시지 맵에 등록되어있는 메시지 핸들러 호출 • 매시지 맵은 메시지 맵 항목들로 이루어진 배열 함수포인터 하나 Or 베이스 메시지맵 포인터 AND 메시지맵 엔트리 포인터 Univ of Incheon, 고급프로그래밍

  23. 메시지 매크로의 확장(4/8) • BEGIN_MESSAGE_MAP 메시지 맵이 정의된 클래스 기초 클래스 배열 열기 • GetMessageMap을 구현, messageMap초기화하며 messageEntries[]에 메시지 맵 항목을 넣을 수 있게 준비 Univ of Incheon, 고급프로그래밍

  24. ` 메시지 매크로의 확장(5/8) • Message Map entries • 메시지 맵 매크로 형식은 메시지에 따라 다르다 Ex) WM_LBUTTONDOWN을 처리할 때 다음과 같은 매크로 필요 ON_WM_LBUTTONDOWN( ) • ON_WM_LBUTTONDOWN은 WM_LBUTTONDOWN메시지 발생시 OnLButtonDown이 호출되어야 함 • 유저가 임의로 바꿀 수 없음 Univ of Incheon, 고급프로그래밍

  25. ` 배열 닫기 메시지 handler 윈도우 Message ID 메시지 매크로의 확장(6/8) • END_MESSAGE_MAP • messageEntries의 마지막임을 표시하는 메시지 맵 항목 추가, 메시지 맵 배열 종료 Univ of Incheon, 고급프로그래밍

  26. BEGIN_MESSAGE_MAP(CChildView, CWnd) ON_WM_LBUTTONDOWN( ) ON_WM_KEYDOWN( ) ON_WM_RBUTTONDOWN( ) END_MESSAGE_MAP( ) const AFX_MSGMAP CChildView::GetMessageMap( ) const { return & CChildView::messageMap;} const AFX_MSGMAP CChildView::_message Map = {&CWnd::messageMap, &CChildView::_messageEntries[]}; const AFX_MSGMAP_ENTRY CChildView::_messageEntries[]={ {WM_LBUTTONDOWN, 0, 0, 0, AfxSig_vwp, &OnLButtonDown}, {WM_KEYDOWN, 0, 0, 0, AfxSig_vwp, &OnKeyDown}, {WM_RBUTTONDOWN, 0, 0, 0, AfxSig_vwp, &OnRButtonDown}, {0, 0, 0, 0, afxSig_end, (AFX_PMSG)0 } }; 메시지 매크로의 확장(7/8) Univ of Incheon, 고급프로그래밍

  27. 메시지 매크로의 확장(8/8) • MESSAGE_MAP의 특징 • _messageEntries[] 배열의 크기를 한정하지 않고 있음 몇 개의 메시지가 추가될지 모름 • 여러 개 구조체 변수들 관련 • AFX_MSGMAP • AFX_MSGMAP_ENTRY • 매크로 정의이기 때문에 컴파일 1차 패스에서 변환 • 각 클래스별로 메시지맵 관리 Univ of Incheon, 고급프로그래밍

  28. 프로젝트명View.cpp 사용자 정의 메시지(1/8) • MFC가 제공하지 않는 윈도우 메시지 • 사용자가 직접 발생시키는 메시지 • WM_MYMESSAGE라는 새로운 메시지를 만들고자 한다면 #define문을 이용 WM_USER이후의 값을 선언 • WM_USER이후의 값(WM_USER+1)의 의미 • 윈도우메시지는“WINUSER.H”에메시지Number, 즉 ID값이 정의되어있음 • (MFC에서 미리 정의한 Message ID) < (사용자 정의 Message ID) • 따라서 중복 방지를 위해 WM_USER + 1, 2와 같은 방법으로 메시지 생성 Univ of Incheon, 고급프로그래밍

  29. <프로젝트명View.h> afx_msg void 핸들러함수명(WPARAM wParam, LPARAM lParam); wParam과 lParam인수는 처리중인 메시지에 따라 달리짐 프로젝트명View.h 사용자 정의 메시지(2/8) • 메시지가 발생했을때 수행되는 함수를 헤더부에 설정 • 해당 메시지에 대한 핸들러 함수의 원형을 헤더부에 선언 Univ of Incheon, 고급프로그래밍

  30. 프로젝트명View.cpp 사용자 정의 메시지(3/8) • ON_MESSAGE매크로를 이용하여 정의한 메시지명과 함수명을 결합하여 선언 • 메시지 맵에 ON_MESSAGE()라는 메시지 매크로를 추가 <메시지 매크로> ON_MESSAGE(메시지명, 함수명) Univ of Incheon, 고급프로그래밍

  31. UsrMsgTestView.cpp 사용자 정의 메시지(4/8) • 선언한 함수를 소스부에 만들고 해당 메시지가 수행되었을때의 함수를 만듬 • 다음과 같이 소스부에 핸들러 함수 구현 <소스부> void 클래스명 :: 함수명(WPARAM wParam, LPARAM lParam) { // 소스코딩 } Univ of Incheon, 고급프로그래밍

  32. SendMessage 사용자가 만든 메시지는 사용자가 직접 메시지를 발생시킴 이때 사용하는 함수가 SendMessage() CWnd의 멤버 함수 WM_MYMESSAGE를 생성 사용자 정의 메시지(5/8) LRESULT SendMessage ( UINT message, WPARAM wParam = 0, LPARAM lParam = 0); Message : 보내고자 하는 Message ID wParam : 메시지 정보와 함께 보내주는 WPARAM 인자 lParam : 메시지 정보와 함께 보내주는 lParam 인자 SendMessage(WM_MYMESSAGE, 0, 0); Univ of Incheon, 고급프로그래밍

  33. UsrMsgTestView.cpp UsrMsgTestView.h 사용자 정의 메시지(6/8) • 사용자 정의 메시지의 예 (프로젝트명 : UsrMsgTest) Message ID를 등록후 사용자 정의 메시지에 대한 핸들러 함수의 원형을 헤더에 선언 Univ of Incheon, 고급프로그래밍

  34. UsrMsgTestView.cpp 사용자 정의 메시지(7/8) UsrMsgTestView.cpp 메시지 매크로를 메시지 맵 블럭내에 추가 한후 핸들러 함수 구현 Univ of Incheon, 고급프로그래밍

  35. 사용자 정의 메시지(8/8) • 프로그램 실행 결과 UsrMsgTestView.cpp 마우스 왼쪽버튼클릭 Univ of Incheon, 고급프로그래밍

  36. 메시지 처리 방식의 종류(1/2) • 큐 경유 방식 • 입력 메시지들(WM_LBUTTONDOWN, WM_KEYDOWN, WM_SYSTEMDOWN, WM_TIMER 등) • message  message queue  message loop  window procedure • 큐를 경유 하지 않는 방식 • 입력 메시지를 제외한 대부분의 메시지들(WM_CREATE, WM_SIZE, WM_CLOSE,WM_PAINT() WM_DESTROY, WM_MOVE, 등) • message  window procedure Univ of Incheon, 고급프로그래밍

  37. Windows O/S 응용 프로그램 하드웨어 장치 입력 메시지 시스템 큐 메시지 루프 응용 큐 입력 제외 메시지 Window procedure 메시지 처리 방식의 종류(2/2) Univ of Incheon, 고급프로그래밍

  38. 메시지 처리 흐름(1/11) • Message Loop • 메시지 큐를 경유하는 메시지들은 Message Loop를 통해 윈도우 프로시져에 전달 • 메시지 루프는 CWinThread::Run에 의해 실행 • CWinThread::Run은 WM_QUIT가 발생할 때까지 반복적으로 메시지를 가져와 분배 • CWnd::SendMessage • 메시지 큐를 거치지 않고 메시지 발생 • CWnd::PostMessage • 메시지 큐에 메시지를 넣음 Univ of Incheon, 고급프로그래밍

  39. 메시지 처리 흐름(2/11) int CWinThread::Run() // idle time 상태를 추적하기 위한 변수 { BOOL bIdle = TRUE; LONG lIdleCount = 0; //WM_QUIT를받을때까지메시지를가져와 분배한다. for (;;) { while ( bIdle && !::PeekMessage( &m_msgCur, ... ) ) {// bIdle이 TRUE 이고 메시지 큐에 메시지가 없는지 체크 if ( !OnIdle ( lIdleCount++ ) ) bIdle = FALSE; } do { if ( !PumpMessage() ) return ExitInstance(); // WM_QUIT를 받으면 여기 if ( IsIdleMessage ( &m_msgCur ) ) { bIdle = TRUE; // idle 메시지면 여기 IdleCount = 0; } } while ( ::PeekMessage ( &m_msgCur, ... ) ); } } Univ of Incheon, 고급프로그래밍

  40. 메시지 처리 흐름(3/11) • 메시지가 없을때 CWinThread::OnIdle()을 호출하여 백그라운드작업 수행 • 메시지가 있을 경우 CWinThread::PumpMessage()를 호출 메시지 큐로부터 메시지를 가져와 윈도우 프로시저에 분배 • DispatchMessage() 를 통해 메시지를 분배하기 이전에 가상함수인 PreTranslateMessage()를 호출함으로써 유저에게 입력 메시지를 가로챌 수 있는 기회 제공 BOOL CWinThread::PumpMessage() { if ( !::GetMessage(&m_msgCur, ...) ) // message queue로부터 메시지를 가져온다. { return FALSE; // WM_QUIT를 받으면 FALSE를 반환하게 된다. } if ( m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur) ) { ::TranslateMessate(&m_msgCur); ::DispatchMessage(&m_msgCur); // window procedure에게 메시지 분배 } return TRUE; } Univ of Incheon, 고급프로그래밍

  41. ` 메시지 처리 흐름(4/11) • Window Procedure • 모든 메시지는 윈도우 프로시저에 의해 처리 • CWnd::WindowProc()은 CWnd::OnWndMsg()를 호출하여 메시지 맵에 등록된 메시지 핸들러 호출 • 처리되지 않는 메시지는 CWnd::DefWindowProc()을 호출, default 방식으로 메시지 처리 Univ of Incheon, 고급프로그래밍

  42. 메시지 처리 흐름(5/11) • CWnd::OnWndMsg • GetMesageMap( )을사용하여메시지맵에서 아이디에 해당하는 핸들러 검색 • 해당메시지핸들러(사용자정의메시지핸들러) 검색 후 해당 메시지 핸들러 실행 • 예외) WM_COMMAND OnCommand 함수 호출 WM_NOTIFY OnNotify 함수 호출 event 1 CWinTread::Run() 2 CWinTread:: PumpMessage() 3 CWnd:: PreTranslateMesssage() 4 CWnd:: DispatchMesssage() 5 AfxWndProc( ) CWnd::OnCommand() 6 AfxCallWndProc( ) CWnd::OnNotify() 7 CWnd::OnWndMsg() CWnd:: GetMessageMap() Tread Message Queue 8 CWnd:: DefWindowProc() 6 Message Handling Function Univ of Incheon, 고급프로그래밍

  43. CWnd::OnWndMsg Wincore.cpp // WM_COMMAND 계열 처리 // WM_NOTIFY 계열 처리 // WM_ACTIVATE 처리 // WM_SETCURSOR 처리 메시지 처리 흐름(6/11) Univ of Incheon, 고급프로그래밍

  44. 메시지 처리 흐름(7/11) // 캐쉬내에서 찾았다면 (메시지 처리를 캐쉬를 이용해서 찾는다) // message map entry에 등록된 메시지 핸들러가 없으면 FALSE 반환 • GetMessageMap() 함수 • 유저클래스에서 사용한 BEGIN_MESSAGE_MAP 매크로가 확장시 재정의된 가상함수 • 이 함수는 CChildView::messageMap을 리턴 • CChildView::messageMap안에는 CChildView::_messageEntries의 주소가 포함 • 결국 가장 하위레벨 클래스의 메시지 맵부터 검사 Univ of Incheon, 고급프로그래밍

  45. 메시지 처리 흐름(8/11) // 정해진 메시지인지 사용자 정의 메시지 핸들러 인지 판단 메시지 핸들러 검색함수 Messge id를 가지고 CChildView::_messageEntries를 검색해서 메시지 맵 항목 리턴 만약 WM_LBUTTONDOWN메세지면 {WM_LBUTTONDOWN, 0, 0, 0, afxSig_vwp, &OnLButtonDown}을리턴 //캐쉬가 정해져 있지 않으면 선형검색 Univ of Incheon, 고급프로그래밍

  46. 메시지 처리 흐름(9/11) //CWnd::OnWndMsg에서는 메시지 맵 항목의 6번째 멤버 변수인 pfn을 호출 // 각각 핸들러의 시그니처에 맞는 함수의 형태를 호출 //case가 많이 있음 // 핸들러 함수 실행 Univ of Incheon, 고급프로그래밍

  47. 메시지 처리 흐름(10/11) • DefWindowProc CWnd::OnWndMsg에서는 메시지 핸들러가 현재 클래스에 있으면 현재 클래스의 메시지 핸들러를 호출하고 현재 클래스에 없으면 FALSE를 리턴해서 CWnd::WindowProc가 CWnd::DefWindowProc를 호출하도록 되어 있다 LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { ..... if (!OnWndMsg(message, wParam, lParam, &lResult)) lResult = DefWindowProc(message, wParam, lParam); <--- OnWndMsg에서 FALSE가 리턴되면 여기 ..... } Univ of Incheon, 고급프로그래밍

  48. 메시지 처리 흐름(11/11) LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { if (m_pfnSuper != NULL) return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam); WNDPROC pfnWndProc; if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL) return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam); else return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam); } m_pfnSuper은 창이 서브클래싱(subclassing)되어 있을 때 서브클래싱된 창의 윈도우 프로시저(WNDPROC)을 가리키는 함수 포인터이다. 즉, CWnd::DefWindowProc은 창이 서브클래싱 된 경우 서브클래싱된 창의 윈도우 프로시저를 호출하고 서브클래싱 되지 않은 경우에는 ::DefWindowProc를 호출하여 default 방식으로 메시지를 처리하도록 하고 있다. Univ of Incheon, 고급프로그래밍

More Related