Click here to load reader
Upload
mikasi
View
348
Download
27
Embed Size (px)
DESCRIPTION
MFC Internals. C ontents. 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. Chapter 01 MFC 개관. Contents. - PowerPoint PPT Presentation
Citation preview
MFC Internals
비트교육센터[2]
비트교육센터
ContentsChapter 01MFC 개관
Chapter 02MFC 와 C/SDK
Chapter 03MFC 에서의 Message 처리
Chapter 04MFC Utility Class
Chapter 05모든 길은 Cobject 로 통한다
Chapter 06MFC Dialog 와 Control Dialog
Chapter 07MFC 의 Document/View Architecture
Chapter 01MFC 개관
비트교육센터[4]
비트교육센터
ContentsApplication Frameworks 정의MFC 의 역사MFC 의 설계 목적MFC 의 구성MFC code basics
비트교육센터[5]
비트교육센터
Application Frameworks
Framework– 특정 영역의 작업을 도와 주는 class 집합
Application Framework– 특정 OS 의 application 개발 작업을 도와 주는 class 집합
MFC (Microsoft Foundation Classes)– Windows 용 application 개발 작업을 도와 주는 framework
비트교육센터[6]
비트교육센터
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
비트교육센터[7]
비트교육센터
MFC 의 역사 (cont’d)1992 년
– MFC version 1.0C/C++ version 7.0 과 함께 나옴60 개가 넘는 Windows application 개발을 위한 class 포함일반 목적의 여러 class 포함완벽하지 못했음
– 개발자로부터 많은 불평을 받음
비트교육센터[8]
비트교육센터
MFC 의 역사 (cont’d)1993 년
– MFC version 2.0Visual C++ version 1.0 과 Windows NT 와 함께 나옴100 개가 넘는 class 포함새로 포함된 내용
– 새로운 application architecture– 새로운 high-level abstractions
비트교육센터[9]
비트교육센터
MFC 의 역사 (cont’d)1993 년 말
– MFC version 2.5Visual C++ version 1.5 와 함께 나옴OLE2.0 과 ODBC 지원이 추가됨
1994 년
– MFC version 3.0Thread 에 대한 기능이 보강됨
비트교육센터[10]
비트교육센터
MFC 의 역사 (cont’d)1995 년
– MFC version 3.1추가된 기능
– Simple Messaging Application Programming Interface(MAPI)– WinSock
– MFC version 4.0Visual C++ version 4.0 과 함께 나옴개발환경의 발전 , 재사용성의 향상
비트교육센터[11]
비트교육센터
MFC 의 역사 (cont’d)1997 년
– MFC version 4.2Visual 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
비트교육센터[12]
비트교육센터
MFC 의 역사 (cont’d)
MFC version 과 Visual C++ version
Microsoft Visual C++ version 6.06.0
Microsoft C/C++ version 7.01.0
Microsoft Visual C++ version 1.02.0
Microsoft Visual C++ version 1.02.1
Microsoft Visual C++ version 1.52.5
Microsoft Visual C++ version 2.03.0
Microsoft Visual C++ version 2.13.1
Microsoft Visual C++ version 2.23.2
Microsoft Visual C++ versions 4.0 and 4.14.0
Microsoft Visual C++ versions 4.2 and 5.04.2
Visual C++ versionMFC version
비트교육센터[13]
비트교육센터
MFC 설계 목적AFX 그룹의 설계 목적
– Real-World Application– Simplifying the Windows API– Using the existing knowledge of Windows– Foundation for large-scale applications– Small and fast framework
비트교육센터[14]
비트교육센터
MFC 의 구성MFC class 의 분류
– General-purpose classes– Windows API classes– Application framework classes– High-level abstractions– Operating System Extension
비트교육센터[15]
비트교육센터
MFC 의 구성 (cont’d)General-purpose Class
– 프로그램의 일반적 용도를 위한 class
(1) CObject classMFC 의 최상위 class
run-time type information, serialization, diagnostic function, support for dynamic creation 4 가지 중요한 기능 제공
CArchive, CDumpContext, CRuntimeClass 등과 연계되어 작용
비트교육센터[16]
비트교육센터
MFC 의 구성 (cont’d)(2) Exception-handling class
memory, I/O error 발생 시 처리CException : base classCArchiveException, CFileExceptionCMemoryException, CResourceExceptionCNotSupportedException, CUserExceptionCOleException, CDBException
비트교육센터[17]
비트교육센터
MFC 의 구성 (cont’d)(3) Collection class
Array : CByteArray, CWordArray, CDWordArray, CPtrArray, CObArray, CStringArray, CUnitArray
Linked list : CObList, CPtrList, CStringList
Map : CMapPtrToWord, CMapPtrToPtr, CMapStringToOb, CMapStringToPtr, CMapStringToString, CMapWordToOb, CMapWordToPtr
비트교육센터[18]
비트교육센터
MFC 의 구성 (cont’d)(4) Dynamic string class
CStringconcatenation, comparison, assignment 등의 기본 연산 제공
(5) File classCFile, CStdioFile, CMemFile추상적으로 disk 상의 파일 제어 , 실제로는 memory 상의 파일 제어
비트교육센터[19]
비트교육센터
MFC 의 구성 (cont’d)(6) Time class
CTime, CTimeSpan(7) 기타
CPoint, CSize, CRect : Windows structure
비트교육센터[20]
비트교육센터
MFC 의 구성 (cont’d)Windows API class
(1) Application 관련 class CCmdTarget : message 처리
CCmdUI : user interface 의 update
CWinThread : MFC program 의 실행 thread 를 의미 , 즉 program 의 main 을 포함
CWinApp : CWinThread 의 파생 class 으로서 standard windows application 을 표현
비트교육센터[21]
비트교육센터
MFC 의 구성 (cont’d)– Window 관련 class
CWnd : CCmdTarget 의 파생 class 이므로 message 를 handle. 윈도우를 다루는 API 포함 .
CFramWnd, CMDIFrameWnd : main frame window 로서 message 를 받는 첫 윈도우
CDialog, 공통다이어로그박스 (CFileDialog, CColorDialog, CFontDialog, CPrintDialog, CFindReplaceDialog)
CDataExchange : DDX/DDV
비트교육센터[22]
비트교육센터
MFC 의 구성 (cont’d)CPropertySheet, CPropertyPageControls : CButton, CEdit, …Cmenu
– GDI 관련 classCDC, CPaintDC, CWindowDC, CClientDC, CMetaFileDCCPen, CBrush, CFont, ...
비트교육센터[23]
비트교육센터
MFC 의 구성 (cont’d)Application framework class
– Document/View ArchitectureCDocTemplate, CSingleDocTemplate, CMultiDocTemplate : document
와 view 를 연결CDocument : data 를 관리CView : data 를 redering 하여 보여 줌
– Context-Sensitive Help
비트교육센터[24]
비트교육센터
MFC 의 구성 (cont’d)High-level abstraction
– Enhanced ViewsCScrollView, CFormViewCEditView, CListView, CRichEditView, CTreeView
– Splitter WindowCSplitterWnd : dynamic, static
– Control ViewsCToolBar, CStatusBar, CDialogBar
비트교육센터[25]
비트교육센터
MFC Code BasicsClass Declaration Subsections
– MFC library 개발 팀의 코딩 규칙Not based public/protected/privatePrivate 변수는 거의 사용하지 않는다 .
– Header / source file// Constructors// Attributes// Operations// Overridables// Implementation
비트교육센터[26]
비트교육센터
Example of Commentsclass CStdioFile : public CFile{ DECLARE_DYNAMIC(CStdioFile)public:// Constructors CStdioFile();...// Attributes FILE* m_pStream; // stdio FILE...// Operations virtual void WriteString(LPCTSTR lpsz);... virtual LPTSTR ReadString(LPTSTR lpsz, UINT nMax);...// Implementationpublic:...};
비트교육센터[27]
비트교육센터
MFC CommentsClass 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 함수들
비트교육센터[28]
비트교육센터
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
비트교육센터[29]
비트교육센터
MFC Code Basics (cont’d)Variable Naming (common)
Pointer to a functionlpfnHookProc lpfncallback
hWnd hhandle
Z indicates NULL terminated.lpszFileName lpszLPSTR
lpWnd lpFAR *
pWnd p* (pointer)
dwPackedmessage dwDWORD
lAxisRatio lLONG
wListID wWORD
nMyUnsigned nUINT
nVariableCnt nint
blsSending bBOOL
cDirSeparator cchar
CommentExamplePrefixType
비트교육센터[30]
비트교육센터
MFC Code Basics (cont’d)
Variable Naming (MFC extensions)
pWndDialog pWndCWnd*
WndControl WndCWnd
strFind strCString
szRectangle szCSize
ptMouseClick ptCPoint
rectScroll rectCRect
ExamplePrefixClass
비트교육센터[31]
비트교육센터
MFC Code Basics (cont’d)
Symbol Naming
1-0x6FFFIDC_HANDIDC_Cursor resourceIcon resource
1-0x6FFFIDB_SMILEYIDB_Bitmap resource
0x2001-0x26FFHIDD_HELP_ABOUTHIDD_Dialog resource help context ID(for context-sensitive help)
1-0x6FFFIDD_ABOUTIDD_Dialog resource
1-0x6FFFIDR_MAINFRAMEIDR_Shared by multiple resources
RangeExamplePrefixType
비트교육센터[32]
비트교육센터
MFC Code Basics (cont’d)
Symbol Naming
8-0xDFFFIDC_COMBO1IDC_Control in dialog template
1-0x7FFFIDS_ERROR12IDS_String resource
0x3008-0x3DFFHIDP_FATALERRORHIDP_Message box help context
8-0xDFFFIDP_FATALERRORIDP_Message box prompt
0x1800-0x1DFFHID_CIRCLE_TOOLHID_Command help context
0x8000-0xDFFFID_CIRCLE_TOOLID_Menu or toolbar command
RangeExamplePrefixType
Chapter 02MFC 와 C/CDK
비트교육센터[34]
비트교육센터
ContentsIntroductionMFC versus C/SDKBasic Application Components
– CWinApp– CWnd– Window handles & Window objects
Find WinMain()Hidden Cool Stuff
– Registering Window Classes– MFC’s Windows Hooks– MFC’s Message Pump
MFC’s GDI Support
비트교육센터[35]
비트교육센터
IntroductionMFC
– 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
WinMain, window class 등록 , 메시지 루프 , …
비트교육센터[36]
비트교육센터
IssueMFC 가 어떻게 Windows application 을 만드는가
– The application itself( 응용프로그램 그 자체 ) - main thread – Windows– Message handling( 위의 두가지를 연결해줌 )– The Graphics Device Interface (GDI)
비트교육센터[37]
비트교육센터
MFC vs. C/SDKMotivation
– 모든 Windows application 은 다음 2 개의 component 를 포함한다 .main application itselfmessage 를 핸들하는 하나 이상의 window
– C/SDK 개발 환경copy & pasteTime-consuming & inefficient
– C++/MFC 개발 환경OOP 활용 : inheritance & encaptulation필요한 부분만 변경
비트교육센터[38]
비트교육센터
Boilerplate Code왜 필요한가 ?
– Windows is event-driven OSImposes a grate deal of overhead
– Windows OSH/W 와 응용 프로그램을 연결하는 위치Application 에게 발생하는 이벤트를 알림이벤트를 다루기 위해 상당한 양의 코드가 항상 필요
비트교육센터[39]
비트교육센터
메시지 처리를 위한 작업들Set up a message handler and register it
– RegiserClass() : 윈도우 프로시져 등록
Windows 가 application 의 instance 들을 추적
application 은 Windows 에게 메시지를 요청 (ask) 하고 , 처리 (dispatch) 한다 .
application 이 종료될 때까지 위 작업을 반복한다 .
비트교육센터[40]
비트교육센터
Application 의 준비WinMain() 함수
– 프로그램의 시작점– 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 를 제공 최소한 WM_DESTROY 처리 -> WM_QUIT 생성
비트교육센터[41]
비트교육센터
Application 의 기본 요소
Main 함수Application specific
Initialization(Window class 등록 )
Instance specificInitialization
(Main window(UI) 생성 , 보여줌 )
Message loop
MessageHandler
비트교육센터[42]
비트교육센터
Source 1 : C/SDK#include <windows.h>HANDLE hInst; /* current instance */LRESULT CALLBACK MainWndProc(HANDLE hWnd, UINT message, WPARAM wParam, LPARAM
lParam){
switch(message) {case WM_LBUTTONDOWN:
MessageBox(hWnd,“Left mouse button clicked”, NULL, MB_OK);break;
case WM_DESTROY:PostQuitMessage(0);break;
default: /* Passes it on if unprocessed */return (DefWindowProc(hWnd, message, wParam, lParam));
}return 0;
}
비트교육센터[43]
비트교육센터
BOOL InitApplication(HANDLE hInstance){
WNDCLASS wc;
wc.style = 0; /* Class style(s) */wc.lpfnWndProc = MainWndProc; /* Message handler */wc.cbClsExtra = 0; /* No per-class extra data */wc.cbWndExtra = 0; /* No per-window extra data */wc.hInstance = hInstance; /* Application that owns the class*/wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = GetStockObject(WHITE_BRUSH);wc.lpszMenuName = NULL; /* Name of menu */wc.lpszClassName = “MinimalWClass”; /* Name of window class */
return (RegisterClass(&wc));}
비트교육센터[44]
비트교육센터
BOOL InitInstance(HANDLE hInstance, int nCmdShow) {
HWND hWnd; /* Main window handle */hInst = hInstance; // needed for loading resources //hWnd = CreateWindow(
“MinimalWClass”, /* Window class */“Minimal”, /* Caption */WS_OVERLAPPEDWINDOW, /* Window style */CW_USEDEFAULT, /* Default horizontal pos. */CW_USEDEFAULT, /* Default vertical pos. */CW_USEDEFAULT, /* Default width */CW_USEDEFAULT, /* Default height. */NULL, /* No parent */NULL, /* Use the window class menu */hInstance, /* This instance owns the window. */NULL);
비트교육센터[45]
비트교육센터
if (!hWnd)return (FALSE);
ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);return (TRUE);
}
비트교육센터[46]
비트교육센터
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
MSG msg; /* message */if (!hPrevInstance) { /* First instance? */
if (!InitApplication(hInstance)) /* Shared stuff */return (FALSE); /* cannot initialize */
}
if (!InitInstance(hInstance, nCmdShow))return (FALSE);
while (GetMessage(&msg, NULL, 0, 0)) {TranslateMessage(&msg);DispatchMessage(&msg);
} return(msg.wParam);/*Returns the value from PostQuitMessage*/}
비트교육센터[47]
비트교육센터
Source 2 : MFC#include <afxwin.h> // MFC 주요 클래스 선언
class CGenericApp : public CWinApp {public:virtual BOOL InitInstance();
};
class CGenericWindow : public CFrameWnd {public:CGenericWindow() {
Create(NULL, “Generic”);}
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);DECLARE_MESSAGE_MAP()
};
비트교육센터[48]
비트교육센터
BEGIN_MESSAGE_MAP(CGenericWindow, CFrameWnd)ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
void CGenericWindow::OnLButtonDown(UINT nFlags, CPoint point) {MessageBox(“Left mouse button pressed…”, NULL, MB_OK);
}
BOOL CGenericApp::InitInstance() {m_pMainWnd = new CGenericWindow();m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();return TRUE;
}
CGenericApp GenericApp;
비트교육센터[49]
비트교육센터
WinMain() 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, PreTranslateMessage()
C/SDK 와 MFC 의 비교
비트교육센터[50]
비트교육센터
C/SDK 와 MFC 의 비교 (cont’d)
Instance initialization– C/SDK : 존재– MFC : 존재 , 그러나 언제 실행 ?
Message handling– C/SDK : 존재– MFC : 존재 , 그러나 어떻게 command-routing, message-dispatch?
Member functions + Message mapAfxWndProc() : 공통 window procedure
항상 시작점이다 .
비트교육센터[51]
비트교육센터
Basic MFC Application ComponentsWindows application 의 두 가지 components
– Message pump– Window procedure
MFC 에서의 구현 방법– CWinApp
Application 을 나타내는 classapplication-specific : 초기화 , window 생성 , 메시지 루프
– CWndWindow 를 나타내는 class window-specific : 메시지 핸들링
비트교육센터[52]
비트교육센터
CWinApp (“AfxWin.h”)CWinApp : public CWinThread{public:// Constructor
CWinApp(LPCTSTR lpszAppName = NULL); // app name defaults to EXE name
// Attributes// Startup args (do not change)HINSTANCE m_hInstance;HINSTANCE m_hPrevInstance; // not usedLPTSTR m_lpCmdLine;int m_nCmdShow;
// Running args (can be changed in InitInstance)LPCTSTR m_pszAppName; // human readable name
// (from constructor or AFX_IDS_APP_TITLE)
비트교육센터[53]
비트교육센터
public: // set in constructor to override defaultLPCTSTR m_pszExeName; // executable name (no spaces)LPCTSTR m_pszHelpFilePath; // default based on module pathLPCTSTR m_pszProfileName; // default based on app name
// Overridables// hooks for your initialization codevirtual BOOL InitApplication();void SetCurrentHandles();// overrides for implementationvirtual BOOL InitInstance();virtual int ExitInstance(); // return app exit codevirtual int Run();virtual BOOL OnIdle(LONG lCount);
// return TRUE if more idle processingvirtual LRESULT ProcessWndProcException
(CException* e, const MSG* pMsg);
비트교육센터[54]
비트교육센터
public:virtual ~CWinApp();
protected://{{AFX_MSG(CWinApp)afx_msg void OnAppExit();afx_msg void OnUpdateRecentFileMenu(CCmdUI* pCmdUI);afx_msg BOOL OnOpenRecentFile(UINT nID);//}}AFX_MSGDECLARE_MESSAGE_MAP()
};
비트교육센터[55]
비트교육센터
CWinApp
AFXWIN.h멤버 변수와 멤버 함수
– WinMain() 에 전달된 command line parameter 를 관리할 변수m_hInstance : the current instance handlem_hPrevInstance : the previous instance handlem_lpCmdLine : the command line parametersm_nCmdShow : the show window flag
비트교육센터[56]
비트교육센터
CWinApp (cont’d)– m_pszAppName : application name– 관련 pointer
m_pszExeName : executable file namem_pszHelpFilePath : the path to help filem_pszProfileName : application profiles name
– 프로그램 실행 시 주어진 command line parameter 유지CCommandLineInfo class 이용 (AFXWIN.H)
비트교육센터[57]
비트교육센터
CWinApp (cont’d)
– InitInstance() : instance-specific 초기화– ExitInstance() : instance 종료 시 처리– Run() : message pump 수행– OnIdle() : Message queue 가 비었을 때 , Run 함수에 의해 호출
비트교육센터[58]
비트교육센터
CWnd
AFXWIN.H
2 가지 기능 수행– Wrapping the regular Windows API
예 : Create(), ShowWindow(), …– Higher-level MFC-related functionality
예 : default message handling
비트교육센터[59]
비트교육센터
CWnd ( 기능 1 )Wrapping the Windows API
– m_hWnd : regular API-level window handle 을 나타내기 위한 멤버변수– window handle 을 인자로 갖는 거의 모든 API 를 멤버 함수로 가진다 .
예 )
– AFXWIN2.INL : API 의 호출
APIHWND hWnd;ShowWindow(hWnd,SW_SHOWNORMAL);
MFCCWnd * pWnd;pWnd->ShowWindow(SW_SHOWNORMAL);
_AFXWIN_INLINE BOOL CWnd::ShowWindow(int nCmdShow){ ASSERT(::IsWindow(m_hWnd)); return ::ShowWindow(m_hWnd, nCmdShow); }
비트교육센터[60]
비트교육센터
CWnd ( 기능 2 )
Higher-level MFC-related functionality– CObject -> CCmdTarget -> CWnd– CObject derivation
Dynamic run-time informationSerialization
– CCmdTarget derivationMFC’s message-routing scheme
– Default message handling 제공
비트교육센터[61]
비트교육센터
_AFXWIN_INLINE void CWnd::OnActivate(UINT, CWnd*, BOOL){ Default(); }
LRESULT CWnd::Default(){ // call DefWindowProc with the last message _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData(); return DefWindowProc(pThreadState->m_lastSentMsg.message,
pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam);
}
예 : default message handling
비트교육센터[62]
비트교육센터
Turning Window Handles into Window Objects
Application
MFC object
Windows OS
Window handle
CHandleMap class
HighLevel
LowLevel
비트교육센터[63]
비트교육센터
계층적 관계High level : MFC object
– application 입장에서는 MFC object 를 이용
Low level : Window handle– Windows OS 는 handle 을 이용
MFC 는 어떤 handle 에 어떤 object 가 연결되어 있는지를 알아야 함
CHandleMap class 를 이용하여 구현
비트교육센터[64]
비트교육센터
CHandleMapAFXSTAT_.H
Mapping window handle to MFC object– Handle 이 주어지면 해당 object 를 찾음– Windows OS 가 callback 함수를 호출할 때 , window handle 을 parameter 로 호출– 그러나 , MFC 는 해당 CWnd- 파생 클래스 객체를 가지고 작업
비트교육센터[65]
비트교육센터
CHandleMap (cont’d)멤버변수
– CMapPtrToPtr m_permanantMapPermanent map명시적으로 객체가 생성될 때 정보가 추가됨 (CWnd’s::Create())객체가 종료될 때 정보가 제거됨 (CWnd’s::OnNcDestroy())cf) WM_NCCREAT -> WM_CREAT -> … -> WM_DESTROY -> WM_NCD
ESTROY
– CMapPtrToPtr m_temporaryMapTemporary map임시로 생성해야 할때 (ex: CWnd::GetActiveWindow())
-> 현재 활성화 되어 있는 오브젝트를 찾을때 사용실제로는 CWnd::HandleMap 에서 필요할 때 생성OnIdle() 에서 삭제 => DeleteTempMap() 호출
비트교육센터[66]
비트교육센터
CHandleMap (cont’d)
멤버함수– CWnd::FromHandle(HWND hWnd)
주어진 window handle 에 mapping 되는 object 의 pointer 를 얻을 때 사용
hWnd 를 wrap 하고 있는 CWnd pointer return만약 없으면 hWnd 를 wrap 하는 temporary CWnd return획득하면 역으로 object 를 통해 hWnd 의 접근이 용이 ( CWnd::m_hWnd 멤버 변수 )
비트교육센터[67]
비트교육센터
Temporary map 예
“AFXWIN2.INL”_AFXWIN_INLINE CWnd* PASCAL CWnd::GetActiveWindow()
{ return CWnd::FromHandle(::GetActiveWindow()); }
“Wincore.cpp”CWnd* PASCAL CWnd::FromHandle(HWND hWnd){
CHandleMap* pMap = afxMapHWND(TRUE); CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd);return pWnd;
}
비트교육센터[68]
비트교육센터
Temporary map 예 (cont’d)“Winhand.cpp”CObject* CHandleMap::FromHandle(HANDLE h){
if (h == NULL)return NULL;
CObject* pObject = LookupPermanent(h);if (pObject != NULL)
return pObject; // return permanent oneelse if ((pObject = LookupTemporary(h)) != NULL){
HANDLE* ph = (HANDLE*)((BYTE*)pObject + m_nOffset);ph[0] = h;if (m_nHandles == 2){
ph[1] = h;}return pObject; // return current temporary one
}
비트교육센터[69]
비트교육센터
Temporary map 예 (cont’d)CObject* pTemp = NULL;TRY {
pTemp = m_pClass->CreateObject();m_temporaryMap.SetAt((LPVOID)h, pTemp);
}CATCH_ALL(e) {
AfxSetNewHandler(pnhOldHandler);AfxEnableMemoryTracking(bEnable);THROW_LAST();
}END_CATCH_ALLAfxSetNewHandler(pnhOldHandler);AfxEnableMemoryTracking(bEnable);HANDLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset);ph[0] = h;if (m_nHandles == 2) ph[1] = h;return pTemp;
}
비트교육센터[70]
비트교육센터
Other MappingAFX_MODULE_THREAD_STATE
– m_pmapHWNDwindow handles CWnd objects
– m_pmapHMENUmenu handles CMenu objects
– m_pmapHDCdevice context handles CDC objects
– m_pmapHGDIOBJGDI object handles CGDIObjects
– m_pmapHIMAGELISTimage list handles CImageList objects
비트교육센터[71]
비트교육센터
Attaching & DetachingWindow handles 과 CWnd-derived objects 를 연관시켜주는 함수
– CWnd::Attach()주어진 window handle 을 CWnd::m_hWnd 에 대입MFC’s permanent map 에 정보 추가
– CWnd::Detach()CWnd::m_hWnd 를 NULL 로 만듬MFC’s permanent map 에서 정보 제거
비트교육센터[72]
비트교육센터
CWnd::AttachBOOL CWnd::Attach(HWND hWndNew){
ASSERT(m_hWnd == NULL); // only attach once, detach on destroy
ASSERT(FromHandlePermanent(hWndNew) == NULL);// must not already be in permanent map
if (hWndNew == NULL) return FALSE;CHandleMap* pMap = afxMapHWND(TRUE);ASSERT(pMap != NULL);
pMap->SetPermanent(m_hWnd = hWndNew, this);AttachControlSite(pMap);return TRUE;
}
비트교육센터[73]
비트교육센터
CWnd::DetachHWND CWnd::Detach(){
HWND hWnd = m_hWnd;if (hWnd != NULL){
CHandleMap* pMap = afxMapHWND(); // don't create if not exist
if (pMap != NULL)pMap->RemoveHandle(m_hWnd);
m_hWnd = NULL;}m_pCtrlSite = NULL;return hWnd;
}
비트교육센터[74]
비트교육센터
주의
Multiple threads– Permanent( 영구 ) , temporary map( 임시 ) 모두 thread 단위로 저장– 전달할 경우 object 대신 HANDLE 을 보내는 것이 바람직
Window createWindow create
Thread 1Thread 1
Window createWindow create
Thread 2Thread 2
접근 불가접근 불가
비트교육센터[75]
비트교육센터
Find WinMain()APPCORE.CPP
– CWinApp 생성자 호출
APPMODULE.CPP ( 여기에 정의 )– _tWinMain()
extern "C" int WINAPI_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow){
// call shared/exported WinMainreturn AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
비트교육센터[76]
비트교육센터
Find WinMain() (cont’d)WINMAIN.CPP
– AfxWinMain()
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{int nReturnCode = -1;CWinThread* pThread = AfxGetThread();CWinApp* pApp = AfxGetApp();// AFX internal initializationif (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
goto InitFailure;
// App global initializations (rare)if (pApp != NULL && !pApp->InitApplication())
goto InitFailure;
비트교육센터[77]
비트교육센터
Find WinMain() (cont’d)
// Perform specific initializationsif (!pThread->InitInstance()){
if (pThread->m_pMainWnd != NULL){
pThread->m_pMainWnd->DestroyWindow();}nReturnCode = pThread->ExitInstance();goto InitFailure;
}nReturnCode = pThread->Run();AfxWinTerm();return nReturnCode;
}
비트교육센터[78]
비트교육센터
Find WinMain() (cont’d)APPINIT.CPP
– AfxWinInit()
BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){ // handle critical errors and avoid Windows message boxes SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
// set resource handles AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); pModuleState->m_hCurrentInstanceHandle = hInstance; pModuleState->m_hCurrentResourceHandle = hInstance;
비트교육센터[79]
비트교육센터
Find WinMain() (cont’d)
// fill in the initial state for the application CWinApp* pApp = AfxGetApp(); if (pApp != NULL) {
// Windows specific initialization (not done if no CWinApp)pApp->m_hInstance = hInstance;pApp->m_hPrevInstance = hPrevInstance;pApp->m_lpCmdLine = lpCmdLine;pApp->m_nCmdShow = nCmdShow;pApp->SetCurrentHandles();
}
// initialize thread specific data (for main thread) if (!afxContextIsDLL) AfxInitThread(); return TRUE;}
비트교육센터[80]
비트교육센터
Find WinMain() (cont’d)InitApplication()
– application-specific, but do nothing
InitInstance()– instance-specific, virtual
Run()
비트교육센터[81]
비트교육센터
CWinApp 생성자
CWinApp::CWinApp(LPCTSTR lpszAppName){ if (lpszAppName != NULL) m_pszAppName = _tcsdup(lpszAppName); else m_pszAppName = NULL;
// initialize CWinThread state AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE(); AFX_MODULE_THREAD_STATE* pThreadState =
pModuleState->m_thread; pThreadState->m_pCurrentWinThread = this; m_hThread = ::GetCurrentThread(); m_nThreadID = ::GetCurrentThreadId();
// initialize CWinApp state ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please pModuleState->m_pCurrentWinApp = this; ASSERT(AfxGetApp() == this);
비트교육센터[82]
비트교육센터
CWinApp 생성자 (cont’d)// in non-running state until WinMainm_hInstance = NULL;m_pszHelpFilePath = NULL;m_pszProfileName = NULL;m_pszRegistryKey = NULL;m_pszExeName = NULL;m_pRecentFileList = NULL;m_pDocManager = NULL;m_atomApp = m_atomSystemTopic = NULL;m_lpCmdLine = NULL;m_pCmdInfo = NULL;// other initializationm_bHelpMode = FALSE;m_nSafetyPoolSize = 512; // default size
}
비트교육센터[83]
비트교육센터
InitApplication()BOOL CWinApp::InitApplication(){
if (CDocManager::pStaticDocManager != NULL){
if (m_pDocManager == NULL)m_pDocManager = CDocManager::pStaticDocManager;
CDocManager::pStaticDocManager = NULL;}
if (m_pDocManager != NULL)m_pDocManager->AddDocTemplate(NULL);
elseCDocManager::bStaticInit = FALSE;
return TRUE;}
비트교육센터[84]
비트교육센터
InitInstance()BOOL CWinApp::InitInstance(){
return TRUE;}
비트교육센터[85]
비트교육센터
Run()int CWinThread::Run(){
// for tracking the idle time stateBOOL bIdle = TRUE;LONG lIdleCount = 0;
// acquire and dispatch messages until a WM_QUIT message for (;;) {
// phase1: check to see if we can do idle workwhile (bIdle && !::PeekMessage(
&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)){
// call OnIdle while in bIdle stateif (!OnIdle(lIdleCount++))
bIdle = FALSE; // assume "no idle" state}
비트교육센터[86]
비트교육센터
Run (cont’d)// phase2: pump messages while availabledo {
// pump message, but quit on WM_QUITif (!PumpMessage()) return ExitInstance();// reset "no idle" state after pumping "normal" messageif (IsIdleMessage(&m_msgCur)){
bIdle = TRUE;lIdleCount = 0;
}} while (::PeekMessage
(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));}ASSERT(FALSE); // not reachable
}
비트교육센터[87]
비트교육센터
MFC state information프로그램 종료까지 유지되는 정보AFX_MODULE_STATE class
– AFXSTAT_.H– 보유하는 정보
Main window handlesResource, module handlesMemory allocation trackingODBC support, OLE support, exception handling
비트교육센터[88]
비트교육센터
Hidden Cool Stuff2 issues
– window class 의 등록– Windows hook 와 MFC window 의 연결
비트교육센터[89]
비트교육센터
Registering Window Classes
Windows application– OS 에 적어도 하나 이상의 window class 를 등록해야만 한다 .
window class– window 의 기본적인 성질 정의
appearance ( via some flag )behavior ( via a callback function )
비트교육센터[90]
비트교육센터
Registering Window Classes (cont’d)
MFC 의 window class 등록– 4 개의 기본 window class 등록
regular child windowsa control bar windowan MDI frame windowa window for an SDI or MDI child window
– 기타common controls
비트교육센터[91]
비트교육센터
Registering Window Classes (cont’d)
WNDCLASSes and MFC
Style Style of window
LpfnWndProc window proc, must be AfxWndProcCbClsExtra not used ( 0 )CbWndExtra not used ( 0 )HInstance automatically filled with AfxGetInstanceHandleHIcon icon for frame windowHCursor cursor for when mouse is over windowHbrBackground background colorLpszMenuName not used ( NULL )LpszClassName class name
비트교육센터[92]
비트교육센터
Registering Window Classes (cont’d)
AfxWnd– Used for all child windows (CWnd::Create)– Class style : CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW– No icon– Arrow cursor– No background color
AfxFrameOrView– 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
비트교육센터[93]
비트교육센터
Registering Window Classes (cont’d)
AfxMDIFrame– Used for MDI frame window (CMDIFrameWnd::Create)– Class style : CS_DBLCLKS– Icon Icon AFX_IDI_STD_MDIFRAME– Arrow cursor– No background color
AfxControlBar– Used for standard control bar implementation– Class style : 0– No icon– Arrow cursor– Gray background color (COLOR_BTNFACE)
비트교육센터[94]
비트교육센터
Registering Window Classes (cont’d)AfxDeferRegisterClass()
– AFXIMPL.H
AfxEndDeferRegisterClass()– WINCORE.CPP
#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister);
비트교육센터[95]
비트교육센터
Class 등록 예“WINCORE.CPP”BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
{// allow modification of several common create parametersCREATESTRUCT cs;cs.dwExStyle = dwExStyle;cs.lpszClass = lpszClassName;cs.lpszName = lpszWindowName;cs.style = dwStyle;cs.x = x; cs.y = y;cs.cx = nWidth; cs.cy = nHeight;cs.hwndParent = hWndParent;cs.hMenu = nIDorHMenu;cs.hInstance = AfxGetInstanceHandle();cs.lpCreateParams = lpParam;
비트교육센터[96]
비트교육센터
Class 등록 예 (cont’d)if (!PreCreateWindow(cs)) {
PostNcDestroy();return FALSE;
}AfxHookWindowCreate(this);HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
if (hWnd == NULL)GetLastError());if (!AfxUnhookWindowCreate()) PostNcDestroy();if (hWnd == NULL)return FALSE;ASSERT(hWnd == m_hWnd);
// should have been set in send msg hookreturn TRUE;
}
비트교육센터[97]
비트교육센터
Class 등록 예 (cont’d)BOOL CWnd::PreCreateWindow(CREATESTRUCT& cs){
if (cs.lpszClass == NULL){
// make sure the default window class is registeredVERIFY(AfxDeferRegisterClass(AFX_WND_REG));
// no WNDCLASS provided - use child window defaultASSERT(cs.style & WS_CHILD);cs.lpszClass = _afxWnd;
}return TRUE;
}
비트교육센터[98]
비트교육센터
MFC’s Message Pump
CWinApp::Run()– 이 함수가 실행되면서 실제 메시지 펌프가 동작하게 됨– 이는 CWinApp 가 CWinThread 로 부터 상속받기 때문에 가능한 것임– Thread 종류
Worker thread : 일반적으로 말하는 threadInterface thread : Message pump
비트교육센터[99]
비트교육센터
MFC’s GDI 지원GDI (Graphical Device Interface)
– Windows OS 상의 풍부한 그리기 작업– 장치 독립적 지원 : GDI + Device driver
DC (Device Context)– GDI 의 핵심적인 개념– GDI 함수의 parameter– 스크린 , 프린터 등을 표시– 구조체 : 객체 + 속성 + 모드
비트교육센터[100]
비트교육센터
Device Contexts
CDC– CPaintDC
painting 작업이 발생할 때BeginPaint() ~ EndPaint()
– CWindowDC전체 스크린을 표시 (client area+frame)GetWindowDC() ~ ReleaseDC()
– CClientDCClient area 를 표시GetClientDC() ~ ReleaseDC()
– CMetaFileDC메타파일에 대한 그리기 작업생성자 ~ Create() ~ DeleteMetaFile()
비트교육센터[101]
비트교육센터
Graphic ObjectsCGdiObject : Base class
– CPen– CBrush– CFont– CBitmap– CPalette– CRgn
Win32 API 의 함수들을 wrapping
비트교육센터[102]
비트교육센터
예제
CMyWnd::OnPaint() {CPaintDC paintDC(this);CPen* pOldPen;CPen bluePen(PS_SOLID, 25, RGB(0, 0, 255));
pOldPen = paintDC.SelectObject(&bluePen);paintDC.MoveTo(1, 1);paintDC.LineTo(100, 100);paintDC.SelectObject(pOldPen);
}
Chapter 03MFC 에서의 Message 처리
비트교육센터[104]
비트교육센터
ContentsIntroductionWindow messagesMessage mappingMFC 가 message map 을 이용하는 방법Message loop 의 hooking
비트교육센터[105]
비트교육센터
Introduction
Message handling– C/SDK
Switch/case 문을 통해 구현– MFC
Switch/case 문은 없다Callback function 은 어떻게 정의되는가
비트교육센터[106]
비트교육센터
Basic Components
MFC 의 message handling 구조– CCmdTarget class– Message maps
MFC message maps 에 대한 의문– 어떻게 switch/case 문을 대체하는가– 어떤 data structure 로 정의되는가– 어떻게 message map 이 작동하는가– 어떻게 message 가 연결되는가
비트교육센터[107]
비트교육센터
Window Messages3 개 부분으로 구성됨
– Unsigned integer실제 메시지를 나타냄
– WPARAMWord(32bits) 크기의 parameter메시지에 따른 특정 데이타
– LPARAM4byte parameter메시지에 따른 특정 데이타
비트교육센터[108]
비트교육센터
Window Messages (cont’d)
핸들링 해야 할 메시지의 분류– Windows message
WM_ 로 시작하는 메시지들 (WM_COMMAND 제외 )일반적으로 window, view 등에서 핸들링
– Control notificationWM_COMMAND 중 notify, WM_NOTIFYControl, 자식 window 가 부모 윈도우에게 전달하는 메시지들예 ) EN_CHANGED 를 포함한 WM_COMMAND 메시지
– Command message메뉴 , 툴바 , 엑셀레이터 등으로 인한 메시지
비트교육센터[109]
비트교육센터
Window Messages (cont’d)
핸들링 클래스– Windows message, control notification
CWnd 로부터 파생된 클래스들 : HWND 를 포함
– Command message다양한 종류 : CCmdTarget 로부터 파생된 클래스들예 ) open 명령 핸들링 : application
비트교육센터[110]
비트교육센터
UI Objects and Command IDs
비트교육센터[111]
비트교육센터
Message Handling in C/SDK
Windows program 의 정수
While (GetMessage(&msg, NULL, NULL, NULL)){
// Translates virtual key codesTranslateMessage(&msg);// Dispatches message to windowDispatchMessage(&msg);
}// Returns the value from PostQuitMessageReturn (msg.wParam);
비트교육센터[112]
비트교육센터
Message Handling in C/SDK (cont’d)WNDCLASS ws;…ws.lpfnWndProc = WndProc;…RegisterClass(ws);
LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{switch (message) {
case WM_CREATE:…break;
case WM_COMMAND:switch (wParam) {
case IDM_ABOUT:…
}}
비트교육센터[113]
비트교육센터
Message Handling in MFC
방법 1– Polymorphism : 가상 멤버 함수 이용– 심각한 메모리 낭비
방법 2– Message maps– MFC 의 특징
비트교육센터[114]
비트교육센터
Message Mapping Internals두 부분으로 구성
– CCmdTargetWindow message 나 command 를 받기 위해 반드시 상속받아야
하는 class– Message map
Window message 와 이를 처리하는 class member function 을 연관시켜주는 mechanism
비트교육센터[115]
비트교육센터
CCmdTarget Class
메시지의 처리– CCmdTarget 의 파생 클래스– 예
CWnd classCDocumentCWinApp
비트교육센터[116]
비트교육센터
Message MapData structures
– AFX_MSGMAP_ENTRY(AFXWIN.H)Message map table 의 한 element(entry)Message 에 대한 정보와 message handler 에 대한 정보를 저장
struct AFX_MSGMAP_ENTRY{
UINT nMessage; // windows messageUINT nCode; // control code or WM_NOTIFY codeUINT nID; // control ID (or 0 for windows messages)UINT nLastID; // used for entries specifying a range of control id'sUINT nSig; // signature type (action) or pointer to message #AFX_PMSG pfn; // routine to call (or special value)
};
비트교육센터[117]
비트교육센터
Message Map(contd.)
– AFX_MSGMAP(AFXWIN.H)실제 message map
struct AFX_MSGMAP{#ifdef _AFXDLL
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();#else
const AFX_MSGMAP* pBaseMap;#endif
const AFX_MSGMAP_ENTRY* lpEntries;};
비트교육센터[118]
비트교육센터
Message Map Macros
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 _messageEntries[]; \protected: \
static AFX_DATA const AFX_MSGMAP messageMap; \virtual const AFX_MSGMAP* GetMessageMap() const; \
비트교육센터[119]
비트교육센터
Message Map Macros (cont’d)
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \const AFX_MSGMAP* theClass::GetMessageMap() const \
{ return &theClass::messageMap; } \AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = \{ &baseClass::messageMap, &theClass::_messageEntries[0] }; \AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \{ \
#define END_MESSAGE_MAP() \{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
}; \
비트교육센터[120]
비트교육센터
Massage Map 예class CTestView : public Cview{protected:
//{{AFX_MSG(CTestView)afx_msg void OnLButtonDblClk(UINT nFlags, Cpoint point);//}}AFX_MSGDECLARE_MESSAGE_MAP()
};
class CTestView : public Cview{protected:
afx_msg void OnLButtonDblClk(UINT nFlags, Cpoint point);private:
static const AFX_MSGMAP_ENTRY _messageEntries[];protected:
static const AFX_MSGMAP messageMap;virtual const AFX_MSGMAP* GetMessageMap() const;
};
비트교육센터[121]
비트교육센터
Massage Map 예 (cont’d)BEGIN_MESSAGE_MAP(CTestVIew, Cview)
//{{AFX_MSG_MAP(CTestView)ON_COMMAND(ID_STRING_CENTER, OnStringCenter)ON_WM_LBUTTONDBLCLK()//}}AFX_MSG_MAP
END_MESSAGE_MAP()
const AFX_MSGMAP* CTestView::GetMessageMap() const{ return &CTestView::messageMap; }
AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CTestView::messageMap = { &CView::messageMap, &CTestView::_messageEntries[0] };
const AFX_MSGMAP_ENTRY CTestVIew::_messageEntries[] ={ (BEGIN_MESSAGE_MAP)
ON_COMMAND(ID_STRING_CENTER, OnStringCenter)ON_WM_LBUTTONDBLCLK(){0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } (END_MESSAGE_MAP)
};
비트교육센터[122]
비트교육센터
Message Map Entry Macro
#define ON_COMMAND(id, memberFxn) \{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, \AfxSig_vv, (AFX_PMSG)&memberFxn },
userdefine( 사용자가 지정한 이름 사용 )
#define ON_WM_LBUTTONDBLCLK() \{ WM_LBUTTONDBLCLK, 0, 0, 0, AfxSig_vwp, \
(AFX_PMSG)(AFX_PMSGW) \(void (AFX_MSG_CALL CWnd::*) \(UINT, CPoint))&OnLButtonDblClk },
만들어져 있는 이름을 사용
AFXMSG_.H
비트교육센터[123]
비트교육센터
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
Message Map Entry Macro (cont’d)Message Map Entry Macro (cont’d)
비트교육센터[124]
비트교육센터
User-define Message // inside the class declaration afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
For example: #define WM_MYMESSAGE (WM_USER + 100)
BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass) ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)END_MESSAGE_MAP()
CWnd* pWnd = ...;pWnd->SendMessage(WM_MYMESSAGE);
비트교육센터[125]
비트교육센터
Handlers for Message-Map Ranges
종류– ON_COMMAND_RANGE– ON_UPDATE_COMMAND– ON_CONTROL_RANGE
Message-Map Entry– ID 는 연속적이어야 한다 .
BEGIN_MESSAGE_MAP(CMyApp, CWinApp)ON_COMMAND_RANGE(ID_MYCMD_ONE, ID_MYCMD_TEN, On
DoSomething)ON_CONTROL_RANGE(BN_CLICKED, IDC_BUTTON1, IDC
_BUTTON10, OnButtonClicked)END_MESSAGE_MAP( )
비트교육센터[126]
비트교육센터
Handlers for Message-Map Ranges
Handlers
...void CMyDialog::OnButtonClicked( UINT nID ){ int nButton = nID - IDC_BUTTON1; ASSERT( nButton >= 0 && nButton < 10 ); // ...}
비트교육센터[127]
비트교육센터
MFC 의 Message Map 이용
MFC-based program– 두 종류의 메시지를 처리
regular window messages– WM_MOUSEMOVE, …
commands– WM_COMMAND
– Message-mapping architecture 의 이해두 종류 메시지를 각각 추적
비트교육센터[128]
비트교육센터
How to be wired16-bit version
– AfxWndProc()Message handling procedure 로 등록된 함수
32-bit version– DefWindowProc() 가 message handler 로 등록– Message hook 방법을 써서 결국에는 AfxWndProc() 가 message 를 처리하게 함– Hooking function
_AfxCbtFilterHook(), _AfxStandardSubclass()– 3D Control 을 지원하기 위함
비트교육센터[129]
비트교육센터
How to be wired (cont’d)
“WinCore.cpp”
BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister){
// mask off all classes that are already registeredAFX_MODULE_STATE* pModuleState = AfxGetModuleState();fToRegister &= ~pModuleState->m_fRegisteredClasses;if (fToRegister == 0) return TRUE;LONG fRegisteredClasses = 0;
// common initializationWNDCLASS wndcls;memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaultswndcls.lpfnWndProc = DefWindowProc;wndcls.hInstance = AfxGetInstanceHandle();wndcls.hCursor = afxData.hcurArrow;
비트교육센터[130]
비트교육센터
How to be wired (cont’d)BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,int x, int y, int nWidth, int nHeight,HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
{ … AfxHookWindowCreate(this);}void AFXAPI AfxHookWindowCreate(CWnd* pWnd){ if (pThreadState->m_hHookOldCbtFilter == NULL) {
pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
if (pThreadState->m_hHookOldCbtFilter == NULL)AfxThrowMemoryException();
} pThreadState->m_pWndInit = pWnd;}
비트교육센터[131]
비트교육센터
How to be wired (cont’d)LRESULT CALLBACK_AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam){…
// subclass the window if not already wired to AfxWndProcif (!bAfxWndProc){
// subclass the window with standard AfxWndProcoldWndProc = (WNDPROC)SetWindowLong(hWnd,
GWL_WNDPROC, (DWORD)afxWndProc);ASSERT(oldWndProc != NULL);*pOldWndProc = oldWndProc;
}…}
비트교육센터[132]
비트교육센터
Message HandlingAfxWndProc()(WINCORE.CPP)
– WM_QUERYAFXWNDPROCMFC’s message map 을 사용하는 MFC window 인지를 확인할
수 있는 message– 다른 message 에 대해서는 AfxCallWndProc() 함수를 호출
LRESULT CALLBACKAfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam){
if (nMsg == WM_QUERYAFXWNDPROC)return 1;
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
}
비트교육센터[133]
비트교육센터
Message Handling (cont’d)AfxCallWndProc()(WINCORE.CPP)
– Thread state 구조체에 message 의 정보를 저장– WM_INITDIALOG 처리
Auto-center dialog 위한 처리를 수행– Window object 의 window procedure 호출
CWnd::WindowProc()(WINCORE.CPP)내부적으로 OnWndMsg() 를 호출OnWndMsg() 가 처리하지 못하면 CWnd::DefWindowProc() 를 호출
비트교육센터[134]
비트교육센터
LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,WPARAM wParam = 0, LPARAM lParam = 0)
{_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();MSG oldState = pThreadState->m_lastSentMsg; // save for nestingpThreadState->m_lastSentMsg.hwnd = hWnd;pThreadState->m_lastSentMsg.message = nMsg;pThreadState->m_lastSentMsg.wParam = wParam;pThreadState->m_lastSentMsg.lParam = lParam;CRect rectOld;DWORD dwStyle = 0;if (nMsg == WM_INITDIALOG) _AfxPreInitDialog(pWnd, &rectOld, &dwStyle);// delegate to object's WindowProclResult = pWnd->WindowProc(nMsg, wParam, lParam);// more special case for WM_INITDIALOGif (nMsg == WM_INITDIALOG) _AfxPostInitDialog(pWnd, rectOld, dwStyle);pThreadState->m_lastSentMsg = oldState;return lResult;
}
Message Handling (cont’d)Message Handling (cont’d)
비트교육센터[135]
비트교육센터
“WinCore.Cpp”
LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam){
// OnWndMsg does most of the work, except for DefWindowProc callLRESULT lResult = 0;if (!OnWndMsg(message, wParam, lParam, &lResult))
lResult = DefWindowProc(message, wParam, lParam);return lResult;
}
Message Handling (cont’d)Message Handling (cont’d)
CWnd::WndowProc()(WINCORE.CPP)– virtual 이므로 override 가능– 성능 향상을 위해 message-mapping system 을 거치지 않고 처리해야 하는
메시지에 대한 핸들링 가능
비트교육센터[136]
비트교육센터
Message Handling (cont’d)CWnd::OnWndMsg()(WINCORE.CPP)
– 특별히 처리하는 messageWM_COMMAND, WM_NOTIFYWM_ACTIVATE, WM_SETCURSOR
– 기타 다른 message 들은 message map 을 이용하여 해당 message handler 를 호출
비트교육센터[137]
비트교육센터
Message Handling (cont’d)BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pRes
ult){
// special case for commandsif (message == WM_COMMAND) {
if (OnCommand(wParam, lParam)) {lResult = 1;goto LReturnTrue;
}return FALSE;
}// special case for notifiesif (message == WM_NOTIFY) { }// special case for activationif (message == WM_ACTIVATE) { }// special case for set cursor HTERRORif (message == WM_SETCURSOR ) { }
비트교육센터[138]
비트교육센터
Message Handling (cont’d)const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();UINT iHash; iHash = (LOWORD((DWORD)pMessageMap) ^ message) & (iHashMax-1);AfxLockGlobals(CRIT_WINMSGCACHE);AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];const AFX_MSGMAP_ENTRY* lpEntry;if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap){
…} else {
// not in cache, look for itpMsgCache->nMsg = message;pMsgCache->pMessageMap = pMessageMap;for (/* pMessageMap already init'ed */; pMessageMap != NULL;
pMessageMap = pMessageMap->pBaseMap) {AfxFindMessageEntry();
}
비트교육센터[139]
비트교육센터
Message Handling Trace두가지 종류의 message
– Regular window messageWM_MOUSEMOVE
– Command message메뉴나 control 이 보내는 messageWM_COMMAND
서로 다른 방식으로 처리– CWnd::OnWndMsg() 참고
비트교육센터[140]
비트교육센터
Handling WM_COMMAND가정
– Main frame 의 메뉴 명령 수행
CWnd::OnWndMsg() 함수에서– CWnd::OnCommand() 함수 호출
CWnd::OnCommand()– Virtual function(Framework 이 적절한 version 의 함수를 호출함 )– CFrameWnd::OnCommand()
On-line help 에 관한 것이면 해당 기능 수행아니면 CWnd::OnCommand() 함수 호출
비트교육센터[141]
비트교육센터
Handling WM_COMMAND (cont’d)“WinFrm.cpp”
BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam){
HWND hWndCtrl = (HWND)lParam;UINT nID = LOWORD(wParam);CFrameWnd* pFrameWnd = GetTopLevelFrame();ASSERT_VALID(pFrameWnd);if (pFrameWnd->m_bHelpMode&&hWndCtrl==NULL&&nID!=ID_HELP&&
nID!= ID_DEFAULT_HELP && nID != ID_CONTEXT_HELP) { // route as help if (!SendMessage(WM_COMMANDHELP, 0, HID_BASE_COMMAND+nID))
SendMessage(WM_COMMAND, ID_DEFAULT_HELP); return TRUE;}// route as normal commandreturn CWnd::OnCommand(wParam, lParam);
}
비트교육센터[142]
비트교육센터
Handling WM_COMMAND (cont’d)“WinCore.Cpp”BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam){
if (hWndCtrl == NULL)else {
if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)return TRUE; // locked out - ignore control notification
// reflect notification to child window controlif (ReflectLastMsg(hWndCtrl))
return TRUE; // eaten by child
// zero IDs for normal commands are not allowedif (nID == 0)
return FALSE;}return OnCmdMsg(nID, nCode, NULL, NULL);
}
비트교육센터[143]
비트교육센터
CWnd::OnCommand()(WINCORE.CPP)– LPARAM 을 조사– 만약 control 이 보낸 message 이면 control 에게 다시 message 를 reflect 한 후
return– 아니면 CWnd::OnCmdMsg()(virtual function) 함수 호출
Handling WM_COMMAND (cont’d)
비트교육센터[144]
비트교육센터
Handling WM_COMMAND (cont’d)“WinFrm.cpp”BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo){
CPushRoutingFrame push(this);// pump through current view FIRSTCView* pView = GetActiveView();if (pView != NULL && pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;// then pump through frameif (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;// last but not least, pump through appCWinApp* pApp = AfxGetApp();if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;return FALSE;
}
비트교육센터[145]
비트교육센터
Handling WM_COMMAND (cont’d)“ViewCore.cpp”BOOL CView::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo){
// first pump through paneif (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;// then pump through documentif (m_pDocument != NULL){
// special state for saving view before routing to documentCPushRoutingView push(this);return m_pDocument->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}return FALSE;
}
비트교육센터[146]
비트교육센터
Handling WM_COMMAND (cont’d)“DocCore.cpp”BOOL CDocument::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo){
if (CCmdTarget::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))return TRUE;
// otherwise check templateif (m_pDocTemplate != NULL && m_pDocTemplate->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
return FALSE;}
비트교육센터[147]
비트교육센터
CFrameWnd::OnCmdMsg()(WINFRM.CPP)
– 다음의 순서로 해당 OnCmdMsg() 함수를 호출Active viewActive view’s documentMain frame windowApplication
Handling WM_COMMAND (cont’d)
비트교육센터[148]
비트교육센터
만약 active view 에 해당 handler 가 있다면– CView::OnCmdMsg() 가 호출됨
CView::OnCmdMsg()(VIEWCORE.CPP)– View 에서 처리를 시도한 후 안되면 document 에서 처리를 시도– View 에서 처리 시도는 CWnd::OnCmdMsg() 함수의 호출로 이루어짐– 이 때 CWnd 는 OnCmdMsg 를 override 하지 않기 때문에 CCmdTarget::OnCmdM
sg 를 호출하는 결과가 됨
Handling WM_COMMAND (cont’d)
비트교육센터[149]
비트교육센터
Handling WM_COMMAND (cont’d)“CmdTarg.cpp”
BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo)
{for (pMessageMap = GetMessageMap(); pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMap) {
lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries, nMsg, nCode, nID);
if (lpEntry != NULL) {return _AfxDispatchCmdMsg(this, nID, nCode,
lpEntry->pfn, pExtra, lpEntry->nSig, pHandlerInfo);}
}return FALSE; // not handled
}
비트교육센터[150]
비트교육센터
CCmdTarget::OnCmdMsg()(CMDTARG.CPP)– Message map 을 보고 message handler 를 찾음– 찾게 되면 _AfxDispatchCmdMsg() 함수를 호출하여 해당 handler 를 실행시킴
_AfxDispatchCmdMsg()(CMDTARG.CPP)– Function signature 에 따라 다른 동작을 수행
Regular commandExtended commandVisual Basic control 등등
Handling WM_COMMAND (cont’d)
비트교육센터[151]
비트교육센터
Frame window 일 때의 처리과정 정리– 1. AfxWndProc()– 1.1 AfxCallWndProc()– 1.2CWnd::WindowProc()– 1.2. 1CWnd::OnWndMsg()– CFrameWnd::OnCommand()– CWnd::OnCommand()– CFrameWnd::OnCmdMsg()– CCmdTarget::OnCmdMsg()– _AfxDispatchCmdMsg()– CMainFram::On~()
Handling WM_COMMAND (cont’d)
비트교육센터[152]
비트교육센터
Document 일 때의 처리과정 정리– AfxWndProc()– AfxCallWndProc()– CWnd::WindowProc()– CWnd::OnWndMsg()– CFrameWnd::OnCommand()– CWnd::OnCommand()– CFrameWnd::OnCmdMsg()– CView::OnCmdMsg()– Cdocument::OnCmdMsg()– CCmdTarget::OnCmdMsg()– _AfxDispatchCmdMsg()– CMyDoc::On~()
Handling WM_COMMAND (cont’d)
비트교육센터[153]
비트교육센터
View 일 때의 처리과정 정리– AfxWndProc()– AfxCallWndProc()– CWnd::WindowProc()– CWnd::OnWndMsg()– CFrameWnd::OnCommand()– CWnd::OnCommand()– CFrameWnd::OnCmdMsg()– CView::OnCmdMsg()– CCmdTarget::OnCmdMsg()– _AfxDispatchCmdMsg()– CMyView::On~()
Handling WM_COMMAND (cont’d)
비트교육센터[154]
비트교육센터
App 일 때의 처리과정 정리– AfxWndProc()– AfxCallWndProc()– CWnd::WindowProc()– CWnd::OnWndMsg()– CFrameWnd::OnCommand()– CCmdTarget::OnCmdMsg()– _AfxDispatchCmdMsg()– CMyApp::On~()
Handling WM_COMMAND (cont’d)
비트교육센터[155]
비트교육센터
Dialog Box 일 때의 처리과정 정리– AfxWndProc()– AfxCallWndProc()– CWnd::WindowProc()– CWnd::OnWndMsg()– CDialog::OnCmdMsg()– CCmdTarget::OnCmdMsg()– _AfxDispatchCmdMsg()– CAboutDlg::On~()
Handling WM_COMMAND (cont’d)
비트교육센터[156]
비트교육센터
예 – Clear All
Handling 과정 (MDI application)– Main frame window 가 message 를 받는다– 현재 활성화된 MDI child window 가 처리 할 기회를 얻는다– Child window 가 먼저 view 에게 처리 기회를 준다 .– 실패하여 view 가 연결된 document 가 처리를 시도한다– Document 가 메시지 핸들러를 찾는 데 성공한다 .
비트교육센터[157]
비트교육센터
Handling Regular Window MessageCommand message 일 때와 처음의 과정은 비슷
– AfxWndProc()– AfxCallWndProc()– WindowProc()– OnWndMsg()
이 함수 안에서 message handler 를 찾기 위해 AfxFindMessageEntry()를
호출
비트교육센터[158]
비트교육센터
Handling Regular Window Message (cont’d)
AfxFindMessageEntry()– 두 버전이 있음 .
Assembly language : intel-based machineC language : otherwise
– Message map 에서 해당 핸들러가 있는지 검색– END_MESSAGE_MAP 에 의해 생성된 table 의 끝까지 검색
비트교육센터[159]
비트교육센터
Command message 와의 차이점– Command message 는 handler 를 찾기 위해서 여러 장소를 옮겨다님– Regular message 는 OnWndMsg() 에서 handler 를 찾으면 바로 해당 handler 를
호출하고 , 아니면 DefWindowProc() 를 이용
Handling Regular Window Message (cont’d)
비트교육센터[160]
비트교육센터
예 ) View 에서 WM_SIZE message 처리 과정– AfxWndProc()– AfxCallWndProc()– CWnd::WindowProc()– CWnd::OnWndMsg()– CSdiappView::OnSize()
Handling Regular Window Message (cont’d)
비트교육센터[161]
비트교육센터
Other Kinds of Messages
지금까지 살펴 본 메시지 종류– WM_COMMAND– Window messages(WM_SIZE, WM_MOVE, …)
그 이외의 메시지 종류– WM_NOTIFY– WM_ACTIVATE– WM_SETCURSOR
비트교육센터[162]
비트교육센터
Other Kinds of Messages (cont’d)
WM_NOTIFY– Control 이 보내는 message– 항상 notify message– 반면 , WM_COMMAND
command 이거나 notify message
비트교육센터[163]
비트교육센터
Other Kinds of Messages (cont’d)
struct NMHDR {HWND hwndFrom; // control that sent notificationUINT idFrom; // ID of controlUINT code; // notification code
CWnd::OnWndMsg() 에서
// special case for notifies if (message == WM_NOTIFY) { NMHDR* pNMHDR = (NMHDR*)lParam;
if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))goto LReturnTrue;
return FALSE; …}
비트교육센터[164]
비트교육센터
Other Kinds of Messages (cont’d)“Wincore.cpp”BOOL CWnd::OnNotify(WPARAM, LPARAM lParam, LRESULT* pResult){
NMHDR* pNMHDR = (NMHDR*)lParam;HWND hWndCtrl = pNMHDR->hwndFrom;// get the child ID from the window itselfUINT nID = _AfxGetDlgCtrlID(hWndCtrl);int nCode = pNMHDR->code;if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
return TRUE; // locked out - ignore control notification// reflect notification to child window controlif (ReflectLastMsg(hWndCtrl, pResult)) return TRUE; // eaten by childAFX_NOTIFY notify;notify.pResult = pResult;notify.pNMHDR = pNMHDR;return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY), ¬ify, NULL);
}
비트교육센터[165]
비트교육센터
Other Kinds of Messages (cont’d)BOOL PASCAL CWnd::ReflectLastMsg(HWND hWndChild, LRESULT* pResult){
CHandleMap* pMap = afxMapHWND();CWnd* pWnd = (CWnd*)pMap->LookupPermanent(hWndChild);if (pWnd == NULL) {
// check if the window is an OLE control…return FALSE;
}
return pWnd->SendChildNotifyLastMsg(pResult);}
비트교육센터[166]
비트교육센터
Other Kinds of Messages (cont’d)BOOL CWnd::SendChildNotifyLastMsg(LRESULT* pResult){
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();return OnChildNotify(pThreadState->m_lastSentMsg.message,
pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam, pResult);
}
비트교육센터[167]
비트교육센터
Other Kinds of Messages (cont’d)
Message reflection– OnWndMsg() 에서 OnNotify() 를 호출– OnNofity() 는 다시 OnChildNotify() 를 호출하여 control 로 message 를 다시 보냄– 결국에는 control 이 parent 에 의존하지 않고 자신의 일을 처리하게 함
비트교육센터[168]
비트교육센터
Other Kinds of Messages (cont’d)
– WM_ACTIVATEOnWndMsg() 함수에서 _AfxHandleActivate() 를 호출
– WM_SETCURSOROnWndMsg() 함수에서 _AfxHandleSetCursor() 함수 호출
비트교육센터[169]
비트교육센터
Speed Message-map Matching
방법– 최근에 처리 된 메시지를 캐쉬에 저장– 같은 메시지를 다시 처리할 가능성이 높음
장점– Unhandled message 빠르고 효과적으로 처리
비트교육센터[170]
비트교육센터
Message Loop HookingMessage loop hooking
– Message 가 해당 handler 에 의해 처리되기 전에 어떠한 작업을 하고 싶을때
– PreTranslateMessage()
CWinApp::PreTranslateMessage()– CWinApp::Run() 함수는 message 가 message pump 에 의해 처리되기
전에 위 함수를 호출
– TRUE 를 return 하면 message pump 는 해당 message 에 관해서는 처리를 하지 않음
CWnd::PreTranslateMessage()
비트교육센터[171]
비트교육센터
Message Loop Hooking (cont’d)
“THRDCORE.cpp”int CWinThread::Run(){
// for tracking the idle time stateBOOL bIdle = TRUE;LONG lIdleCount = 0;// acquire and dispatch messages until a WM_QUIT message is received.for (;;){
// phase1: check to see if we can do idle workwhile (bIdle &&!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)){
// call OnIdle while in bIdle stateif (!OnIdle(lIdleCount++))
bIdle = FALSE; // assume "no idle" state}
비트교육센터[172]
비트교육센터
Message Loop Hooking (cont’d)
// phase2: pump messages while availabledo {
// pump message, but quit on WM_QUITif (!PumpMessage())
return ExitInstance();
// reset "no idle" state after pumping "normal" messageif (IsIdleMessage(&m_msgCur)){
bIdle = TRUE;lIdleCount = 0;
}
} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));}ASSERT(FALSE); // not reachable
}
비트교육센터[173]
비트교육센터
Message Loop Hooking (cont’d)
BOOL CWinThread::PumpMessage(){
ASSERT_VALID(this);
if (!::GetMessage(&m_msgCur, NULL, NULL, NULL)){}
// process this messageif (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur)){
::TranslateMessage(&m_msgCur);::DispatchMessage(&m_msgCur);
}return TRUE;
}
비트교육센터[174]
비트교육센터
Message Loop Hooking (cont’d)
BOOL CWinThread::PreTranslateMessage(MSG* pMsg){
// if this is a thread-message, short-circuit this functionif (pMsg->hwnd == NULL && DispatchThreadMessageEx(pMsg))
return TRUE;// walk from target to main windowCWnd* pMainWnd = AfxGetMainWnd();if (CWnd::WalkPreTranslateTree(pMainWnd->GetSafeHwnd(), pMsg))
return TRUE;// in case of modeless dialogs, last chance route through main// window's accelerator tableif (pMainWnd != NULL) {
CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd); if (pWnd->GetTopLevelParent() != pMainWnd)
return pMainWnd->PreTranslateMessage(pMsg);}return FALSE; // no special processing
}
비트교육센터[175]
비트교육센터
Message Loop Hooking (cont’d)
“WinCore.Cpp”BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg){
// walk from the target window up to the hWndStop window checking// if any window wants to translate this message
for (HWND hWnd=pMsg->hwnd; hWnd != NULL;hWnd=::GetParent(hWnd)){CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);if (pWnd != NULL) {
// target window is a C++ windowif (pWnd->PreTranslateMessage(pMsg))
return TRUE; }// got to hWndStop window without interestif (hWnd == hWndStop)
break;}return FALSE; // no special processing
}