MFC源码剖析之——MFC来龙去脉以传统的C/SDK撰写Windows程序,最大的好处是可以清楚看见整个程序的来龙去脉和消息动向,然而这些重要的动线在MFC应用程序中却隐晦不明,因为它们被ApplicationFramework包起来了。这一章主要目的除了解释MFC应用程序的长像,也要从MFC源代码中检验出一个Windows程序原本该有的程序进入点(WinMain)、视窗类别注册(RegisterClass)、窗口产生(CreateWindow)、消息循环(MessageLoop)、窗口函数(WindowProcedure)等等动作,抽丝剥茧彻底了解一个MFC程序的诞生与结束,以及生命过程。先来看个一般的C/SDKWindows程序:////////////////////////////////////////////////////////////////Generic.cpp一般的windows程序流程演示#includeLRESULTCALLBACKMyWinProc(HWND,UINT,WPARAM,LPARAM);//○6intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnShowCmd){WNDCLASSwc;wc.cbClsExtra=0;wc.cbWndExtra=0;wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);wc.hCursor=LoadCursor(NULL,IDC_ARROW);wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);wc.hInstance=hInstance;wc.lpfnWndProc=MyWinProc;wc.lpszClassName="generic";wc.lpszMenuName=NULL;wc.style=CS_VREDRAW|CS_HREDRAW;//窗口的样式RegisterClass(&wc);//注册窗口类○1HWNDhWnd;hWnd=CreateWindow("generic","Title",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);//产生窗口○2ShowWindow(hWnd,SW_NORMAL);//显示窗口○3UpdateWindow(hWnd);//更新窗口○4MSGmsg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}//消息循环○5return0;}LRESULTCALLBACKMyWinProc(HWNDhwnd,//窗口句柄UINTuMSG,//消息标志符WPARAMwParam,//消息的第一个参数LPARAMlParam//消息的第二个参数){switch(uMSG){caseWM_LBUTTONDOWN://鼠标左键点击MessageBox(hwnd,"点击","HelloWorld",MB_OK);break;caseWM_CLOSE://窗口被关闭消息if(IDYES==MessageBox(hwnd,"是否真的要关闭窗口?","提示",MB_YESNO)){DestroyWindow(hwnd);}break;caseWM_PAINT://窗口被绘制时消息HDChDc;PAINTSTRUCTps;hDc=BeginPaint(hwnd,&ps);TextOut(hDc,0,10,"第一行字符",10);EndPaint(hwnd,&ps);break;caseWM_DESTROY://窗口被销毁是消息PostQuitMessage(0);//有了这个才可以使while(GetMessage(&MSG,,,))为假break;default://处理我不感兴趣的消息returnDefWindowProc(hwnd,uMSG,wParam,lParam);}return0;}从上述的原码中可以看出windows程序设计有个基本的脉络:RegisterClass(WNDCLASS*)→CreateWindow→ShowWindow→UpdateWindow→MessageLoop→Windowprocedure。但我们从MFC中看不出有这么一个流程,甚至是看不到程序的入口functionnamedWinMain。即便是基于MFC的应用程序,建立窗口类也是会遵循如下的过程:设计窗口类->注册窗口类->生成窗口->显示窗口->更新窗口->消息循环->消息路由到窗口过程函数处理。下面就剖析一下在MFC中是如何完成上述过程的。(1)每个应用程序都有且仅有一个应用类的全局变量theApp,全局变量先于WinMain函数进行处理。(2)WinMain函数体在APPMODUL.CPP文件中,定义如下:extern"C"intWINAPI_tWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPTSTRlpCmdLine,intnCmdShow){//callshared/exportedWinMainreturnAfxWinMain(hInstance,hPrevInstance,lpCmdLine,nCmdShow);}其中#define_tWinMainWinMain(3)AfxWinMain函数体在WINMAIN.CPP文件中,里面有如下两句话:CWinThread*pThread=AfxGetThread();CWinApp*pApp=AfxGetApp();其实这里得到的这两个指针都是指向全局的对象theApp的;接下来有函数调用pThread->InitInstance(),根据多态性,会调用CXXXApp类中的InitInstance()函数。该函数很重要,在对该函数的调用中就会完成:设计窗口类->注册窗口类->生成窗口->显示窗口->更新窗口。接下来,该函数中会继续调用pThread->Run(),这就完成了:消息循环-...