MFC Internals Contents Chapter 01 MFC Chapter 02

  • Slides: 175
Download presentation
MFC Internals

MFC Internals

Contents Chapter 01 MFC 개관 Chapter 02 MFC와 C/SDK Chapter 03 MFC에서의 Message 처리

Contents Chapter 01 MFC 개관 Chapter 02 MFC와 C/SDK Chapter 03 MFC에서의 Message 처리 Chapter 04 MFC Utility Class Chapter 05 모든 길은 Cobject로 통한다 Chapter 06 MFC Dialog와 Control Dialog Chapter 07 MFC의 Document/View Architecture 1 비트교육센터

Chapter 01 MFC 개관

Chapter 01 MFC 개관

Contents Application Frameworks 정의 MFC의 역사 MFC의 설계 목적 MFC의 구성 MFC code basics

Contents Application Frameworks 정의 MFC의 역사 MFC의 설계 목적 MFC의 구성 MFC code basics 3 비트교육센터

Application Frameworks Framework – 특정 영역의 작업을 도와 주는 class 집합 Application Framework –

Application Frameworks Framework – 특정 영역의 작업을 도와 주는 class 집합 Application Framework – 특정 OS의 application 개발 작업을 도와 주는 class 집합 MFC (Microsoft Foundation Classes) – Windows용 application 개발 작업을 도와 주는 framework 4 비트교육센터

MFC의 역사 1989년 – AFX group 탄생 Application framework technology development group의 약자 –

MFC의 역사 1989년 – AFX group 탄생 Application framework technology development group의 약자 – 목적 Windows application개발자를 위한 C++과 object-oriented 개념을 적용시 킨 tool의 개발 – First prototype 실패 Too complex and too different from Windows itself 5 비트교육센터

MFC의 역사 (cont’d) 1993년 – MFC version 2. 0 Visual C++ version 1. 0과

MFC의 역사 (cont’d) 1993년 – MFC version 2. 0 Visual C++ version 1. 0과 Windows NT와 함께 나옴 100개가 넘는 class포함 새로 포함된 내용 – 새로운 application architecture – 새로운 high-level abstractions 7 비트교육센터

MFC의 역사 (cont’d) 1993년 말 – MFC version 2. 5 Visual C++ version 1.

MFC의 역사 (cont’d) 1993년 말 – MFC version 2. 5 Visual C++ version 1. 5와 함께 나옴 OLE 2. 0과 ODBC 지원이 추가됨 1994년 – MFC version 3. 0 Thread에 대한 기능이 보강됨 8 비트교육센터

MFC의 역사 (cont’d) 1995년 – MFC version 3. 1 추가된 기능 – Simple Messaging

MFC의 역사 (cont’d) 1995년 – MFC version 3. 1 추가된 기능 – Simple Messaging Application Programming Interface(MAPI) – Win. Sock – MFC version 4. 0 Visual C++ version 4. 0과 함께 나옴 개발환경의 발전, 재사용성의 향상 9 비트교육센터

MFC의 역사 (cont’d) 1997년 – MFC version 4. 2 Visual C++ version 5. 0과

MFC의 역사 (cont’d) 1997년 – MFC version 4. 2 Visual C++ version 5. 0과 함께 나옴 Internet 등을 위한 기능 추가 1998년 – MFC version 6. 0 Visual C++ version 6. 0과 함께 나옴 User interface향상 등의 기능이 포함 2002년 – MFC version 7. 0 Visual C++. net(7. 0) 과 함께 나옴 기존의 각 요소별 추가 및 확장 – DHTML(editing, dialog box, …), Ole control, … Static casting and MFC message maps 10 비트교육센터

MFC의 역사(cont’d) MFC version과 Visual C++ version MFC version Visual C++ version 6. 0

MFC의 역사(cont’d) MFC version과 Visual C++ version MFC version Visual C++ version 6. 0 Microsoft Visual C++ version 6. 0 4. 2 Microsoft Visual C++ versions 4. 2 and 5. 0 4. 0 Microsoft Visual C++ versions 4. 0 and 4. 1 3. 2 Microsoft Visual C++ version 2. 2 3. 1 Microsoft Visual C++ version 2. 1 3. 0 Microsoft Visual C++ version 2. 0 2. 5 Microsoft Visual C++ version 1. 5 2. 1 Microsoft Visual C++ version 1. 0 2. 0 Microsoft Visual C++ version 1. 0 Microsoft C/C++ version 7. 0 11 비트교육센터

MFC 설계 목적 AFX 그룹의 설계 목적 – – – Real-World Application Simplifying the

MFC 설계 목적 AFX 그룹의 설계 목적 – – – Real-World Application Simplifying the Windows API Using the existing knowledge of Windows Foundation for large-scale applications Small and fast framework 12 비트교육센터

MFC의 구성 MFC class 의 분류 – – – General-purpose classes Windows API classes

MFC의 구성 MFC class 의 분류 – – – General-purpose classes Windows API classes Application framework classes High-level abstractions Operating System Extension 13 비트교육센터

MFC의 구성(cont’d) General-purpose Class – 프로그램의 일반적 용도를 위한 class (1) CObject class MFC의

MFC의 구성(cont’d) General-purpose Class – 프로그램의 일반적 용도를 위한 class (1) CObject class MFC의 최상위 class run-time type information, serialization, diagnostic function, support for dynamic creation 4가지 중요한 기능 제공 CArchive, CDump. Context, CRuntime. Class 등과 연계되어 작용 14 비트교육센터

MFC의 구성(cont’d) (2) Exception-handling class memory, I/O error 발생 시 처리 CException : base

MFC의 구성(cont’d) (2) Exception-handling class memory, I/O error 발생 시 처리 CException : base class CArchive. Exception, CFile. Exception CMemory. Exception, CResource. Exception CNot. Supported. Exception, CUser. Exception COle. Exception, CDBException 15 비트교육센터

MFC의 구성(cont’d) (3) Collection class Array : CByte. Array, CWord. Array, CDWord. Array, CPtr.

MFC의 구성(cont’d) (3) Collection class Array : CByte. Array, CWord. Array, CDWord. Array, CPtr. Array, COb. Array, CString. Array, CUnit. Array Linked list : COb. List, CPtr. List, CString. List Map : CMap. Ptr. To. Word, CMap. Ptr. To. Ptr, CMap. String. To. Ob, CMap. String. To. Ptr, CMap. String. To. String, CMap. Word. To. Ob, CMap. Word. To. Ptr 16 비트교육센터

MFC의 구성(cont’d) (4) Dynamic string class CString concatenation, comparison, assignment 등의 기본 연산 제공

MFC의 구성(cont’d) (4) Dynamic string class CString concatenation, comparison, assignment 등의 기본 연산 제공 (5) File class CFile, CStdio. File, CMem. File 추상적으로 disk상의 파일 제어, 실제로는 memory상의 파일 제어 17 비트교육센터

MFC의 구성(cont’d) (6) Time class CTime, CTime. Span (7) 기타 CPoint, CSize, CRect :

MFC의 구성(cont’d) (6) Time class CTime, CTime. Span (7) 기타 CPoint, CSize, CRect : Windows structure 18 비트교육센터

MFC의 구성(cont’d) Windows API class (1) Application 관련 class CCmd. Target : message 처리

MFC의 구성(cont’d) Windows API class (1) Application 관련 class CCmd. Target : message 처리 CCmd. UI : user interface의 update CWin. Thread : MFC program의 실행 thread를 의미, 즉 program의 main을 포함 CWin. App : CWin. Thread의 파생 class으로서 standard windows application을 표현 19 비트교육센터

MFC의 구성(cont’d) – Window 관련 class CWnd : CCmd. Target의 파생 class이므로 message를 handle.

MFC의 구성(cont’d) – Window 관련 class CWnd : CCmd. Target의 파생 class이므로 message를 handle. 윈도우를 다루는 API 포함. CFram. Wnd, CMDIFrame. Wnd : main frame window로서 message를 받는 첫 윈도우 CDialog, 공통다이어로그박스(CFile. Dialog, CColor. Dialog, CFont. Dialog, CPrint. Dialog, CFind. Replace. Dialog) CData. Exchange : DDX/DDV 20 비트교육센터

MFC의 구성(cont’d) CProperty. Sheet, CProperty. Page Controls : CButton, CEdit, … Cmenu – GDI

MFC의 구성(cont’d) CProperty. Sheet, CProperty. Page Controls : CButton, CEdit, … Cmenu – GDI 관련 class CDC, CPaint. DC, CWindow. DC, CClient. DC, CMeta. File. DC CPen, CBrush, CFont, . . . 21 비트교육센터

MFC의 구성(cont’d) Application framework class – Document/View Architecture CDoc. Template, CSingle. Doc. Template, CMulti.

MFC의 구성(cont’d) Application framework class – Document/View Architecture CDoc. Template, CSingle. Doc. Template, CMulti. Doc. Template : document와 view를 연결 CDocument : data를 관리 CView : data를 redering하여 보여 줌 – Context-Sensitive Help 22 비트교육센터

MFC의 구성(cont’d) High-level abstraction – Enhanced Views CScroll. View, CForm. View CEdit. View, CList.

MFC의 구성(cont’d) High-level abstraction – Enhanced Views CScroll. View, CForm. View CEdit. View, CList. View, CRich. Edit. View, CTree. View – Splitter Window CSplitter. Wnd : dynamic, static – Control Views CTool. Bar, CStatus. Bar, CDialog. Bar 23 비트교육센터

MFC Code Basics Class Declaration Subsections – MFC library 개발 팀의 코딩 규칙 Not

MFC Code Basics Class Declaration Subsections – MFC library 개발 팀의 코딩 규칙 Not based public/protected/private Private 변수는 거의 사용하지 않는다. – Header / source file // Constructors // Attributes // Operations // Overridables // Implementation 24 비트교육센터

