MFC의 메시지 처리.

Slides:



Advertisements
Similar presentations
을지대학교 무선 네트워크 사용 방법 2010 년 06 월 01 일. 을지대학교 무선 네트워크 사용 방법 1. PC 무선랜 카드 활성화 및 체크 1 단계 : 시작 -> 설정 -> 네트워크 설정 2 단계 : 무선 네트워크 설정 선택 -> 마우스 버튼 오른쪽 클릭 -> 사용.
Advertisements

메시지 처리의 기본 개념 메시지 발생된 이벤트의 종류와 정보를 전달하는 일종의 상수 값 윈도우 프로그래밍 가장 중요한 것은 메시지를 처리하는 것 윈도우 시스템 Application 이벤트 발생 메시지 전송 메시지 처리 화면에 출력.
Message Process for SDI Chung-Buk HRD Institute of KCCI Dept. of Information & Communication PhD. Kang, Won-Chan.
메뉴 용어 (1/6) 최상위 메뉴 = 메뉴 바 최상위 메뉴 = 메뉴 바.
목 차 C# 언어 특징 .NET 프레임워크 C# 콘솔 프로그램 C# 윈도우 프로그램 실습 프로그래밍세미나 2.
목차 Contents 무선인터넷용 비밀번호 설정방법 Windows 7 Windows 8 Windows XP MAC OS.
윈도우 운영체제와 윈도우 응용 프로그램의 특징을 이해한다.
MFC Application Frameworks (AFX)
클래스 class, 객체 object 생성자 constructor 접근 access 제어 이벤트 event 처리.
WSAAsync Select 김대열 Bit - Academy Sunmoon University, Korea.
Lab 10 Guide: 프린터 출력 예제. 한 페이지의 그림 인쇄 (교재 24장, 쪽)
컴퓨터프로그래밍 1주차실습자료 Visual Studio 2005 사용법 익히기.
윤 홍 란 다이알로그(대화상자) 윤 홍 란
제 9 장 구조체와 공용체.
윤 홍 란 MFC 기초 윤 홍 란
Lab 2 Guide: 교재 3장 그래픽 예제 ( 쪽) - 펜과 브러시로 그리기 - 튀는 공
공통 컨트롤의 종류와 특징을 개관한다. 각종 공통 컨트롤의 사용 방법을 익힌다..
4장. 웹로직 서버상에서의 JDBC와 JTA의 운용
MFC Application Frameworks (AFX)
07. 디바이스 드라이버의 초기화와 종료 김진홍
CHAPTER 02 OpenCV 개요 PART 01 영상 처리 개요 및 OpenCV 소개.
5장. 마우스와 키보드.
3.2 SQL Server 설치 및 수행(계속) 시스템 데이터베이스 master
1. C++ 시작하기.
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
SqlParameter 클래스 선문 비트 18기 발표자 : 박성한.
메시지 큐[5] – test1.c 메시지 제어: msgctl(2) #include <sys/msg.h>
WinCE Device Driver 실습 #3
LCD 모듈의 특징 LCD 컨트롤러 내장으로 모든 디스플레이 기능을 명령어로 제어 8비트 혹은 4비트로 인터페이스
학습목표 학습목차 다른 홈페이지의 HTML 파일 코드를 보는 방법에 대해 알아봅니다.
TCP/IP Socket Programming…
14. 예외처리.
분할 윈도, 다중 뷰… 영상 통신 연구실 권 동 진 발표 일 : 04월 27일.
10장. 예외처리.
C#.
Method & library.
사용자 함수 사용하기 함수 함수 정의 프로그램에서 특정한 기능을 수행하도록 만든 하나의 단위 작업
자바응용.
인터넷응용프로그래밍 JavaScript(Intro).
2015학년도 PHP 기말 레포트 로그인 홈페이지 제작.
홀인원2.0 설치 메뉴얼.
Quiz #7 다음 수들을 합병 정렬과 퀵 정렬 알고리즘을 이용하여 오름 차순으로 정렬하였을 때, 데이터 이동 회수를 각각 구하라. 여러분은 정렬 과정을 단계별로 보이면서 이동 회수를 추적해야 한다. 단, 퀵 정렬시에 피봇으로 배열의 왼쪽 첫 번째 원소를 선택한다. 5.
영상처리 실습 인공지능연구실.
GUI 소켓 애플리케이션 Chapter 08. * 학습목표 윈도우 GUI 애플리케이션의 구조와 동작 원리를 이해
Lesson 2. 기본 데이터형.
Lab 1 Guide: 교재 2장 DrawX ( 쪽)
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
USN(Ubiquitous Sensor Network)
인터넷응용프로그래밍 JavaScript(Intro).
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
Lab 8 Guide: 멀티스레딩 예제 2 * Critical Section을 이용한 멀티스레딩 동기화 (교재 15장, 쪽)
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
컴퓨터 계측 및 실습 디지털 출력 영남대학교 기계공학부.
CHAP 21. 전화, SMS, 주소록.
( Windows Service Application Debugging )
학습목표 처음 만드는 비주얼 베이직 프로그램 프로그램 실행과 실행 파일 생성. 학습목표 처음 만드는 비주얼 베이직 프로그램 프로그램 실행과 실행 파일 생성.
3장. 제어 메시지 처리하기 1/211 1.
데이터 동적 할당 Collection class.
3. 윈도우 핸들 제어.
영상처리 실습 (OpenCV + MFC) Chonbuk National University A.I. Lab.
.Net Web Application 2007 컴퓨터공학실험(Ⅰ)
가장 많이 사용 Accelerator 최상위 WM_COMMAND, OLE 메시지 관련 이벤트 처리만 가능 이 클래스를 상속받아서 다른 이벤트 처리 이벤트 처리 관련 윈도우(창) 최상위 클래스 멀티 테스킹(모듈) CFrameWnd, Cview,
메뉴(Menu) 컴퓨터응용 및 실습 I.
3. 모듈 (5장. 모듈).
9 브라우저 객체 모델.
Android -Data Base 윤수진 GyeongSang Univ. IT 1.
엔코더 프로그램 설명 // 쓰레드를 사용하기 때문에 변수와 핸들을 전역변수로 지정 HANDLE hDevice;
윈도우 운영체제와 윈도우 응용 프로그램의 특징 SDK 응용 프로그램 MFC 응용 프로그램
MFC 기초 윈도우 응용프로그램 개발 간략한 역사 Microsoft Foundation Classes
BoardGame 보드게임 따라가기.
Presentation transcript:

MFC의 메시지 처리

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

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

메시지 개요(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, 고급프로그래밍

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

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

메시지 개요(4/7) Windows Message 메시지 유형 발생상황 메시지 핸들러 함수 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() Univ of Incheon, 고급프로그래밍

메시지 개요(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, 고급프로그래밍

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

메시지 개요(7/7) 파생 클래스 설명 CDocument 프로그램의 데이터를 처리하는 기능 CView WM_COMMAND 메시지 전달순서 CView 파생 클래스 CDocument CFrameWnd CWinApp 파생 클래스 설명 CDocument 프로그램의 데이터를 처리하는 기능 CView 데이터를 화면에 표시하는 기능 CWinApp 프로그램의 시작과 종료에 관련 된 커맨드 CFrameWnd 프레임 윈도우의 제어에 관계된 커멘드 처리 Univ of Incheon, 고급프로그래밍

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

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, 고급프로그래밍

Message Map 처리 기본개념(3/5) SDK로 표현 MFC로 표현 해당하는 모듈을 모두 switch문으로 설정 LESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch (iMsg) case WM_CREATE : //윈도가 만들어질 때 모듈 break; case WM_PAINT : //화면 출력 모듈 case WM_KEYDOWN : //키 입력시 처리 모듈 case WM_CHAR : //문자 입력시 처리 모듈 case WM_DESTROY : //윈도가 없어질 때 모듈 } 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, 고급프로그래밍

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

Message Map 처리 기본개념(5/5) MFC 메시지 맵의 핵심 코드의 자동화를 위하여 메시지 맵에 메시지와 메시지 핸들러 함수를 묶는 메시지의 매크로를 추가하여 사용 Handler0() { //… } Message ID 0 Handler0 Message ID 1 Handler1 Handler1() { //… } ● ● Message ID n-1 Handler n-1 Handler n-1() { //… } NULL Message Map Univ of Incheon, 고급프로그래밍

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, 고급프로그래밍

Message 처리단계(1/3) 메시지 핸들러 함수 선언 (DECLARE_MESSAGE_MAP) 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( ) } ChildView.h 핸들러 함수 선언 Univ of Incheon, 고급프로그래밍

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, 고급프로그래밍

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, 고급프로그래밍

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

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

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

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

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

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

메시지 매크로의 확장(7/8) 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 } }; Univ of Incheon, 고급프로그래밍

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

사용자 정의 메시지(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와 같은 방법으로 메시지 생성 프로젝트명View.cpp Univ of Incheon, 고급프로그래밍

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

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

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

사용자 정의 메시지(5/8) SendMessage 사용자가 만든 메시지는 사용자가 직접 메시지를 발생시킴 CWnd의 멤버 함수 WM_MYMESSAGE를 생성 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, 고급프로그래밍

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

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

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

메시지 처리 방식의 종류(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, 고급프로그래밍

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

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

메시지 처리 흐름(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, 고급프로그래밍

메시지 처리 흐름(3/11) 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; 메시지가 없을때 CWinThread::OnIdle()을 호출하여 백그라운드작업 수행 메시지가 있을 경우 CWinThread::PumpMessage()를 호출 메시지 큐로부터 메시지를 가져와 윈도우 프로시저에 분배 DispatchMessage() 를 통해 메시지를 분배하기 이전에 가상함수인 PreTranslateMessage()를 호출함으로써 유저에게 입력 메시지를 가로챌 수 있는 기회 제공 Univ of Incheon, 고급프로그래밍

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

PreTranslateMesssage() 메시지 처리 흐름(5/11) event CWnd::OnWndMsg GetMesageMap( )을 사용하여 메시지맵에서 아이디에 해당하는 핸들러 검색 해당 메시지 핸들러(사용자 정의 메시지 핸들러) 검색 후 해당 메시지 핸들러 실행 예외) WM_COMMAND OnCommand 함수 호출 WM_NOTIFY OnNotify 함수 호출 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, 고급프로그래밍

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

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

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

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

메시지 처리 흐름(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, 고급프로그래밍

메시지 처리 흐름(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, 고급프로그래밍