使用MFC向导,生成一个对话框的应用程序。通过调试、设置断点的方式解析MFC程序。下面只是给出主要的源代码以及它们所在文件的名字。
1/**//*
2 Noun Explain:
3 1、CRT: C run-time
4 you can refer to C运行库到底是什么东西?它和操作系统有没有关系?
5 http://tech.cixiong.com/t/200406/17/0229562.html
6*/
7//在此之前调用了__DllMainCRTStartup, VC\crt\src\crtdll.c 464, 还有一个重要的crtlib.c文件
8//you can refer to MFC技术内幕系列http://www.mx68.com/WebDeveloper/2006-03-10/WebDeveloper_26756.shtml
9/**//*
10 seq1 VC\crt\src\crtexe.c , main function
11*/
12/**//***
13*mainCRTStartup(void)
14*wmainCRTStartup(void)
15*WinMainCRTStartup(void)
16*wWinMainCRTStartup(void)
17*
18*Purpose:
19* These routines do the C runtime initialization, call the appropriate
20* user entry function, and handle termination cleanup. For a managed
21* app, they then return the exit code back to the calling routine, which
22* is the managed startup code. For an unmanaged app, they call exit and
23* never return.
24*
25* Function: User entry called:
26* mainCRTStartup main
27* wmainCRTStartup wmain
28* WinMainCRTStartup WinMain
29* wWinMainCRTStartup wWinMain
30*
31*Entry:
32*
33*Exit:
34* Managed app: return value from main() et al, or the exception code if
35* execution was terminated by the __except guarding the call
36* to main().
37* Unmanaged app: never return.
38*
39*******************************************************************************/
40int WinMainCRTStartup(void)
41{
42 return __tmainCRTStartup();
43}
44
45/**//*
46 seq2
47*/
48int __tmainCRTStartup(void)
49{
50 STARTUPINFO StartupInfo;
51 /**//*
52 The API GetStartupInfo function retrieves the contents of the STARTUPINFO structure that was specified
53 when the calling process was created.
54
55 The STARTUPINFO structure is used with the CreateProcess, CreateProcessAsUser, and
56 CreateProcessWithLogonW functions to specify the window station, desktop, standard handles, and
57 appearance of the main window for the new process.
58
59 Before run GetStartupInfo(), it must call CreateProcess. but i don't know how make break point
60 and in witch file make break point.
61 在这之前应该调用了CreateProcess函数,因为运行GetStartupInfo之后,StartupInfo结构被填充了:包括进程的路径、
62 名称……
63 */
64 GetStartupInfo( &StartupInfo );
65
66 /**//*
67 * do C++ constructors (initializers) specific to this EXE
68 */
69 if (__native_startup_state == __initializing)
70 {
71 /**//*
72 * pointers to initialization sections
73 extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a[];
74 extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[]; // C initializers
75 extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[];
76 extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[]; // C++ initializers
77 extern _CRTALLOC(".CRT$XPA") _PVFV __xp_a[];
78 extern _CRTALLOC(".CRT$XPZ") _PVFV __xp_z[]; // C pre-terminators
79 extern _CRTALLOC(".CRT$XTA") _PVFV __xt_a[];
80 extern _CRTALLOC(".CRT$XTZ") _PVFV __xt_z[]; // C terminators
81 */
82 _initterm( __xc_a, __xc_z );//please see seq3
83 }
84 /**//*
85 * Skip past program name (first token in command line).
86 * Check for and handle quoted program name.
87 */
88 #ifdef WPRFLAG
89 /**//* OS may not support "W" flavors */
90 if (_wcmdln == NULL)
91 return 255;
92 lpszCommandLine = (wchar_t *)_wcmdln;
93 #else /* WPRFLAG */
94 //can get the application's complete name:
95 //lpszCommandLine 0x00020724 ""e:\……\debug\CapturePacket.exe
96 //_acmdln's definition is in C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\crtlib.c, it is initialized
97 //by _acmdln = (char *)GetCommandLineA() in function __CRTDLL_INIT Line317
98 //GetCommandLineA在winbase.h、Kernel32.lib中定义的SDKapi
99 lpszCommandLine = (unsigned char *)_acmdln;
100 #endif /* WPRFLAG */
101
102 mainret = WinMain(
103 (HINSTANCE)&__ImageBase,
104 NULL,
105 lpszCommandLine,
106 StartupInfo.dwFlags & STARTF_USESHOWWINDOW
107 ? StartupInfo.wShowWindow
108 : SW_SHOWDEFAULT
109 );//see seq4
110}
111
112/**//*
113 seq3
114 VC\crt\src\crt0dat.c , main function
115 you can refer to 静态对象、全局对象与程序的运行机制 http://dev.csdn.net/Develop/article/28/61880.shtm
116
117 在函数指针表中不断循环找到所有函数的入口(内存地址)(在WinMainCRTStartup启动函数之前就把所有的函数入口
118 地址保存了?这项工作是在创建Process的时候做的?)
119*/
120/**//***
121* static void _initterm(_PVFV * pfbegin, _PVFV * pfend) - call entries in
122* function pointer table
123*
124*Purpose:
125* Walk a table of function pointers, calling each entry, as follows:
126*
127* 1. walk from beginning to end, pfunctbl is assumed to point
128* to the beginning of the table, which is currently a null entry,
129* as is the end entry.
130* 2. skip NULL entries
131* 3. stop walking when the end of the table is encountered
132*
133*Entry:
134* _PVFV *pfbegin - pointer to the beginning of the table (first
135* valid entry).
136* _PVFV *pfend - pointer to the end of the table (after last
137* valid entry).
138*
139*Exit:
140* No return value
141*
142*Notes:
143* This routine must be exported in the CRT DLL model so that the client
144* EXE and client DLL(s) can call it to initialize their C++ constructors.
145*
146*Exceptions:
147* If either pfbegin or pfend is NULL, or invalid, all bets are off!
148*
149*******************************************************************************/
150
151void __cdecl _initterm (_PVFV * pfbegin, _PVFV * pfend)
152{
153 /**//*
154 在此设置断点,可以看到pfbegin、pfend的类型为void(void)**(空函数指针的指针?0x0041d000-0x0041d41c),循环指向函数入口地址。
155 Call Stack中可以看到msvcr80d.dll(和kernel32.dll)
156 */
157 /**//*
158 * walk the table of function pointers from the bottom up, until
159 * the end is encountered. Do not skip the first entry. The initial
160 * value of pfbegin points to the first valid entry. Do not try to
161 * execute what pfend points to. Only entries before pfend are valid.
162 */
163 while ( pfbegin < pfend )
164 {
165 /**//*
166 * if current table entry is non-NULL, call thru it.
167 */
168 if ( *pfbegin != NULL )
169 /**//*
170 第1次、在0x0041d104 pcppinit
171 0x00414340 pre_cpp_init(void)进入
172 第2次、在0x0041d208 _afxInitAppState$initializer$
173 0x00419fe0 'dynamic initializer for '_afxInitAppState"(void)进入
174 第3次、在0x0041d30c theApp$initializer$ 对象的定义(构造函数)
175 0x00419fe0 'dynamic initializer for 'theApp"(void)进入
176 第4次、在0x0041d310 clash$initializer$
177 0x00419f20 Inconsistent_definition_of_symbol__ATL_MIXED::`dynamic initializer for 'clash''(void)进入
178 第5次、在0x0041d314 clash$initializer$
179 0x00419f60 Define_the_symbol__ATL_MIXED::`dynamic initializer for 'clash''(void)进入
180 */
181 (**pfbegin)();//指针的指针
182 ++pfbegin;
183 }
184}
185
186/**//***
187 seq3.1
188*pre_cpp_init(void) crtexe.c Line295
189*
190*Purpose:
191* The code in mainCRTStartup that was executed after C initializers and
192* before C++ initializers is shifted in this function. Also this funciton
193* is the first thing that is executed in C++ init section.
194*
195*Entry:
196*
197*Exit:
198*
199*******************************************************************************/
200
201static void __cdecl pre_cpp_init(void)
202{
203#ifdef _RTC
204 atexit(_RTC_Terminate);
205#endif /* _RTC */
206
207 /**//*
208 * Get the arguments for the call to main. Note this must be
209 * done explicitly, rather than as part of the dll's
210 * initialization, to implement optional expansion of wild
211 * card chars in filename args
212 */
213
214 startinfo.newmode = _newmode;
215
216
217#ifdef WPRFLAG
218 argret = __wgetmainargs(&argc, &argv, &envp,
219 _dowildcard, &startinfo);
220#else /* WPRFLAG */
221 argret = __getmainargs(&argc, &argv, &envp,
222 _dowildcard, &startinfo);
223#endif /* WPRFLAG */
224
225#ifndef _SYSCRT
226 if (argret < 0)
227 _amsg_exit(_RT_SPACEARG);
228#endif /* _SYSCRT */
229}
230/**//*
231 seq3.2
232 \Microsoft Visual Studio 8\VC\atlmfc\src\mfc\appmodul.cpp Line70
233*/
234char _afxInitAppState = (char)(AfxInitialize(FALSE, _MFC_VER));
235
236/**//////////////////////////////////////////////////////////////////////////////237//seq3.2.1
238// initialize app state such that it points to this module's core state
239//\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\appmodul.cpp Line31
240
241BOOL AFXAPI AfxInitialize(BOOL bDLL, DWORD dwVersion)
242{
243 //AfxGetModuleState:c:\program files\microsoft visual studio 8\vc\atlmfc\include\afxstat_.h Line206
244 /**//*
245 CWinApp* m_pCurrentWinApp; //0x00000000
246 HINSTANCE m_hCurrentInstanceHandle; //0x00000000
247 HINSTANCE m_hCurrentResourceHandle; //0x00000000
248 LPCTSTR m_lpszCurrentAppName; //0x00000000
249 BYTE m_bDLL; // TRUE if module is a DLL, FALSE if it is an EXE //1
250 BYTE m_bSystem; // TRUE if module is a "system" module, FALSE if not //0
251 BYTE m_bReserved[2]; // padding
252
253 DWORD m_fRegisteredClasses; // flags for registered window classes
254 ……
255 */
256 AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
257 pModuleState->m_bDLL = (BYTE)bDLL;
258 ASSERT(dwVersion <= _MFC_VER);
259 UNUSED(dwVersion); // not used in release build
260#ifdef _AFXDLL
261 pModuleState->m_dwVersion = dwVersion;
262#endif
263#ifdef _MBCS
264 // set correct multi-byte code-page for Win32 apps
265 if (!bDLL)
266 _setmbcp(_MB_CP_ANSI);
267#endif //_MBCS
268 return TRUE;
269}
270
271/**//*
272 seq3.3.1
273 My dialog class:CCapturePacketApp
274*/
275CCapturePacketApp theApp;
276/**//*
277 seq3.3.1.5
278 先调用父类CWinApp的constructor
279*/
280CCapturePacketApp::CCapturePacketApp()
281{
282}
283/**//*
284 seq3.3.1.4
285 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\appcore.cpp Line401
286 先调用父类CWinThread的constructor
287 函数中的变量如m_pszAppName、m_hThread、m_nThreadID、m_hInstance……都在
288 c:\program files\microsoft visual studio 8\vc\atlmfc\include\afxwin.h中定义
289*/
290CWinApp::CWinApp(LPCTSTR lpszAppName)
291{
292 if (lpszAppName != NULL)
293 m_pszAppName = _tcsdup(lpszAppName);
294 else
295 m_pszAppName = NULL;
296
297 // initialize CWinThread state
298 AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
299 ENSURE(pModuleState);
300 AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
301 ENSURE(pThreadState);
302 ASSERT(AfxGetThread() == NULL);
303 pThreadState->m_pCurrentWinThread = this;
304 ASSERT(AfxGetThread() == this);
305 //Platform SDK Kernel32.dll
306 //The GetCurrentThread function retrieves a pseudo handle for the current thread.
307 m_hThread = ::GetCurrentThread();
308 m_nThreadID = ::GetCurrentThreadId();
309
310 // initialize CWinApp state
311 ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please
312 //its value:0x00421340 class CCapturePacketApp theApp {CWinApp <Bad Ptr>}
313 pModuleState->m_pCurrentWinApp = this;
314 ASSERT(AfxGetApp() == this);
315
316 // in non-running state until WinMain
317 m_hInstance = NULL;
318 m_hLangResourceDLL = NULL;
319 m_pszHelpFilePath = NULL;
320 m_pszProfileName = NULL;
321 m_pszRegistryKey = NULL;
322 m_pszExeName = NULL;
323 m_pRecentFileList = NULL;
324 m_pDocManager = NULL;
325 m_atomApp = m_atomSystemTopic = NULL;
326 m_lpCmdLine = NULL;
327 m_pCmdInfo = NULL;
328
329 // initialize wait cursor state
330 m_nWaitCursorCount = 0;
331 m_hcurWaitCursorRestore = NULL;
332
333 // initialize current printer state
334 m_hDevMode = NULL;
335 m_hDevNames = NULL;
336 m_nNumPreviewPages = 0; // not specified (defaults to 1)
337
338 // initialize DAO state
339 m_lpfnDaoTerm = NULL; // will be set if AfxDaoInit called
340
341 // other initialization
342 m_bHelpMode = FALSE;
343 m_eHelpType = afxWinHelp;
344 m_nSafetyPoolSize = 512; // default size
345}
346/**//*
347 seq3.3.1.3
348 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\thrdcore.cpp Line474
349 先调用父类CCmdTarget的constructor
350*/
351CWinThread::CWinThread()
352{
353 m_pThreadParams = NULL;
354 m_pfnThreadProc = NULL;
355
356 CommonConstruct();
357}
358
359/**//*
360 seq3.3.1..2
361 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\cmdtarg.cpp Line21
362 先调用父类CObject的constructor
363 函数中的变量如m_pModuleState、m_dwRef等都在c:\program files\microsoft visual studio 8\vc\atlmfc\include\afxwin.h
364 中定义
365*/
366CCmdTarget::CCmdTarget()
367{
368 // capture module state where object was constructed
369 /**//*
370 value:0x001544a0
371 CWinApp* m_pCurrentWinApp; //0x00000000
372 HINSTANCE m_hCurrentInstanceHandle; //0x00000000
373 HINSTANCE m_hCurrentResourceHandle; //0x00000000
374 LPCTSTR m_lpszCurrentAppName; //0x00000000
375 BYTE m_bDLL; // TRUE if module is a DLL, FALSE if it is an EXE //0
376 BYTE m_bSystem; // TRUE if module is a "system" module, FALSE if not //0
377 BYTE m_bReserved[2]; // padding
378
379 DWORD m_fRegisteredClasses; // flags for registered window classes //0
380 ……
381 */
382 m_pModuleState = AfxGetModuleState();
383 ASSERT(m_pModuleState != NULL);
384
385 // initialize state
386#ifndef _AFX_NO_OLE_SUPPORT
387 m_dwRef = 1;
388 m_pOuterUnknown = NULL;
389 m_xInnerUnknown = 0;
390 m_xDispatch.m_vtbl = 0;
391 m_bResultExpected = TRUE;
392 m_xConnPtContainer.m_vtbl = 0;
393#endif
394}
395/**//*
396 seq3.3.1..1
397 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afx.inl Line91
398*/
399_AFX_INLINE CObject::CObject()
400{
401}
402
403/**//*
404 seq3.3.1.6
405 C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\atonexit.c Line123
406*/
407int __cdecl atexit (
408 _PVFV func
409 )
410{
411 return (_onexit((_onexit_t)func) == NULL) ? -1 : 0;
412}
413
414/**//*
415 seq3.4
416 c:\program files\microsoft visual studio 8\vc\atlmfc\include\atldef.h Line55
417*/
418__declspec(selectany) _Please_define_it_the_same_throughout_your_project clash = _Please_define_it_the_same_throughout_your_project ();
419
420/**//*
421 seq3.5
422 c:\program files\microsoft visual studio 8\vc\atlmfc\include\atldef.h Line71
423*/
424__declspec(selectany) Thank_you clash = Thank_you();
425
426/**//*
427 seq4
428 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\appmodul.cpp Line23
429*/
430extern "C" int WINAPI
431_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
432 __in LPTSTR lpCmdLine, int nCmdShow)
433{
434 // call shared/exported WinMain
435 return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
436}
437
438/**//*
439 seq4.1
440 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\winmain.cpp Line19
441*/
442int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
443 __in LPTSTR lpCmdLine, int nCmdShow)
444{
445 int nReturnCode = -1;
446 //C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\thrdcore.cpp Line134
447 /**//*
448 CWinThread* AFXAPI AfxGetThread()
449 {
450 // check for current thread in module thread state
451 AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
452 CWinThread* pThread = pState->m_pCurrentWinThread;
453 return pThread;
454 }
455 */
456 //#define afxCurrentWinApp AfxGetModuleState()->m_pCurrentWinApp:
457 CWinThread* pThread = AfxGetThread();
458 CWinApp* pApp = AfxGetApp();
459
460 // AFX internal initialization
461 //see seq4.1.1
462 if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow));
463
464 // App global initializations (rare)
465 //see seq4.1.2
466 if (pApp != NULL && !pApp->InitApplication());
467
468 // Perform specific initializations
469 //see seq4.1.3
470 if (!pThread->InitInstance())
471 {
472 if (pThread->m_pMainWnd != NULL)
473 {
474 TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
475 pThread->m_pMainWnd->DestroyWindow();
476 }
477 nReturnCode = pThread->ExitInstance();
478 goto InitFailure;
479 }
480 nReturnCode = pThread->Run();
481
482InitFailure:
483#ifdef _DEBUG
484 // Check for missing AfxLockTempMap calls
485 if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
486 {
487 TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n",
488 AfxGetModuleThreadState()->m_nTempMapLock);
489 }
490 AfxLockTempMaps();
491 AfxUnlockTempMaps(-1);
492#endif
493
494 AfxWinTerm();
495 return nReturnCode;
496}
497
498/**//*
499 seq4.1.1
500 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\appinit.cpp Line19
501*/
502BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,
503 __in LPTSTR lpCmdLine, int nCmdShow)
504{
505 ASSERT(hPrevInstance == NULL);
506
507
508 // handle critical errors and avoid Windows message boxes
509 SetErrorMode(SetErrorMode(0) |
510 SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
511
512 // set resource handles
513 AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
514 pModuleState->m_hCurrentInstanceHandle = hInstance;
515 pModuleState->m_hCurrentResourceHandle = hInstance;
516 pModuleState->CreateActivationContext();
517
518 // fill in the initial state for the application
519 CWinApp* pApp = AfxGetApp();
520 if (pApp != NULL)
521 {
522 // Windows specific initialization (not done if no CWinApp)
523 pApp->m_hInstance = hInstance;
524 hPrevInstance; // Obsolete.
525 pApp->m_lpCmdLine = lpCmdLine;
526 pApp->m_nCmdShow = nCmdShow;
527 pApp->SetCurrentHandles();
528 }
529
530 // initialize thread specific data (for main thread)
531 if (!afxContextIsDLL)
532 AfxInitThread();
533
534 // Initialize CWnd::m_pfnNotifyWinEvent
535 HMODULE hModule = ::GetModuleHandle(_T("user32.dll"));
536 if (hModule != NULL)
537 {
538 CWnd::m_pfnNotifyWinEvent = (CWnd::PFNNOTIFYWINEVENT)::GetProcAddress(hModule, "NotifyWinEvent");
539 }
540
541 return TRUE;
542}
543/**//*
544 seq4.1.2
545 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\appcore.cpp Line563
546*/
547BOOL CWinApp::InitApplication()
548{
549 if (CDocManager::pStaticDocManager != NULL)
550 {
551 if (m_pDocManager == NULL)
552 m_pDocManager = CDocManager::pStaticDocManager;
553 CDocManager::pStaticDocManager = NULL;
554 }
555
556 if (m_pDocManager != NULL)
557 m_pDocManager->AddDocTemplate(NULL);
558 else
559 CDocManager::bStaticInit = FALSE;
560
561 LoadSysPolicies();
562
563 return TRUE;
564}
565/**//*
566 seq4.1.2.1
567 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\appcore.cpp Line460
568*/
569// This function is not exception safe - will leak a registry key if exceptions are thrown from some places
570// To reduce risk of leaks, I've declared the whole function throw(). This despite the fact that its callers have
571// no dependency on non-throwing.
572BOOL CWinApp::_LoadSysPolicies() throw()
573{
574}
575
576/**//*
577 seq4.1.3
578 ……\CapturePacket.cpp
579*/
580BOOL CCapturePacketApp::InitInstance()
581{
582 // InitCommonControlsEx() is required on Windows XP if an application
583 // manifest specifies use of ComCtl32.dll version 6 or later to enable
584 // visual styles. Otherwise, any window creation will fail.
585 INITCOMMONCONTROLSEX InitCtrls;
586 InitCtrls.dwSize = sizeof(InitCtrls);
587 // Set this to include all the common control classes you want to use
588 // in your application.
589 InitCtrls.dwICC = ICC_WIN95_CLASSES;
590 InitCommonControlsEx(&InitCtrls);
591
592 CWinApp::InitInstance();
593
594 AfxEnableControlContainer();
595
596 // Standard initialization
597 // If you are not using these features and wish to reduce the size
598 // of your final executable, you should remove from the following
599 // the specific initialization routines you do not need
600 // Change the registry key under which our settings are stored
601 // TODO: You should modify this string to be something appropriate
602 // such as the name of your company or organization
603 SetRegistryKey(_T("Local AppWizard-Generated Applications"));
604
605 CCapturePacketDlg dlg;
606 m_pMainWnd = &dlg;
607 //message loop here:
608 /**//*
609 !!see seq4.1.3.1
610 */
611 INT_PTR nResponse = dlg.DoModal();
612 if (nResponse == IDOK)
613 {
614 // TODO: Place code here to handle when the dialog is
615 // dismissed with OK
616 }
617 else if (nResponse == IDCANCEL)
618 {
619 // TODO: Place code here to handle when the dialog is
620 // dismissed with Cancel
621 }
622
623 // Since the dialog has been closed, return FALSE so that we exit the
624 // application, rather than start the application's message pump.
625
626
627 return FALSE;
628}
629
630/**//*
631 seq4.1.3.1
632 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\dlgcore.cpp Line483
633*/
634INT_PTR CDialog::DoModal()
635{
636 //……
637 //see seq4.1.3.1.1
638 VERIFY(RunModalLoop(dwFlags) == m_nModalResult);
639 //……
640}
641/**//*
642 seq4.1.3.1.1
643 C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc\wincore.cpp Line4270
644*/
645int CWnd::RunModalLoop(DWORD dwFlags)
646{
647 //……
648 for (;;)
649 {
650 //……
651 // phase1: check to see if we can do idle work
652 while (bIdle &&
653 !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
654 {
655 //……
656 }
657 // phase2: pump messages while available
658 do
659 {
660 //……
661 if (!ContinueModal())
662 goto ExitModal;
663 }while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
664 }
665 ExitModal:
666 m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
667 return m_nModalResult;
668}