Example of Comments class CStdio. File : public CFile { DECLARE_DYNAMIC(CStdio. File) public: //

Example of Comments class CStdio. File : public CFile { DECLARE_DYNAMIC(CStdio. File) public: // Constructors CStdio. File(); . . . // Attributes FILE* m_p. Stream; // stdio FILE. . . // Operations virtual void Write. String(LPCTSTR lpsz); . . . virtual LPTSTR Read. String(LPTSTR lpsz, UINT n. Max); . . . // Implementation public: . . . }; 25 비트교육센터

MFC Comments Class Declaration Subsections – MFC library 개발 팀의 코딩 규칙 – Class

MFC Comments Class Declaration Subsections – MFC library 개발 팀의 코딩 규칙 – Class header file의 각 항목의 의미 // Constructors(생성자 함수들, 초기화 함수들) – C++ constructors, any other initialization – 예) CWnd: : Create – 대개는 public // Attributes(위의 내용을 setting하거나 얻어옴) – 대개는 documented public data members – Member functions(위의 data를 조작하는) : Get / Set 함수들 26 비트교육센터

MFC Code Basics (cont’d) // Operations(값이 변한다>? ? ) – Documented member functions –

MFC Code Basics (cont’d) // Operations(값이 변한다>? ? ) – Documented member functions – 대개는 public, non-const : side effects // Overridables – 상속 받은 class가 override한 functions – Pure virtual functions // Implementation(현재 쓰고 있는 개념임) – – Implementation detail Undocumented 대개는 protected 주의 : may change in future versions of MFC 27 비트교육센터

MFC Code Basics (cont’d) Variable Naming (common) Type Prefix Example Comment char c c.

MFC Code Basics (cont’d) Variable Naming (common) Type Prefix Example Comment char c c. Dir. Separator BOOL b bls. Sending int n n. Variable. Cnt UINT n n. My. Unsigned WORD w w. List. ID LONG l l. Axis. Ratio DWORD dw dw. Packedmessage * (pointer) p p. Wnd FAR * lp lp. Wnd LPSTR handle lpsz h lpsz. File. Name h. Wnd Z indicates NULL terminated. callback lpfn. Hook. Proc Pointer to a function 28 비트교육센터

MFC Code Basics (cont’d) Variable Naming (MFC extensions) Class Prefix Example CRect rect. Scroll

MFC Code Basics (cont’d) Variable Naming (MFC extensions) Class Prefix Example CRect rect. Scroll CPoint pt pt. Mouse. Click CSize sz sz. Rectangle CString str. Find CWnd Wnd. Control CWnd* p. Wnd. Dialog 29 비트교육센터

MFC Code Basics (cont’d) Symbol Naming Type Prefix Example Range Shared by multiple resources

MFC Code Basics (cont’d) Symbol Naming Type Prefix Example Range Shared by multiple resources IDR_MAINFRAME 1 -0 x 6 FFF Dialog resource IDD_ABOUT 1 -0 x 6 FFF Dialog resource help context ID (for context-sensitive help) HIDD_HELP_ABOUT 0 x 2001 -0 x 26 FF Bitmap resource IDB_SMILEY 1 -0 x 6 FFF Cursor resource Icon resource IDC_HAND 1 -0 x 6 FFF 30 비트교육센터

MFC Code Basics (cont’d) Symbol Naming Type Prefix Example Range Menu or toolbar command

MFC Code Basics (cont’d) Symbol Naming Type Prefix Example Range Menu or toolbar command ID_CIRCLE_TOOL 0 x 8000 -0 x. DFFF Command help context HID_CIRCLE_TOOL 0 x 1800 -0 x 1 DFF Message box prompt IDP_FATALERROR 8 -0 x. DFFF Message box help context HIDP_FATALERROR 0 x 3008 -0 x 3 DFF Control in dialog template IDC_COMBO 1 8 -0 x. DFFF String resource IDS_ERROR 12 1 -0 x 7 FFF 31 비트교육센터

Chapter 02 MFC와 C/CDK

Chapter 02 MFC와 C/CDK

Contents Introduction MFC versus C/SDK Basic Application Components – CWin. App – CWnd –

Contents Introduction MFC versus C/SDK Basic Application Components – CWin. App – CWnd – Window handles & Window objects Find Win. Main() Hidden Cool Stuff – Registering Window Classes – MFC’s Windows Hooks – MFC’s Message Pump MFC’s GDI Support 33 비트교육센터

Introduction MFC – 200개 이상의 클래스들의 거대한 집합 – But, MFC has also “Basic

Introduction MFC – 200개 이상의 클래스들의 거대한 집합 – But, MFC has also “Basic Windows Support” A Windows program is still a Windows program – 어떤 언어(C, C++, Delphi, …)나 framework(MFC, OWL, …) 를 이용하든지 기본적인 요소들이 구현된다. – Basic windows application support Win. Main, window class 등록, 메시지 루프, … 34 비트교육센터

Issue MFC가 어떻게 Windows application을 만드는가 – The application itself(응용프로그램 그 자체) - main

Issue MFC가 어떻게 Windows application을 만드는가 – The application itself(응용프로그램 그 자체) - main thread – Windows – Message handling(위의 두가지를 연결해줌) – The Graphics Device Interface (GDI) 35 비트교육센터

MFC vs. C/SDK Motivation – 모든 Windows application은 다음 2개의 component를 포함한다. main application

MFC vs. C/SDK Motivation – 모든 Windows application은 다음 2개의 component를 포함한다. main application itself message를 핸들하는 하나 이상의 window – C/SDK 개발 환경 copy & paste Time-consuming & inefficient – C++/MFC 개발 환경 OOP 활용 : inheritance & encaptulation 필요한 부분만 변경 36 비트교육센터

메시지 처리를 위한 작업들 Set up a message handler and register it – Regiser.

메시지 처리를 위한 작업들 Set up a message handler and register it – Regiser. Class() : 윈도우 프로시져 등록 Windows가 application의 instance들을 추적 application은 Windows에게 메시지를 요청(ask)하고, 처리(dispatch)한다. application이 종료될 때까지 위 작업을 반복한다. 38 비트교육센터

Application의 준비 Win. Main() 함수 – – 프로그램의 시작점 Windows 로부터 프로그램을 실행하는데 필요한

Application의 준비 Win. Main() 함수 – – 프로그램의 시작점 Windows 로부터 프로그램을 실행하는데 필요한 정보를 얻어 오는 통로 현재 instance의 handle, 직전에 실행된 instance의 handle, command line argument, window의 모습(최대화, 최소화, …) 적어도 하나의 main window class를 등록 – User interface를 제공 Message loop를 설정 Some initialization and setup(초기화 작업) – Application specific, instance specific Message handler를 제공 v 최소한 WM_DESTROY 처리 -> WM_QUIT 생성 39 비트교육센터

Application의 기본 요소 Message Handler Main 함수 Application specific Initialization (Window class 등록) Instance

Application의 기본 요소 Message Handler Main 함수 Application specific Initialization (Window class 등록) Instance specific Initialization (Main window(UI)생성, 보여줌) Message loop 40 비트교육센터

Source 1 : C/SDK #include <windows. h> HANDLE h. Inst; /* current instance */

Source 1 : C/SDK #include <windows. h> HANDLE h. Inst; /* current instance */ LRESULT CALLBACK Main. Wnd. Proc(HANDLE h. Wnd, UINT message, WPARAM w. Param, LPARAM l. Param) { switch(message) { case WM_LBUTTONDOWN: Message. Box(h. Wnd, “Left mouse button clicked”, NULL, MB_OK); break; case WM_DESTROY: Post. Quit. Message(0); break; default: /* Passes it on if unprocessed */ return (Def. Window. Proc(h. Wnd, message, w. Param, l. Param)); } return 0; } 41 비트교육센터

BOOL Init. Application(HANDLE h. Instance){ WNDCLASS wc; wc. style = 0; /* Class style(s)

BOOL Init. Application(HANDLE h. Instance){ WNDCLASS wc; wc. style = 0; /* Class style(s) */ wc. lpfn. Wnd. Proc = Main. Wnd. Proc; /* Message handler */ wc. cb. Cls. Extra = 0; /* No per-class extra data */ wc. cb. Wnd. Extra = 0; /* No per-window extra data */ wc. h. Instance = h. Instance; /* Application that owns the class*/ wc. h. Icon = Load. Icon(NULL, IDI_APPLICATION); wc. h. Cursor = Load. Cursor(NULL, IDC_ARROW); wc. hbr. Background = Get. Stock. Object(WHITE_BRUSH); wc. lpsz. Menu. Name = NULL; /* Name of menu */ wc. lpsz. Class. Name = “Minimal. WClass”; /* Name of window class */ return (Register. Class(&wc)); } 42 비트교육센터

BOOL Init. Instance(HANDLE h. Instance, int n. Cmd. Show) { HWND h. Wnd; h.

BOOL Init. Instance(HANDLE h. Instance, int n. Cmd. Show) { HWND h. Wnd; h. Inst = h. Instance; h. Wnd = Create. Window( “Minimal. WClass”, “Minimal”, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, NULL, h. Instance, NULL); /* Main window handle */ // needed for loading resources // /* /* /* Window class */ Caption */ Window style */ Default horizontal pos. */ Default vertical pos. */ Default width */ Default height. */ No parent */ Use the window class menu */ This instance owns the window. */ 43 비트교육센터

if (!h. Wnd) return (FALSE); Show. Window(h. Wnd, n. Cmd. Show); Update. Window(h. Wnd);

if (!h. Wnd) return (FALSE); Show. Window(h. Wnd, n. Cmd. Show); Update. Window(h. Wnd); return (TRUE); } 44 비트교육센터

int WINAPI Win. Main(HINSTANCE h. Instance, HINSTANCE h. Prev. Instance, LPSTR lp. Cmd. Line,

int WINAPI Win. Main(HINSTANCE h. Instance, HINSTANCE h. Prev. Instance, LPSTR lp. Cmd. Line, int n. Cmd. Show) { MSG msg; /* message */ if (!h. Prev. Instance) { /* First instance? */ if (!Init. Application(h. Instance)) /* Shared stuff */ return (FALSE); /* cannot initialize */ } if (!Init. Instance(h. Instance, n. Cmd. Show)) return (FALSE); while (Get. Message(&msg, NULL, 0, 0)) { Translate. Message(&msg); Dispatch. Message(&msg); } return(msg. w. Param); /*Returns the value from Post. Quit. Message*/ } 45 비트교육센터

Source 2 : MFC #include <afxwin. h> // MFC 주요 클래스 선언 class CGeneric.

Source 2 : MFC #include <afxwin. h> // MFC 주요 클래스 선언 class CGeneric. App : public CWin. App { public: virtual BOOL Init. Instance(); }; class CGeneric. Window : public CFrame. Wnd { public: CGeneric. Window() { Create(NULL, “Generic”); } afx_msg void On. LButton. Down(UINT n. Flags, CPoint point); DECLARE_MESSAGE_MAP() }; 46 비트교육센터

BEGIN_MESSAGE_MAP(CGeneric. Window, CFrame. Wnd) ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() void CGeneric. Window: : On. LButton. Down(UINT n.

BEGIN_MESSAGE_MAP(CGeneric. Window, CFrame. Wnd) ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() void CGeneric. Window: : On. LButton. Down(UINT n. Flags, CPoint point) { Message. Box(“Left mouse button pressed…”, NULL, MB_OK); } BOOL CGeneric. App: : Init. Instance() { m_p. Main. Wnd = new CGeneric. Window(); m_p. Main. Wnd->Show. Window(m_n. Cmd. Show); m_p. Main. Wnd->Update. Window(); return TRUE; } CGeneric. App; 47 비트교육센터

C/SDK와 MFC의 비교 Win. Main() Function – C/SDK : 존재 – MFC : where?

C/SDK와 MFC의 비교 Win. Main() Function – C/SDK : 존재 – MFC : where? ( part of application framework ) Window class 등록 – C/SDK : 존재 – MFC : where? Message loop – C/SDK : 존재 – MFC : where? Additional functions : idle processing, Pre. Translate. Message() 48 비트교육센터

C/SDK와 MFC의 비교 (cont’d) Instance initialization – C/SDK : 존재 – MFC : 존재,

C/SDK와 MFC의 비교 (cont’d) Instance initialization – C/SDK : 존재 – MFC : 존재, 그러나 언제 실행? Message handling – C/SDK : 존재 – MFC : 존재, 그러나 어떻게 command-routing, message-dispatch? Member functions + Message map Afx. Wnd. Proc() : 공통 window procedure �항상 시작점이다. 49 비트교육센터

Basic MFC Application Components Windows application의 두 가지 components – Message pump – Window

Basic MFC Application Components Windows application의 두 가지 components – Message pump – Window procedure MFC에서의 구현 방법 – CWin. Application을 나타내는 class application-specific : 초기화, window 생성, 메시지 루프 – CWnd Window를 나타내는 class window-specific : 메시지 핸들링 50 비트교육센터

CWin. App (“Afx. Win. h”) CWin. App : public CWin. Thread { public: //

CWin. App (“Afx. Win. h”) CWin. App : public CWin. Thread { public: // Constructor CWin. App(LPCTSTR lpsz. App. Name = NULL); name // app name defaults to EXE // Attributes // Startup args (do not change) HINSTANCE m_h. Instance; HINSTANCE m_h. Prev. Instance; // not used LPTSTR m_lp. Cmd. Line; int m_n. Cmd. Show; // Running args (can be changed in Init. Instance) LPCTSTR m_psz. App. Name; // human readable name // (from constructor or AFX_IDS_APP_TITLE) 51 비트교육센터

public: // set in constructor to override default LPCTSTR m_psz. Exe. Name; // executable

public: // set in constructor to override default LPCTSTR m_psz. Exe. Name; // executable name (no spaces) LPCTSTR m_psz. Help. File. Path; // default based on module path LPCTSTR m_psz. Profile. Name; // default based on app name // Overridables // hooks for your initialization code virtual BOOL Init. Application(); void Set. Current. Handles(); // overrides for implementation virtual BOOL Init. Instance(); virtual int Exit. Instance(); // return app exit code virtual int Run(); virtual BOOL On. Idle(LONG l. Count); // return TRUE if more idle processing virtual LRESULT Process. Wnd. Proc. Exception (CException* e, const MSG* p. Msg); 52 비트교육센터

public: virtual ~CWin. App(); protected: //{{AFX_MSG(CWin. App) afx_msg void On. App. Exit(); afx_msg void

public: virtual ~CWin. App(); protected: //{{AFX_MSG(CWin. App) afx_msg void On. App. Exit(); afx_msg void On. Update. Recent. File. Menu(CCmd. UI* p. Cmd. UI); afx_msg BOOL On. Open. Recent. File(UINT n. ID); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; 53 비트교육센터

CWin. App AFXWIN. h 멤버 변수와 멤버 함수 – Win. Main()에 전달된 command line

CWin. App AFXWIN. h 멤버 변수와 멤버 함수 – Win. Main()에 전달된 command line parameter 를 관리할 변수 m_h. Instance : the current instance handle m_h. Prev. Instance : the previous instance handle m_lp. Cmd. Line : the command line parameters m_n. Cmd. Show : the show window flag 54 비트교육센터

CWin. App (cont’d) – m_psz. App. Name : application name – 관련 pointer m_psz.

CWin. App (cont’d) – m_psz. App. Name : application name – 관련 pointer m_psz. Exe. Name : executable file name m_psz. Help. File. Path : the path to help file m_psz. Profile. Name : application profiles name – 프로그램 실행 시 주어진 command line parameter 유지 CCommand. Line. Info class 이용 (AFXWIN. H) 55 비트교육센터

CWin. App (cont’d) – – Init. Instance() : instance-specific 초기화 Exit. Instance() : instance

CWin. App (cont’d) – – Init. Instance() : instance-specific 초기화 Exit. Instance() : instance 종료 시 처리 Run() : message pump 수행 On. Idle() : Message queue가 비었을 때, Run 함수에 의해 호출 56 비트교육센터

CWnd AFXWIN. H 2가지 기능 수행 – Wrapping the regular Windows API 예: Create(),

CWnd AFXWIN. H 2가지 기능 수행 – Wrapping the regular Windows API 예: Create(), Show. Window(), … – Higher-level MFC-related functionality 예: default message handling 57 비트교육센터

CWnd ( 기능 1 ) Wrapping the Windows API – m_h. Wnd : regular

CWnd ( 기능 1 ) Wrapping the Windows API – m_h. Wnd : regular API-level window handle 을 나타내기 위한 멤버변수 – window handle을 인자로 갖는 거의 모든 API를 멤버 함수로 가진다. 예) API HWND h. Wnd; Show. Window(h. Wnd, SW_SHOWNORMAL); MFC CWnd * p. Wnd; p. Wnd->Show. Window(SW_SHOWNORMAL); – AFXWIN 2. INL : API 의 호출 _AFXWIN_INLINE BOOL CWnd: : Show. Window(int n. Cmd. Show) { ASSERT(: : Is. Window(m_h. Wnd)); return : : Show. Window(m_h. Wnd, n. Cmd. Show); } 58 비트교육센터

CWnd ( 기능 2 ) Higher-level MFC-related functionality – CObject -> CCmd. Target ->

CWnd ( 기능 2 ) Higher-level MFC-related functionality – CObject -> CCmd. Target -> CWnd – CObject derivation Dynamic run-time information Serialization – CCmd. Target derivation MFC’s message-routing scheme – Default message handling 제공 59 비트교육센터

예 : default message handling _AFXWIN_INLINE void CWnd: : On. Activate(UINT, CWnd*, BOOL) {

예 : default message handling _AFXWIN_INLINE void CWnd: : On. Activate(UINT, CWnd*, BOOL) { Default(); } LRESULT CWnd: : Default() { // call Def. Window. Proc with the last message _AFX_THREAD_STATE* p. Thread. State = _afx. Thread. State. Get. Data(); return Def. Window. Proc(p. Thread. State->m_last. Sent. Msg. message, p. Thread. State->m_last. Sent. Msg. w. Param, p. Thread. State->m_last. Sent. Msg. l. Param); } 60 비트교육센터

Turning Window Handles into Window Objects High Level Application MFC object CHandle. Map class

Turning Window Handles into Window Objects High Level Application MFC object CHandle. Map class Low Level Windows OS Window handle 61 비트교육센터

계층적 관계 High level : MFC object – application 입장에서는 MFC object를 이용 Low

계층적 관계 High level : MFC object – application 입장에서는 MFC object를 이용 Low level : Window handle – Windows OS는 handle을 이용 MFC는 어떤 handle에 어떤 object가 연결되어 있는지를 알아야 함 CHandle. Map class를 이용하여 구현 62 비트교육센터

CHandle. Map AFXSTAT_. H Mapping window handle to MFC object – Handle이 주어지면 해당

CHandle. Map AFXSTAT_. H Mapping window handle to MFC object – Handle이 주어지면 해당 object를 찾음 – Windows OS가 callback 함수를 호출할 때, window handle을 parameter로 호 출 – 그러나, MFC는 해당 CWnd- 파생 클래스 객체를 가지고 작업 63 비트교육센터

CHandle. Map (cont’d) 멤버변수 – CMap. Ptr. To. Ptr m_permanant. Map Permanent map 명시적으로

CHandle. Map (cont’d) 멤버변수 – CMap. Ptr. To. Ptr m_permanant. Map Permanent map 명시적으로 객체가 생성될 때 정보가 추가됨(CWnd’s: : Create()) 객체가 종료될 때 정보가 제거됨 (CWnd’s: : On. Nc. Destroy()) cf) WM_NCCREAT -> WM_CREAT -> … -> WM_DESTROY -> WM_NCDESTROY – CMap. Ptr. To. Ptr m_temporary. Map Temporary map 임시로 생성해야 할때(ex: CWnd: : Get. Active. Window()) -> 현재 활성화 되어 있는 오브젝트를 찾을때 사용 실제로는 CWnd: : Handle. Map 에서 필요할 때 생성 On. Idle()에서 삭제 => Delete. Temp. Map() 호출 64 비트교육센터

CHandle. Map (cont’d) 멤버함수 – CWnd: : From. Handle(HWND h. Wnd) 주어진 window handle에

CHandle. Map (cont’d) 멤버함수 – CWnd: : From. Handle(HWND h. Wnd) 주어진 window handle에 mapping되는 object의 pointer를 얻을 때 사용 h. Wnd를 wrap하고 있는 CWnd pointer return 만약 없으면 h. Wnd를 wrap하는 temporary CWnd return 획득하면 역으로 object를 통해 h. Wnd의 접근이 용이 ( CWnd: : m_h. Wnd 멤버 변수 ) 65 비트교육센터

Temporary map 예 “AFXWIN 2. INL” _AFXWIN_INLINE CWnd* PASCAL CWnd: : Get. Active. Window()

Temporary map 예 “AFXWIN 2. INL” _AFXWIN_INLINE CWnd* PASCAL CWnd: : Get. Active. Window() { return CWnd: : From. Handle(: : Get. Active. Window()); } “Wincore. cpp” CWnd* PASCAL CWnd: : From. Handle(HWND h. Wnd) { CHandle. Map* p. Map = afx. Map. HWND(TRUE); CWnd* p. Wnd = (CWnd*)p. Map->From. Handle(h. Wnd); return p. Wnd; } 66 비트교육센터

Temporary map 예 (cont’d) “Winhand. cpp” CObject* CHandle. Map: : From. Handle(HANDLE h) {

Temporary map 예 (cont’d) “Winhand. cpp” CObject* CHandle. Map: : From. Handle(HANDLE h) { if (h == NULL) return NULL; CObject* p. Object = Lookup. Permanent(h); if (p. Object != NULL) return p. Object; // return permanent one else if ((p. Object = Lookup. Temporary(h)) != NULL) { HANDLE* ph = (HANDLE*)((BYTE*)p. Object + m_n. Offset); ph[0] = h; if (m_n. Handles == 2) { ph[1] = h; } return p. Object; // return current temporary one } 67 비트교육센터

Temporary map 예 (cont’d) CObject* p. Temp = NULL; TRY { p. Temp =

Temporary map 예 (cont’d) CObject* p. Temp = NULL; TRY { p. Temp = m_p. Class->Create. Object(); m_temporary. Map. Set. At((LPVOID)h, p. Temp); } CATCH_ALL(e) { Afx. Set. New. Handler(pnh. Old. Handler); Afx. Enable. Memory. Tracking(b. Enable); THROW_LAST(); } END_CATCH_ALL Afx. Set. New. Handler(pnh. Old. Handler); Afx. Enable. Memory. Tracking(b. Enable); HANDLE* ph = (HANDLE*)((BYTE*)p. Temp + m_n. Offset); ph[0] = h; if (m_n. Handles == 2) ph[1] = h; return p. Temp; } 68 비트교육센터

Other Mapping AFX_MODULE_THREAD_STATE – m_pmap. HWND window handles CWnd objects – m_pmap. HMENU menu

Other Mapping AFX_MODULE_THREAD_STATE – m_pmap. HWND window handles CWnd objects – m_pmap. HMENU menu handles CMenu objects – m_pmap. HDC device context handles CDC objects – m_pmap. HGDIOBJ GDI object handles CGDIObjects – m_pmap. HIMAGELIST image list handles CImage. List objects 69 비트교육센터

Attaching & Detaching Window handles과 CWnd-derived objects를 연관시켜주는 함수 – CWnd: : Attach() 주어진

Attaching & Detaching Window handles과 CWnd-derived objects를 연관시켜주는 함수 – CWnd: : Attach() 주어진 window handle을 CWnd: : m_h. Wnd에 대입 MFC’s permanent map에 정보 추가 – CWnd: : Detach() CWnd: : m_h. Wnd를 NULL로 만듬 MFC’s permanent map에서 정보 제거 70 비트교육센터

CWnd: : Attach BOOL CWnd: : Attach(HWND h. Wnd. New) { ASSERT(m_h. Wnd ==

CWnd: : Attach BOOL CWnd: : Attach(HWND h. Wnd. New) { ASSERT(m_h. Wnd == NULL); // only attach once, detach on destroy ASSERT(From. Handle. Permanent(h. Wnd. New) == NULL); // must not already be in permanent map if (h. Wnd. New == NULL) return FALSE; CHandle. Map* p. Map = afx. Map. HWND(TRUE); ASSERT(p. Map != NULL); p. Map->Set. Permanent(m_h. Wnd = h. Wnd. New, this); Attach. Control. Site(p. Map); return TRUE; } 71 비트교육센터

CWnd: : Detach HWND CWnd: : Detach() { HWND h. Wnd = m_h. Wnd;

CWnd: : Detach HWND CWnd: : Detach() { HWND h. Wnd = m_h. Wnd; if (h. Wnd != NULL) { CHandle. Map* p. Map = afx. Map. HWND(); // don't create if not exist if (p. Map != NULL) p. Map->Remove. Handle(m_h. Wnd); m_h. Wnd = NULL; } m_p. Ctrl. Site = NULL; return h. Wnd; } 72 비트교육센터

주의 Multiple threads – Permanent(영구) , temporary map(임시) 모두 thread 단위로 저장 – 전달할

주의 Multiple threads – Permanent(영구) , temporary map(임시) 모두 thread 단위로 저장 – 전달할 경우 object 대신 HANDLE 을 보내는 것이 바람직 Thread 2 Thread 1 Window create 접근 불가 73 비트교육센터

Find Win. Main() APPCORE. CPP – CWin. App 생성자 호출 APPMODULE. CPP (여기에 정의)

Find Win. Main() APPCORE. CPP – CWin. App 생성자 호출 APPMODULE. CPP (여기에 정의) – _t. Win. Main() extern "C" int WINAPI _t. Win. Main(HINSTANCE h. Instance, HINSTANCE h. Prev. Instance, LPTSTR lp. Cmd. Line, int n. Cmd. Show) { // call shared/exported Win. Main return Afx. Win. Main(h. Instance, h. Prev. Instance, lp. Cmd. Line, n. Cmd. Show); } 74 비트교육센터

Find Win. Main() (cont’d) WINMAIN. CPP – Afx. Win. Main() int AFXAPI Afx. Win.

Find Win. Main() (cont’d) WINMAIN. CPP – Afx. Win. Main() int AFXAPI Afx. Win. Main(HINSTANCE h. Instance, HINSTANCE h. Prev. Instance, LPTSTR lp. Cmd. Line, int n. Cmd. Show) { int n. Return. Code = -1; CWin. Thread* p. Thread = Afx. Get. Thread(); CWin. App* p. App = Afx. Get. App(); // AFX internal initialization if (!Afx. Win. Init(h. Instance, h. Prev. Instance, lp. Cmd. Line, n. Cmd. Show)) goto Init. Failure; // App global initializations (rare) if (p. App != NULL && !p. App->Init. Application()) goto Init. Failure; 75 비트교육센터

Find Win. Main() (cont’d) // Perform specific initializations if (!p. Thread->Init. Instance()) { if

Find Win. Main() (cont’d) // Perform specific initializations if (!p. Thread->Init. Instance()) { if (p. Thread->m_p. Main. Wnd != NULL) { p. Thread->m_p. Main. Wnd->Destroy. Window(); } n. Return. Code = p. Thread->Exit. Instance(); goto Init. Failure; } n. Return. Code = p. Thread->Run(); Afx. Win. Term(); return n. Return. Code; } 76 비트교육센터

Find Win. Main() (cont’d) APPINIT. CPP – Afx. Win. Init() BOOL AFXAPI Afx. Win.

Find Win. Main() (cont’d) APPINIT. CPP – Afx. Win. Init() BOOL AFXAPI Afx. Win. Init(HINSTANCE h. Instance, HINSTANCE h. Prev. Instance, LPTSTR lp. Cmd. Line, int n. Cmd. Show) { // handle critical errors and avoid Windows message boxes Set. Error. Mode(0) | SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); // set resource handles AFX_MODULE_STATE* p. Module. State = Afx. Get. Module. State(); p. Module. State->m_h. Current. Instance. Handle = h. Instance; p. Module. State->m_h. Current. Resource. Handle = h. Instance; 77 비트교육센터

Find Win. Main() (cont’d) // fill in the initial state for the application CWin.

Find Win. Main() (cont’d) // fill in the initial state for the application CWin. App* p. App = Afx. Get. App(); if (p. App != NULL) { // Windows specific initialization (not done if no CWin. App) p. App->m_h. Instance = h. Instance; p. App->m_h. Prev. Instance = h. Prev. Instance; p. App->m_lp. Cmd. Line = lp. Cmd. Line; p. App->m_n. Cmd. Show = n. Cmd. Show; p. App->Set. Current. Handles(); } // initialize thread specific data (for main thread) if (!afx. Context. Is. DLL) Afx. Init. Thread(); return TRUE; } 78 비트교육센터

Find Win. Main() (cont’d) Init. Application() – application-specific, but do nothing Init. Instance() –

Find Win. Main() (cont’d) Init. Application() – application-specific, but do nothing Init. Instance() – instance-specific, virtual Run() 79 비트교육센터

CWin. App 생성자 CWin. App: : CWin. App(LPCTSTR lpsz. App. Name) { if (lpsz.

CWin. App 생성자 CWin. App: : CWin. App(LPCTSTR lpsz. App. Name) { if (lpsz. App. Name != NULL) m_psz. App. Name = _tcsdup(lpsz. App. Name); else m_psz. App. Name = NULL; // initialize CWin. Thread state AFX_MODULE_STATE* p. Module. State = _AFX_CMDTARGET_GETSTATE(); AFX_MODULE_THREAD_STATE* p. Thread. State = p. Module. State->m_thread; p. Thread. State->m_p. Current. Win. Thread = this; m_h. Thread = : : Get. Current. Thread(); m_n. Thread. ID = : : Get. Current. Thread. Id(); // initialize CWin. App state ASSERT(afx. Current. Win. App == NULL); // only one CWin. App object please p. Module. State->m_p. Current. Win. App = this; ASSERT(Afx. Get. App() == this); 80 비트교육센터

CWin. App 생성자 (cont’d) // in non-running state until Win. Main m_h. Instance =

CWin. App 생성자 (cont’d) // in non-running state until Win. Main m_h. Instance = NULL; m_psz. Help. File. Path = NULL; m_psz. Profile. Name = NULL; m_psz. Registry. Key = NULL; m_psz. Exe. Name = NULL; m_p. Recent. File. List = NULL; m_p. Doc. Manager = NULL; m_atom. App = m_atom. System. Topic = NULL; m_lp. Cmd. Line = NULL; m_p. Cmd. Info = NULL; // other initialization m_b. Help. Mode = FALSE; m_n. Safety. Pool. Size = 512; // default size } 81 비트교육센터

Init. Application() BOOL CWin. App: : Init. Application() { if (CDoc. Manager: : p.

Init. Application() BOOL CWin. App: : Init. Application() { if (CDoc. Manager: : p. Static. Doc. Manager != NULL) { if (m_p. Doc. Manager == NULL) m_p. Doc. Manager = CDoc. Manager: : p. Static. Doc. Manager; CDoc. Manager: : p. Static. Doc. Manager = NULL; } if (m_p. Doc. Manager != NULL) m_p. Doc. Manager->Add. Doc. Template(NULL); else CDoc. Manager: : b. Static. Init = FALSE; return TRUE; } 82 비트교육센터

Init. Instance() BOOL CWin. App: : Init. Instance() { return TRUE; } 83 비트교육센터

Init. Instance() BOOL CWin. App: : Init. Instance() { return TRUE; } 83 비트교육센터

Run() int CWin. Thread: : Run() { // for tracking the idle time state

Run() int CWin. Thread: : Run() { // for tracking the idle time state BOOL b. Idle = TRUE; LONG l. Idle. Count = 0; // acquire and dispatch messages until a WM_QUIT message for (; ; ) { // phase 1: check to see if we can do idle work while (b. Idle && !: : Peek. Message( &m_msg. Cur, NULL, PM_NOREMOVE)) { // call On. Idle while in b. Idle state if (!On. Idle(l. Idle. Count++)) b. Idle = FALSE; // assume "no idle" state } 84 비트교육센터

Run (cont’d) // phase 2: pump messages while available do { // pump message,

Run (cont’d) // phase 2: pump messages while available do { // pump message, but quit on WM_QUIT if (!Pump. Message()) return Exit. Instance(); // reset "no idle" state after pumping "normal" message if (Is. Idle. Message(&m_msg. Cur)) { b. Idle = TRUE; l. Idle. Count = 0; } } while (: : Peek. Message (&m_msg. Cur, NULL, PM_NOREMOVE)); } ASSERT(FALSE); // not reachable } 85 비트교육센터

MFC state information 프로그램 종료까지 유지되는 정보 AFX_MODULE_STATE class – AFXSTAT_. H – 보유하는

MFC state information 프로그램 종료까지 유지되는 정보 AFX_MODULE_STATE class – AFXSTAT_. H – 보유하는 정보 Main window handles Resource, module handles Memory allocation tracking ODBC support, OLE support, exception handling 86 비트교육센터

Hidden Cool Stuff 2 issues – window class의 등록 – Windows hook와 MFC window의

Hidden Cool Stuff 2 issues – window class의 등록 – Windows hook와 MFC window의 연결 87 비트교육센터

Registering Window Classes Windows application – OS 에 적어도 하나 이상의 window class를 등록해야만

Registering Window Classes Windows application – OS 에 적어도 하나 이상의 window class를 등록해야만 한다. window class – window의 기본적인 성질 정의 appearance ( via some flag ) behavior ( via a callback function ) 88 비트교육센터

Registering Window Classes (cont’d) MFC의 window class 등록 – 4개의 기본 window class 등록

Registering Window Classes (cont’d) MFC의 window class 등록 – 4개의 기본 window class 등록 regular child windows a control bar window an MDI frame window a window for an SDI or MDI child window – 기타 common controls 89 비트교육센터

Registering Window Classes (cont’d) WNDCLASSes and MFC Style of window Lpfn. Wnd. Proc Cb.

Registering Window Classes (cont’d) WNDCLASSes and MFC Style of window Lpfn. Wnd. Proc Cb. Cls. Extra Cb. Wnd. Extra HInstance HIcon HCursor Hbr. Background Lpsz. Menu. Name Lpsz. Class. Name window proc, must be Afx. Wnd. Proc not used ( 0 ) automatically filled with Afx. Get. Instance. Handle icon for frame window cursor for when mouse is over window background color not used ( NULL ) class name 90 비트교육센터

Registering Window Classes (cont’d) Afx. Wnd – – – Used for all child windows

Registering Window Classes (cont’d) Afx. Wnd – – – Used for all child windows (CWnd: : Create) Class style : CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW No icon Arrow cursor No background color Afx. Frame. Or. View – – – Used for frame windows and views Class style : CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW Icon AFX_IDI_STD_MDIFRAME Arrow cursor COLOR_WINDOW background color 91 비트교육센터

Registering Window Classes (cont’d) Afx. MDIFrame – – – Used for MDI frame window

Registering Window Classes (cont’d) Afx. MDIFrame – – – Used for MDI frame window (CMDIFrame. Wnd: : Create) Class style : CS_DBLCLKS Icon AFX_IDI_STD_MDIFRAME Arrow cursor No background color Afx. Control. Bar – – – Used for standard control bar implementation Class style : 0 No icon Arrow cursor Gray background color (COLOR_BTNFACE) 92 비트교육센터

Registering Window Classes (cont’d) Afx. Defer. Register. Class() – AFXIMPL. H Afx. End. Defer.

Registering Window Classes (cont’d) Afx. Defer. Register. Class() – AFXIMPL. H Afx. End. Defer. Register. Class() – WINCORE. CPP #define Afx. Defer. Register. Class(f. Class) Afx. End. Defer. Register. Class(f. Class) BOOL AFXAPI Afx. End. Defer. Register. Class(LONG f. To. Register); 93 비트교육센터

Class 등록 예 “WINCORE. CPP” BOOL CWnd: : Create. Ex(DWORD dw. Ex. Style, LPCTSTR

Class 등록 예 “WINCORE. CPP” BOOL CWnd: : Create. Ex(DWORD dw. Ex. Style, LPCTSTR lpsz. Class. Name, LPCTSTR lpsz. Window. Name, DWORD dw. Style, int x, int y, int n. Width, int n. Height, HWND h. Wnd. Parent, HMENU n. IDor. HMenu, LPVOID lp. Param) { // allow modification of several common create parameters CREATESTRUCT cs; cs. dw. Ex. Style = dw. Ex. Style; cs. lpsz. Class = lpsz. Class. Name; cs. lpsz. Name = lpsz. Window. Name; cs. style = dw. Style; cs. x = x; cs. y = y; cs. cx = n. Width; cs. cy = n. Height; cs. hwnd. Parent = h. Wnd. Parent; cs. h. Menu = n. IDor. HMenu; cs. h. Instance = Afx. Get. Instance. Handle(); cs. lp. Create. Params = lp. Param; 94 비트교육센터

Class 등록 예 (cont’d) if (!Pre. Create. Window(cs)) { Post. Nc. Destroy(); return FALSE;

Class 등록 예 (cont’d) if (!Pre. Create. Window(cs)) { Post. Nc. Destroy(); return FALSE; } Afx. Hook. Window. Create(this); HWND h. Wnd = : : Create. Window. Ex(cs. dw. Ex. Style, cs. lpsz. Class, cs. lpsz. Name, cs. style, cs. x, cs. y, cs. cx, cs. cy, cs. hwnd. Parent, cs. h. Menu, cs. h. Instance, cs. lp. Create. Params); if (h. Wnd == NULL) Get. Last. Error()); if (!Afx. Unhook. Window. Create()) Post. Nc. Destroy(); if (h. Wnd == NULL) return FALSE; ASSERT(h. Wnd == m_h. Wnd); // should have been set in send msg hook return TRUE; } 95 비트교육센터

Class 등록 예 (cont’d) BOOL CWnd: : Pre. Create. Window(CREATESTRUCT& cs) { if (cs.

Class 등록 예 (cont’d) BOOL CWnd: : Pre. Create. Window(CREATESTRUCT& cs) { if (cs. lpsz. Class == NULL) { // make sure the default window class is registered VERIFY(Afx. Defer. Register. Class(AFX_WND_REG)); // no WNDCLASS provided - use child window default ASSERT(cs. style & WS_CHILD); cs. lpsz. Class = _afx. Wnd; } return TRUE; } 96 비트교육센터

Device Contexts CDC – CPaint. DC painting 작업이 발생할 때 Begin. Paint() ~ End.

Device Contexts CDC – CPaint. DC painting 작업이 발생할 때 Begin. Paint() ~ End. Paint() – CWindow. DC 전체 스크린을 표시 (client area+frame) Get. Window. DC() ~ Release. DC() – CClient. DC Client area를 표시 Get. Client. DC() ~ Release. DC() – CMeta. File. DC 메타파일에 대한 그리기 작업 생성자 ~ Create() ~ Delete. Meta. File() 99 비트교육센터

Graphic Objects CGdi. Object : Base class – – – CPen CBrush CFont CBitmap

Graphic Objects CGdi. Object : Base class – – – CPen CBrush CFont CBitmap CPalette CRgn Win 32 API의 함수들을 wrapping 100 비트교육센터

예제 CMy. Wnd: : On. Paint() { CPaint. DC CPen* CPen paint. DC(this); p.

예제 CMy. Wnd: : On. Paint() { CPaint. DC CPen* CPen paint. DC(this); p. Old. Pen; blue. Pen(PS_SOLID, 25, RGB(0, 0, 255)); p. Old. Pen = paint. DC. Select. Object(&blue. Pen); paint. DC. Move. To(1, 1); paint. DC. Line. To(100, 100); paint. DC. Select. Object(p. Old. Pen); } 101 비트교육센터

Chapter 03 MFC에서의 Message 처리

Chapter 03 MFC에서의 Message 처리

Contents Introduction Window messages Message mapping MFC가 message map을 이용하는 방법 Message loop의 hooking

Contents Introduction Window messages Message mapping MFC가 message map을 이용하는 방법 Message loop의 hooking 103 비트교육센터

Introduction Message handling – C/SDK Switch/case 문을 통해 구현 – MFC Switch/case 문은 없다

Introduction Message handling – C/SDK Switch/case 문을 통해 구현 – MFC Switch/case 문은 없다 Callback function은 어떻게 정의되는가 104 비트교육센터

Basic Components MFC의 message handling 구조 – CCmd. Target class – Message maps MFC

Basic Components MFC의 message handling 구조 – CCmd. Target class – Message maps MFC message maps에 대한 의문 – – 어떻게 switch/case문을 대체하는가 어떤 data structure로 정의되는가 어떻게 message map이 작동하는가 어떻게 message가 연결되는가 105 비트교육센터

Window Messages (cont’d) 핸들링 클래스 – Windows message, control notification CWnd 로부터 파생된 클래스들

Window Messages (cont’d) 핸들링 클래스 – Windows message, control notification CWnd 로부터 파생된 클래스들 : HWND 를 포함 – Command message 다양한 종류 : CCmd. Target 로부터 파생된 클래스들 예) open 명령 핸들링 : application 108 비트교육센터

UI Objects and Command IDs 109 비트교육센터

UI Objects and Command IDs 109 비트교육센터

Message Handling in C/SDK Windows program의 정수 While (Get. Message(&msg, NULL, NULL)) { //

Message Handling in C/SDK Windows program의 정수 While (Get. Message(&msg, NULL, NULL)) { // Translates virtual key codes Translate. Message(&msg); // Dispatches message to window Dispatch. Message(&msg); } // Returns the value from Post. Quit. Message Return (msg. w. Param); 110 비트교육센터

Message Handling in C/SDK (cont’d) WNDCLASS ws; … ws. lpfn. Wnd. Proc = Wnd.

Message Handling in C/SDK (cont’d) WNDCLASS ws; … ws. lpfn. Wnd. Proc = Wnd. Proc; … Register. Class(ws); LRESULT Wnd. Proc(HWND hwnd, UINT message, WPARAM w. Param, LPARAM l. Param) { switch (message) { case WM_CREATE: … break; case WM_COMMAND: switch (w. Param) { case IDM_ABOUT: … } } 111 비트교육센터

Message Mapping Internals 두 부분으로 구성 – CCmd. Target Window message나 command를 받기 위해

Message Mapping Internals 두 부분으로 구성 – CCmd. Target Window message나 command를 받기 위해 반드시 상속받아야 하는 class – Message map Window message와 이를 처리하는 class member function을 연관시켜주는 mechanism 113 비트교육센터

CCmd. Target Class 메시지의 처리 – CCmd. Target의 파생 클래스 – 예 CWnd class

CCmd. Target Class 메시지의 처리 – CCmd. Target의 파생 클래스 – 예 CWnd class CDocument CWin. App 114 비트교육센터

Message Map Data structures – AFX_MSGMAP_ENTRY(AFXWIN. H) Message map table의 한 element(entry) Message에 대한

Message Map Data structures – AFX_MSGMAP_ENTRY(AFXWIN. H) Message map table의 한 element(entry) Message에 대한 정보와 message handler에 대한 정보를 저장 struct AFX_MSGMAP_ENTRY { UINT n. Message; // windows message UINT n. Code; // control code or WM_NOTIFY code UINT n. ID; // control ID (or 0 for windows messages) UINT n. Last. ID; // used for entries specifying a range of control id's UINT n. Sig; // signature type (action) or pointer to message # AFX_PMSG pfn; // routine to call (or special value) }; 115 비트교육센터

Message Map(contd. ) – AFX_MSGMAP(AFXWIN. H) 실제 message map struct AFX_MSGMAP { #ifdef _AFXDLL

Message Map(contd. ) – AFX_MSGMAP(AFXWIN. H) 실제 message map struct AFX_MSGMAP { #ifdef _AFXDLL const AFX_MSGMAP* (PASCAL* pfn. Get. Base. Map)(); #else const AFX_MSGMAP* p. Base. Map; #endif const AFX_MSGMAP_ENTRY* lp. Entries; }; 116 비트교육센터

Message Map Macros (AFXWIN. H) – DECLARE_MESSAGE_MAP Header file에서 정의 – BEGIN_MESSAGE_MAP / END_MESSAGE_MAP

Message Map Macros (AFXWIN. H) – DECLARE_MESSAGE_MAP Header file에서 정의 – BEGIN_MESSAGE_MAP / END_MESSAGE_MAP Implementation file에서 정의 #define DECLARE_MESSAGE_MAP() private: static const AFX_MSGMAP_ENTRY _message. Entries[]; protected: static AFX_DATA const AFX_MSGMAP message. Map; virtual const AFX_MSGMAP* Get. Message. Map() const; 117 비트교육센터

Message Map Macros (cont’d) #define BEGIN_MESSAGE_MAP(the. Class, base. Class)  const AFX_MSGMAP* the. Class:

Message Map Macros (cont’d) #define BEGIN_MESSAGE_MAP(the. Class, base. Class) const AFX_MSGMAP* the. Class: : Get. Message. Map() const { return &the. Class: : message. Map; } AFX_COMDAT AFX_DATADEF const AFX_MSGMAP the. Class: : message. Map = { &base. Class: : message. Map, &the. Class: : _message. Entries[0] }; AFX_COMDAT const AFX_MSGMAP_ENTRY the. Class: : _message. Entries[] = { #define END_MESSAGE_MAP() {0, 0, Afx. Sig_end, (AFX_PMSG)0 } }; 118 비트교육센터

Massage Map 예 class CTest. View : public Cview { protected: //{{AFX_MSG(CTest. View) afx_msg

Massage Map 예 class CTest. View : public Cview { protected: //{{AFX_MSG(CTest. View) afx_msg void On. LButton. Dbl. Clk(UINT n. Flags, Cpoint); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; class CTest. View : public Cview { protected: afx_msg void On. LButton. Dbl. Clk(UINT n. Flags, Cpoint); private: static const AFX_MSGMAP_ENTRY _message. Entries[]; protected: static const AFX_MSGMAP message. Map; virtual const AFX_MSGMAP* Get. Message. Map() const; }; 비트교육센터 119

Massage Map 예 (cont’d) BEGIN_MESSAGE_MAP(CTest. VIew, Cview) //{{AFX_MSG_MAP(CTest. View) ON_COMMAND(ID_STRING_CENTER, On. String. Center) ON_WM_LBUTTONDBLCLK()

Massage Map 예 (cont’d) BEGIN_MESSAGE_MAP(CTest. VIew, Cview) //{{AFX_MSG_MAP(CTest. View) ON_COMMAND(ID_STRING_CENTER, On. String. Center) ON_WM_LBUTTONDBLCLK() //}}AFX_MSG_MAP END_MESSAGE_MAP() const AFX_MSGMAP* CTest. View: : Get. Message. Map() const { return &CTest. View: : message. Map; } AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CTest. View: : message. Map = { &CView: : message. Map, &CTest. View: : _message. Entries[0] }; const AFX_MSGMAP_ENTRY CTest. VIew: : _message. Entries[] = { (BEGIN_MESSAGE_MAP) ON_COMMAND(ID_STRING_CENTER, On. String. Center) ON_WM_LBUTTONDBLCLK() {0, 0, Afx. Sig_end, (AFX_PMSG)0 } (END_MESSAGE_MAP) }; 비트교육센터 120

Message Map Entry Macro AFXMSG_. H #define ON_COMMAND(id, member. Fxn)  { WM_COMMAND, CN_COMMAND,

Message Map Entry Macro AFXMSG_. H #define ON_COMMAND(id, member. Fxn) { WM_COMMAND, CN_COMMAND, (WORD)id, Afx. Sig_vv, (AFX_PMSG)&member. Fxn }, userdefine(사용자가 지정한 이름 사용) #define ON_WM_LBUTTONDBLCLK() { WM_LBUTTONDBLCLK, 0, 0, 0, Afx. Sig_vwp, (AFX_PMSG)(AFX_PMSGW) (void (AFX_MSG_CALL CWnd: : *) (UINT, CPoint))&On. LButton. Dbl. Clk }, 만들어져 있는 이름을 사용 121 비트교육센터

Message Map Entry Macro (cont’d) Message Type Macro Form Predefined Windows messages ON_WM_XXXX Commands

Message Map Entry Macro (cont’d) Message Type Macro Form Predefined Windows messages ON_WM_XXXX Commands ON_COMMAND Update commands ON_UPDATE_COMMAND_UI Control notifications ON_XXXX User-defined message ON_MESSAGE Registered Windows message ON_REGISTERED_MESSAGE Range of command IDs ON_COMMAND_RANGE Range of command Ids for updating ON_UPDATE_COMMAND_UI_RANGE Range of control IDs ON_CONTROL_RANGE 122 비트교육센터

User-define Message // inside the class declaration afx_msg LRESULT On. My. Message(WPARAM w. Param,

User-define Message // inside the class declaration afx_msg LRESULT On. My. Message(WPARAM w. Param, LPARAM l. Param); For example: #define WM_MYMESSAGE (WM_USER + 100) BEGIN_MESSAGE_MAP(CMy. Wnd, CMy. Parent. Wnd. Class) ON_MESSAGE(WM_MYMESSAGE, On. My. Message) END_MESSAGE_MAP() CWnd* p. Wnd =. . . ; p. Wnd->Send. Message(WM_MYMESSAGE); 123 비트교육센터

Handlers for Message-Map Ranges 종류 – ON_COMMAND_RANGE – ON_UPDATE_COMMAND – ON_CONTROL_RANGE Message-Map Entry –

Handlers for Message-Map Ranges 종류 – ON_COMMAND_RANGE – ON_UPDATE_COMMAND – ON_CONTROL_RANGE Message-Map Entry – ID 는 연속적이어야 한다. BEGIN_MESSAGE_MAP(CMy. App, CWin. App) ON_COMMAND_RANGE(ID_MYCMD_ONE, ID_MYCMD_TEN, On. Do. Something) ON_CONTROL_RANGE(BN_CLICKED, IDC_BUTTON 10, On. Button. Clicked) END_MESSAGE_MAP( ) 124 비트교육센터

Handlers for Message-Map Ranges Handlers . . . void CMy. Dialog: : On. Button.

Handlers for Message-Map Ranges Handlers . . . void CMy. Dialog: : On. Button. Clicked( UINT n. ID ) { int n. Button = n. ID - IDC_BUTTON 1; ASSERT( n. Button >= 0 && n. Button < 10 ); //. . . } 125 비트교육센터

MFC의 Message Map이용 MFC-based program – 두 종류의 메시지를 처리 regular window messages –

MFC의 Message Map이용 MFC-based program – 두 종류의 메시지를 처리 regular window messages – WM_MOUSEMOVE, … commands – WM_COMMAND – Message-mapping architecture의 이해 두 종류 메시지를 각각 추적 126 비트교육센터

How to be wired 16 -bit version – Afx. Wnd. Proc() Message handling procedure로

How to be wired 16 -bit version – Afx. Wnd. Proc() Message handling procedure로 등록된 함수 32 -bit version – Def. Window. Proc() 가 message handler로 등록 – Message hook방법을 써서 결국에는 Afx. Wnd. Proc()가 message를 처리하게 함 – Hooking function _Afx. Cbt. Filter. Hook(), _Afx. Standard. Subclass() – 3 D Control을 지원하기 위함 127 비트교육센터

How to be wired (cont’d) “Win. Core. cpp” BOOL AFXAPI Afx. End. Defer. Register.

How to be wired (cont’d) “Win. Core. cpp” BOOL AFXAPI Afx. End. Defer. Register. Class(LONG f. To. Register) { // mask off all classes that are already registered AFX_MODULE_STATE* p. Module. State = Afx. Get. Module. State(); f. To. Register &= ~p. Module. State->m_f. Registered. Classes; if (f. To. Register == 0) return TRUE; LONG f. Registered. Classes = 0; // common initialization WNDCLASS wndcls; memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults wndcls. lpfn. Wnd. Proc = Def. Window. Proc; wndcls. h. Instance = Afx. Get. Instance. Handle(); wndcls. h. Cursor = afx. Data. hcur. Arrow; 128 비트교육센터

How to be wired (cont’d) BOOL CWnd: : Create. Ex(DWORD dw. Ex. Style, LPCTSTR

How to be wired (cont’d) BOOL CWnd: : Create. Ex(DWORD dw. Ex. Style, LPCTSTR lpsz. Class. Name, LPCTSTR lpsz. Window. Name, DWORD dw. Style, int x, int y, int n. Width, int n. Height, HWND h. Wnd. Parent, HMENU n. IDor. HMenu, LPVOID lp. Param) { … Afx. Hook. Window. Create(this); } void AFXAPI Afx. Hook. Window. Create(CWnd* p. Wnd) { if (p. Thread. State->m_h. Hook. Old. Cbt. Filter == NULL) { p. Thread. State->m_h. Hook. Old. Cbt. Filter = : : Set. Windows. Hook. Ex(WH_CBT, _Afx. Cbt. Filter. Hook, NULL, : : Get. Current. Thread. Id()); if (p. Thread. State->m_h. Hook. Old. Cbt. Filter == NULL) Afx. Throw. Memory. Exception(); } p. Thread. State->m_p. Wnd. Init = p. Wnd; } 129 비트교육센터

How to be wired (cont’d) LRESULT CALLBACK _Afx. Cbt. Filter. Hook(int code, WPARAM w.

How to be wired (cont’d) LRESULT CALLBACK _Afx. Cbt. Filter. Hook(int code, WPARAM w. Param, LPARAM l. Param) { … // subclass the window if not already wired to Afx. Wnd. Proc if (!b. Afx. Wnd. Proc) { // subclass the window with standard Afx. Wnd. Proc old. Wnd. Proc = (WNDPROC)Set. Window. Long(h. Wnd, GWL_WNDPROC, (DWORD)afx. Wnd. Proc); ASSERT(old. Wnd. Proc != NULL); *p. Old. Wnd. Proc = old. Wnd. Proc; } … } 130 비트교육센터

Message Handling Afx. Wnd. Proc()(WINCORE. CPP) – WM_QUERYAFXWNDPROC MFC’s message map을 사용하는 MFC window인지를

Message Handling Afx. Wnd. Proc()(WINCORE. CPP) – WM_QUERYAFXWNDPROC MFC’s message map을 사용하는 MFC window인지를 확인할 수 있는 message – 다른 message에 대해서는 Afx. Call. Wnd. Proc() 함수를 호출 LRESULT CALLBACK Afx. Wnd. Proc(HWND h. Wnd, UINT n. Msg, WPARAM w. Param, LPARAM l. Param) { if (n. Msg == WM_QUERYAFXWNDPROC) return 1; CWnd* p. Wnd = CWnd: : From. Handle. Permanent(h. Wnd); return Afx. Call. Wnd. Proc(p. Wnd, h. Wnd, n. Msg, w. Param, l. Param); } 131 비트교육센터

Message Handling (cont’d) Afx. Call. Wnd. Proc()(WINCORE. CPP) – Thread state 구조체에 message의 정보를

Message Handling (cont’d) Afx. Call. Wnd. Proc()(WINCORE. CPP) – Thread state 구조체에 message의 정보를 저장 – WM_INITDIALOG처리 Auto-center dialog위한 처리를 수행 – Window object의 window procedure호출 CWnd: : Window. Proc()(WINCORE. CPP) 내부적으로 On. Wnd. Msg()를 호출 On. Wnd. Msg()가 처리하지 못하면 CWnd: : Def. Window. Proc()를 호출 132 비트교육센터

Message Handling (cont’d) LRESULT AFXAPI Afx. Call. Wnd. Proc(CWnd* p. Wnd, HWND h. Wnd,

Message Handling (cont’d) LRESULT AFXAPI Afx. Call. Wnd. Proc(CWnd* p. Wnd, HWND h. Wnd, UINT n. Msg, WPARAM w. Param = 0, LPARAM l. Param = 0) { _AFX_THREAD_STATE* p. Thread. State = _afx. Thread. State. Get. Data(); MSG old. State = p. Thread. State->m_last. Sent. Msg; // save for nesting p. Thread. State->m_last. Sent. Msg. hwnd = h. Wnd; p. Thread. State->m_last. Sent. Msg. message = n. Msg; p. Thread. State->m_last. Sent. Msg. w. Param = w. Param; p. Thread. State->m_last. Sent. Msg. l. Param = l. Param; CRect rect. Old; DWORD dw. Style = 0; if (n. Msg == WM_INITDIALOG) _Afx. Pre. Init. Dialog(p. Wnd, &rect. Old, &dw. Style); // delegate to object's Window. Proc l. Result = p. Wnd->Window. Proc(n. Msg, w. Param, l. Param); // more special case for WM_INITDIALOG if (n. Msg == WM_INITDIALOG) _Afx. Post. Init. Dialog(p. Wnd, rect. Old, dw. Style); p. Thread. State->m_last. Sent. Msg = old. State; return l. Result; } 133 비트교육센터

Message Handling (cont’d) CWnd: : Wndow. Proc()(WINCORE. CPP) – virtual 이므로 override 가능 –

Message Handling (cont’d) CWnd: : Wndow. Proc()(WINCORE. CPP) – virtual 이므로 override 가능 – 성능 향상을 위해 message-mapping system을 거치지 않고 처리해야 하는 메 시지에 대한 핸들링 가능 “Win. Core. Cpp” LRESULT CWnd: : Window. Proc(UINT message, WPARAM w. Param, LPARAM l. Param) { // On. Wnd. Msg does most of the work, except for Def. Window. Proc call LRESULT l. Result = 0; if (!On. Wnd. Msg(message, w. Param, l. Param, &l. Result)) l. Result = Def. Window. Proc(message, w. Param, l. Param); return l. Result; } 134 비트교육센터

Message Handling (cont’d) CWnd: : On. Wnd. Msg()(WINCORE. CPP) – 특별히 처리하는 message WM_COMMAND,

Message Handling (cont’d) CWnd: : On. Wnd. Msg()(WINCORE. CPP) – 특별히 처리하는 message WM_COMMAND, WM_NOTIFY WM_ACTIVATE, WM_SETCURSOR – 기타 다른 message들은 message map을 이용하여 해당 message handler를 호 출 135 비트교육센터

Message Handling (cont’d) BOOL CWnd: : On. Wnd. Msg(UINT message, WPARAM w. Param, LPARAM

Message Handling (cont’d) BOOL CWnd: : On. Wnd. Msg(UINT message, WPARAM w. Param, LPARAM l. Param, LRESULT* p. Result) { // special case for commands if (message == WM_COMMAND) { if (On. Command(w. Param, l. Param)) { l. Result = 1; goto LReturn. True; } return FALSE; } // special case for notifies if (message == WM_NOTIFY) { } // special case for activation if (message == WM_ACTIVATE) { } // special case for set cursor HTERROR if (message == WM_SETCURSOR ) { } 136 비트교육센터

Message Handling (cont’d) const AFX_MSGMAP* p. Message. Map; p. Message. Map = Get. Message.

Message Handling (cont’d) const AFX_MSGMAP* p. Message. Map; p. Message. Map = Get. Message. Map(); UINT i. Hash; i. Hash = (LOWORD((DWORD)p. Message. Map) ^ message) & (i. Hash. Max-1); Afx. Lock. Globals(CRIT_WINMSGCACHE); AFX_MSG_CACHE* p. Msg. Cache; p. Msg. Cache = &_afx. Msg. Cache[i. Hash]; const AFX_MSGMAP_ENTRY* lp. Entry; if (message == p. Msg. Cache->n. Msg && p. Message. Map == p. Msg. Cache>p. Message. Map) { … } else { // not in cache, look for it p. Msg. Cache->n. Msg = message; p. Msg. Cache->p. Message. Map = p. Message. Map; for (/* p. Message. Map already init'ed */; p. Message. Map != NULL; p. Message. Map = p. Message. Map->p. Base. Map) { Afx. Find. Message. Entry(); } 137 비트교육센터

Message Handling Trace 두가지 종류의 message – Regular window message WM_MOUSEMOVE – Command message

Message Handling Trace 두가지 종류의 message – Regular window message WM_MOUSEMOVE – Command message 메뉴나 control이 보내는 message WM_COMMAND 서로 다른 방식으로 처리 – CWnd: : On. Wnd. Msg()참고 138 비트교육센터

Handling WM_COMMAND 가정 – Main frame의 메뉴 명령 수행 CWnd: : On. Wnd. Msg()함수에서

Handling WM_COMMAND 가정 – Main frame의 메뉴 명령 수행 CWnd: : On. Wnd. Msg()함수에서 – CWnd: : On. Command()함수 호출 CWnd: : On. Command() – Virtual function(Framework이 적절한 version의 함수를 호출함) – CFrame. Wnd: : On. Command() On-line help에 관한 것이면 해당 기능 수행 아니면 CWnd: : On. Command()함수 호출 139 비트교육센터

Handling WM_COMMAND (cont’d) “Win. Frm. cpp” BOOL CFrame. Wnd: : On. Command(WPARAM w. Param,

Handling WM_COMMAND (cont’d) “Win. Frm. cpp” BOOL CFrame. Wnd: : On. Command(WPARAM w. Param, LPARAM l. Param) { HWND h. Wnd. Ctrl = (HWND)l. Param; UINT n. ID = LOWORD(w. Param); CFrame. Wnd* p. Frame. Wnd = Get. Top. Level. Frame(); ASSERT_VALID(p. Frame. Wnd); if (p. Frame. Wnd->m_b. Help. Mode&&h. Wnd. Ctrl==NULL&&n. ID!=ID_HELP&& n. ID!= ID_DEFAULT_HELP && n. ID != ID_CONTEXT_HELP) { // route as help if (!Send. Message(WM_COMMANDHELP, 0, HID_BASE_COMMAND+n. ID)) Send. Message(WM_COMMAND, ID_DEFAULT_HELP); return TRUE; } // route as normal command return CWnd: : On. Command(w. Param, l. Param); } 140 비트교육센터

Handling WM_COMMAND (cont’d) “Win. Core. Cpp” BOOL CWnd: : On. Command(WPARAM w. Param, LPARAM

Handling WM_COMMAND (cont’d) “Win. Core. Cpp” BOOL CWnd: : On. Command(WPARAM w. Param, LPARAM l. Param) { if (h. Wnd. Ctrl == NULL) else { if (_afx. Thread. State->m_h. Lockout. Notify. Window == m_h. Wnd) return TRUE; // locked out - ignore control notification // reflect notification to child window control if (Reflect. Last. Msg(h. Wnd. Ctrl)) return TRUE; // eaten by child // zero IDs for normal commands are not allowed if (n. ID == 0) return FALSE; } return On. Cmd. Msg(n. ID, n. Code, NULL); } 141 비트교육센터

Handling WM_COMMAND (cont’d) CWnd: : On. Command()(WINCORE. CPP) – LPARAM을 조사 – 만약 control이

Handling WM_COMMAND (cont’d) CWnd: : On. Command()(WINCORE. CPP) – LPARAM을 조사 – 만약 control이 보낸 message이면 control에게 다시 message를 reflect한 후 return – 아니면 CWnd: : On. Cmd. Msg()(virtual function)함수 호출 142 비트교육센터

Handling WM_COMMAND (cont’d) “Win. Frm. cpp” BOOL CFrame. Wnd: : On. Cmd. Msg(UINT n.

Handling WM_COMMAND (cont’d) “Win. Frm. cpp” BOOL CFrame. Wnd: : On. Cmd. Msg(UINT n. ID, int n. Code, void* p. Extra, AFX_CMDHANDLERINFO* p. Handler. Info) { CPush. Routing. Frame push(this); // pump through current view FIRST CView* p. View = Get. Active. View(); if (p. View != NULL && p. View->On. Cmd. Msg(n. ID, n. Code, p. Extra, p. Handler. Info)) return TRUE; // then pump through frame if (CWnd: : On. Cmd. Msg(n. ID, n. Code, p. Extra, p. Handler. Info)) return TRUE; // last but not least, pump through app CWin. App* p. App = Afx. Get. App(); if (p. App != NULL && p. App->On. Cmd. Msg(n. ID, n. Code, p. Extra, p. Handler. Info)) return TRUE; return FALSE; } 143 비트교육센터

Handling WM_COMMAND (cont’d) “View. Core. cpp” BOOL CView: : On. Cmd. Msg(UINT n. ID,

Handling WM_COMMAND (cont’d) “View. Core. cpp” BOOL CView: : On. Cmd. Msg(UINT n. ID, int n. Code, void* p. Extra, AFX_CMDHANDLERINFO* p. Handler. Info) { // first pump through pane if (CWnd: : On. Cmd. Msg(n. ID, n. Code, p. Extra, p. Handler. Info)) return TRUE; // then pump through document if (m_p. Document != NULL) { // special state for saving view before routing to document CPush. Routing. View push(this); return m_p. Document->On. Cmd. Msg(n. ID, n. Code, p. Extra, p. Handler. Info); } return FALSE; } 144 비트교육센터

Handling WM_COMMAND (cont’d) “Doc. Core. cpp” BOOL CDocument: : On. Cmd. Msg(UINT n. ID,

Handling WM_COMMAND (cont’d) “Doc. Core. cpp” BOOL CDocument: : On. Cmd. Msg(UINT n. ID, int n. Code, void* p. Extra, AFX_CMDHANDLERINFO* p. Handler. Info) { if (CCmd. Target: : On. Cmd. Msg(n. ID, n. Code, p. Extra, p. Handler. Info)) return TRUE; // otherwise check template if (m_p. Doc. Template != NULL && m_p. Doc. Template->On. Cmd. Msg(n. ID, n. Code, p. Extra, p. Handler. Info)) return TRUE; return FALSE; } 145 비트교육센터

Handling WM_COMMAND (cont’d) CFrame. Wnd: : On. Cmd. Msg()(WINFRM. CPP) – 다음의 순서로 해당

Handling WM_COMMAND (cont’d) CFrame. Wnd: : On. Cmd. Msg()(WINFRM. CPP) – 다음의 순서로 해당 On. Cmd. Msg()함수를 호출 Active view’s document Main frame window Application 146 비트교육센터

Handling WM_COMMAND (cont’d) “Cmd. Targ. cpp” BOOL CCmd. Target: : On. Cmd. Msg(UINT n.

Handling WM_COMMAND (cont’d) “Cmd. Targ. cpp” BOOL CCmd. Target: : On. Cmd. Msg(UINT n. ID, int n. Code, void* p. Extra, AFX_CMDHANDLERINFO* p. Handler. Info) { for (p. Message. Map = Get. Message. Map(); p. Message. Map != NULL; p. Message. Map = p. Message. Map->p. Base. Map) { lp. Entry = Afx. Find. Message. Entry (p. Message. Map->lp. Entries, n. Msg, n. Code, n. ID); if (lp. Entry != NULL) { return _Afx. Dispatch. Cmd. Msg(this, n. ID, n. Code, lp. Entry->pfn, p. Extra, lp. Entry->n. Sig, p. Handler. Info); } } return FALSE; // not handled } 148 비트교육센터

Handling WM_COMMAND (cont’d) CCmd. Target: : On. Cmd. Msg()(CMDTARG. CPP) – Message map을 보고

Handling WM_COMMAND (cont’d) CCmd. Target: : On. Cmd. Msg()(CMDTARG. CPP) – Message map을 보고 message handler를 찾음 – 찾게 되면 _Afx. Dispatch. Cmd. Msg()함수를 호출하여 해당 handler를 실행시킴 _Afx. Dispatch. Cmd. Msg()(CMDTARG. CPP) – Function signature에 따라 다른 동작을 수행 Regular command Extended command Visual Basic control 등등 149 비트교육센터

Handling WM_COMMAND (cont’d) Frame window일 때의 처리과정 정리 – – – – – 1.

Handling WM_COMMAND (cont’d) Frame window일 때의 처리과정 정리 – – – – – 1. Afx. Wnd. Proc() 1. 1 Afx. Call. Wnd. Proc() 1. 2 CWnd: : Window. Proc() 1. 2. 1 CWnd: : On. Wnd. Msg() CFrame. Wnd: : On. Command() CFrame. Wnd: : On. Cmd. Msg() CCmd. Target: : On. Cmd. Msg() _Afx. Dispatch. Cmd. Msg() CMain. Fram: : On~() 150 비트교육센터

Handling WM_COMMAND (cont’d) Document일 때의 처리과정 정리 – – – Afx. Wnd. Proc() Afx.

Handling WM_COMMAND (cont’d) Document일 때의 처리과정 정리 – – – Afx. Wnd. Proc() Afx. Call. Wnd. Proc() CWnd: : Window. Proc() CWnd: : On. Wnd. Msg() CFrame. Wnd: : On. Command() CFrame. Wnd: : On. Cmd. Msg() CView: : On. Cmd. Msg() Cdocument: : On. Cmd. Msg() CCmd. Target: : On. Cmd. Msg() _Afx. Dispatch. Cmd. Msg() CMy. Doc: : On~() 151 비트교육센터

Handling WM_COMMAND (cont’d) View일 때의 처리과정 정리 – – – Afx. Wnd. Proc() Afx.

Handling WM_COMMAND (cont’d) View일 때의 처리과정 정리 – – – Afx. Wnd. Proc() Afx. Call. Wnd. Proc() CWnd: : Window. Proc() CWnd: : On. Wnd. Msg() CFrame. Wnd: : On. Command() CFrame. Wnd: : On. Cmd. Msg() CView: : On. Cmd. Msg() CCmd. Target: : On. Cmd. Msg() _Afx. Dispatch. Cmd. Msg() CMy. View: : On~() 152 비트교육센터

Handling WM_COMMAND (cont’d) App일 때의 처리과정 정리 – – – – Afx. Wnd. Proc()

Handling WM_COMMAND (cont’d) App일 때의 처리과정 정리 – – – – Afx. Wnd. Proc() Afx. Call. Wnd. Proc() CWnd: : Window. Proc() CWnd: : On. Wnd. Msg() CFrame. Wnd: : On. Command() CCmd. Target: : On. Cmd. Msg() _Afx. Dispatch. Cmd. Msg() CMy. App: : On~() 153 비트교육센터

Handling WM_COMMAND (cont’d) Dialog Box일 때의 처리과정 정리 – – – – Afx. Wnd.

Handling WM_COMMAND (cont’d) Dialog Box일 때의 처리과정 정리 – – – – Afx. Wnd. Proc() Afx. Call. Wnd. Proc() CWnd: : Window. Proc() CWnd: : On. Wnd. Msg() CDialog: : On. Cmd. Msg() CCmd. Target: : On. Cmd. Msg() _Afx. Dispatch. Cmd. Msg() CAbout. Dlg: : On~() 154 비트교육센터

Handling Regular Window Message Command message일 때와 처음의 과정은 비슷 – – Afx. Wnd.

Handling Regular Window Message Command message일 때와 처음의 과정은 비슷 – – Afx. Wnd. Proc() Afx. Call. Wnd. Proc() Window. Proc() On. Wnd. Msg() 이 함수 안에서 message handler를 찾기 위해Afx. Find. Message. Entry()를 호출 156 비트교육센터

Handling Regular Window Message (cont’d) Afx. Find. Message. Entry() – 두 버전이 있음. Assembly

Handling Regular Window Message (cont’d) Afx. Find. Message. Entry() – 두 버전이 있음. Assembly language : intel-based machine C language : otherwise – Message map에서 해당 핸들러가 있는지 검색 – END_MESSAGE_MAP에 의해 생성된 table의 끝까지 검색 157 비트교육센터

Handling Regular Window Message (cont’d) Command message와의 차이점 – Command message는 handler를 찾기 위해서

Handling Regular Window Message (cont’d) Command message와의 차이점 – Command message는 handler를 찾기 위해서 여러 장소를 옮겨다님 – Regular message는 On. Wnd. Msg()에서 handler를 찾으면 바로 해당 handler를 호출하고, 아니면 Def. Window. Proc()를 이용 158 비트교육센터

Handling Regular Window Message (cont’d) 예) View에서 WM_SIZE message처리 과정 – – – Afx.

Handling Regular Window Message (cont’d) 예) View에서 WM_SIZE message처리 과정 – – – Afx. Wnd. Proc() Afx. Call. Wnd. Proc() CWnd: : Window. Proc() CWnd: : On. Wnd. Msg() CSdiapp. View: : On. Size() 159 비트교육센터

Other Kinds of Messages 지금까지 살펴 본 메시지 종류 – WM_COMMAND – Window messages(WM_SIZE,

Other Kinds of Messages 지금까지 살펴 본 메시지 종류 – WM_COMMAND – Window messages(WM_SIZE, WM_MOVE, …) 그 이외의 메시지 종류 – WM_NOTIFY – WM_ACTIVATE – WM_SETCURSOR 160 비트교육센터

Other Kinds of Messages (cont’d) WM_NOTIFY – Control이 보내는 message – 항상 notify message

Other Kinds of Messages (cont’d) WM_NOTIFY – Control이 보내는 message – 항상 notify message – 반면, WM_COMMAND command이거나 notify message 161 비트교육센터

Other Kinds of Messages (cont’d) CWnd: : On. Wnd. Msg()에서 // special case for

Other Kinds of Messages (cont’d) CWnd: : On. Wnd. Msg()에서 // special case for notifies if (message == WM_NOTIFY) { NMHDR* p. NMHDR = (NMHDR*)l. Param; if (p. NMHDR->hwnd. From != NULL && On. Notify(w. Param, l. Param, &l. Result)) goto LReturn. True; return FALSE; … } struct NMHDR { HWND hwnd. From; UINT id. From; UINT code; // control that sent notification // ID of control // notification code 162 비트교육센터

Other Kinds of Messages (cont’d) “Wincore. cpp” BOOL CWnd: : On. Notify(WPARAM, LPARAM l.

Other Kinds of Messages (cont’d) “Wincore. cpp” BOOL CWnd: : On. Notify(WPARAM, LPARAM l. Param, LRESULT* p. Result) { NMHDR* p. NMHDR = (NMHDR*)l. Param; HWND h. Wnd. Ctrl = p. NMHDR->hwnd. From; // get the child ID from the window itself UINT n. ID = _Afx. Get. Dlg. Ctrl. ID(h. Wnd. Ctrl); int n. Code = p. NMHDR->code; if (_afx. Thread. State->m_h. Lockout. Notify. Window == m_h. Wnd) return TRUE; // locked out - ignore control notification // reflect notification to child window control if (Reflect. Last. Msg(h. Wnd. Ctrl, p. Result)) return TRUE; // eaten by child AFX_NOTIFY notify; notify. p. Result = p. Result; notify. p. NMHDR = p. NMHDR; return On. Cmd. Msg(n. ID, MAKELONG(n. Code, WM_NOTIFY), &notify, NULL); } 163 비트교육센터

Other Kinds of Messages (cont’d) BOOL PASCAL CWnd: : Reflect. Last. Msg(HWND h. Wnd.

Other Kinds of Messages (cont’d) BOOL PASCAL CWnd: : Reflect. Last. Msg(HWND h. Wnd. Child, LRESULT* p. Result) { CHandle. Map* p. Map = afx. Map. HWND(); CWnd* p. Wnd = (CWnd*)p. Map->Lookup. Permanent(h. Wnd. Child); if (p. Wnd == NULL) { // check if the window is an OLE control … return FALSE; } return p. Wnd->Send. Child. Notify. Last. Msg(p. Result); } 164 비트교육센터

Other Kinds of Messages (cont’d) BOOL CWnd: : Send. Child. Notify. Last. Msg(LRESULT* p.

Other Kinds of Messages (cont’d) BOOL CWnd: : Send. Child. Notify. Last. Msg(LRESULT* p. Result) { _AFX_THREAD_STATE* p. Thread. State = _afx. Thread. State. Get. Data(); return On. Child. Notify(p. Thread. State->m_last. Sent. Msg. message, p. Thread. State->m_last. Sent. Msg. w. Param, p. Thread. State->m_last. Sent. Msg. l. Param, p. Result); } 165 비트교육센터

Other Kinds of Messages (cont’d) Message reflection – On. Wnd. Msg()에서 On. Notify()를 호출

Other Kinds of Messages (cont’d) Message reflection – On. Wnd. Msg()에서 On. Notify()를 호출 – On. Nofity()는 다시 On. Child. Notify()를 호출하여 control로 message를 다시 보 냄 – 결국에는 control이 parent에 의존하지 않고 자신의 일을 처리하게 함 166 비트교육센터

Other Kinds of Messages (cont’d) – WM_ACTIVATE On. Wnd. Msg()함수에서 _Afx. Handle. Activate()를 호출

Other Kinds of Messages (cont’d) – WM_ACTIVATE On. Wnd. Msg()함수에서 _Afx. Handle. Activate()를 호출 – WM_SETCURSOR On. Wnd. Msg()함수에서 _Afx. Handle. Set. Cursor()함수 호출 167 비트교육센터

Message Loop Hooking Message loop hooking – Message가 해당 handler에 의해 처리되기 전에 어떠한

Message Loop Hooking Message loop hooking – Message가 해당 handler에 의해 처리되기 전에 어떠한 작업을 하고 싶을때 – Pre. Translate. Message() CWin. App: : Pre. Translate. Message() – CWin. App: : Run()함수는 message가 message pump에 의해 처리되기 전에 위 함수를 호출 – TRUE를 return하면 message pump는 해당 message에 관해서는 처리 를 하지 않음 CWnd: : Pre. Translate. Message() 169 비트교육센터

Message Loop Hooking (cont’d) “THRDCORE. cpp” int CWin. Thread: : Run() { // for

Message Loop Hooking (cont’d) “THRDCORE. cpp” int CWin. Thread: : Run() { // for tracking the idle time state BOOL b. Idle = TRUE; LONG l. Idle. Count = 0; // acquire and dispatch messages until a WM_QUIT message is received. for (; ; ) { // phase 1: check to see if we can do idle work while (b. Idle && !: : Peek. Message(&m_msg. Cur, NULL, PM_NOREMOVE)) { // call On. Idle while in b. Idle state if (!On. Idle(l. Idle. Count++)) b. Idle = FALSE; // assume "no idle" state } 170 비트교육센터

Message Loop Hooking (cont’d) // phase 2: pump messages while available do { //

Message Loop Hooking (cont’d) // phase 2: pump messages while available do { // pump message, but quit on WM_QUIT if (!Pump. Message()) return Exit. Instance(); // reset "no idle" state after pumping "normal" message if (Is. Idle. Message(&m_msg. Cur)) { b. Idle = TRUE; l. Idle. Count = 0; } } while (: : Peek. Message(&m_msg. Cur, NULL, PM_NOREMOVE)); } ASSERT(FALSE); // not reachable } 171 비트교육센터

Message Loop Hooking (cont’d) BOOL CWin. Thread: : Pump. Message() { ASSERT_VALID(this); if (!:

Message Loop Hooking (cont’d) BOOL CWin. Thread: : Pump. Message() { ASSERT_VALID(this); if (!: : Get. Message(&m_msg. Cur, NULL, NULL)) { } // process this message if (m_msg. Cur. message != WM_KICKIDLE && !Pre. Translate. Message(&m_msg. Cur)) { : : Translate. Message(&m_msg. Cur); : : Dispatch. Message(&m_msg. Cur); } return TRUE; } 172 비트교육센터

Message Loop Hooking (cont’d) BOOL CWin. Thread: : Pre. Translate. Message(MSG* p. Msg) {

Message Loop Hooking (cont’d) BOOL CWin. Thread: : Pre. Translate. Message(MSG* p. Msg) { // if this is a thread-message, short-circuit this function if (p. Msg->hwnd == NULL && Dispatch. Thread. Message. Ex(p. Msg)) return TRUE; // walk from target to main window CWnd* p. Main. Wnd = Afx. Get. Main. Wnd(); if (CWnd: : Walk. Pre. Translate. Tree(p. Main. Wnd->Get. Safe. Hwnd(), p. Msg)) return TRUE; // in case of modeless dialogs, last chance route through main // window's accelerator table if (p. Main. Wnd != NULL) { CWnd* p. Wnd = CWnd: : From. Handle(p. Msg->hwnd); if (p. Wnd->Get. Top. Level. Parent() != p. Main. Wnd) return p. Main. Wnd->Pre. Translate. Message(p. Msg); } return FALSE; // no special processing } 173 비트교육센터

Message Loop Hooking (cont’d) “Win. Core. Cpp” BOOL PASCAL CWnd: : Walk. Pre. Translate.

Message Loop Hooking (cont’d) “Win. Core. Cpp” BOOL PASCAL CWnd: : Walk. Pre. Translate. Tree(HWND h. Wnd. Stop, MSG* p. Msg){ // walk from the target window up to the h. Wnd. Stop window checking // if any window wants to translate this message for (HWND h. Wnd=p. Msg->hwnd; h. Wnd != NULL; h. Wnd=: : Get. Parent(h. Wnd)){ CWnd* p. Wnd = CWnd: : From. Handle. Permanent(h. Wnd); if (p. Wnd != NULL) { // target window is a C++ window if (p. Wnd->Pre. Translate. Message(p. Msg)) return TRUE; } // got to h. Wnd. Stop window without interest if (h. Wnd == h. Wnd. Stop) break; } return FALSE; // no special processing } 174 비트교육센터