一、Win32Application Architecture
 
一个Win32 Application Architecture的代码结构如下:
 
| |  LRESULT CALLBACK WinWordsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);  //定义回调处理消息函数   int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){          // 创建一个窗口类分为三步:1.设计窗口类 2.注册窗口类 3.创建窗口 4.显示及更新窗口          // 步骤1.设计窗口类          WNDCLASS wc; ……          // 步骤2:注册窗口类          RegisterClass(&wc);           // 步骤3:创建窗口          HWND hw = NULL;             hw = CreateWindow("Icanth2011", "My Fist Win32 Application Project!~", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 600, 400, NULL, NULL, hInstance, NULL);          // 步骤4:显示及更新窗口          ShowWindow(hw, SW_SHOWNORMAL);          UpdateWindow(hw);          // 消息循环          MSG msg;          BOOL bRet;          while((bRet=GetMessage(&msg, NULL, 0, 0))!=0){                    if(-1 == bRet){                             return -1;                    }                    TranslateMessage(&msg);                    DispatchMessage(&msg);          }          return msg.wParam; } | 
 | 
   
 
 
由此可见,Win32 Application 程序的组成分为如下几个部分:
 
1.       找到WinMain程序入口,并开始执行
 
2.       创建并设计窗口类
 
3.       注册窗口类
 
4.       创建窗口
 
5.       显示及更新窗口
 
6.       循环获取消息,经处理,交还系统让其调用相关回调消息处理函数进行处理。
 
 
 
二、MFCArchitecture
 
由于Windows API过多,不方便程序员使用,并且非面对象。于是MFC被用于对Windows API进行封装,MFC始终实际运行过程就是Win32 Application程序的运行过程。
 
 
 
1.      MFC的项目结构
 
利用MFC AppWipzard自动生成的项目包括五个文件:CMyFirstMFCApp、CMainFrame、CFirstMFCDoc、CMyFirstCView、CAboutDlg。CMyFirstMFCApp继承自CWinApp,CMainFrame、CMyFirstCView、CAboutDlg都继承自CWnd,CFirstMFCDoc继承自CDocument,体现“文档/视图”结构。其项目结构如下所示:
 
 
 
2.      MFC的执行过程
 
对于MFC框架运行过程进行剖析,最好的资料是MFC源代码,VC6位于“\Microsoft Visual Studio\VC98\MFC\SRC”下。执行过程如下:
 
| |  定义theApp(:CMyFistMFCApp)                    ——>执行构造函数:CWinApp()->CMyFistMFCApp()->                                       ——>程序入口_tWinMain (宏,定义为WInMain) ——>执行AftxWinMain   | 
 | 
   
 
 
 
 
 
 
 
 
 
2.1  MFC的WinMain
 
在\SRC\APPMODUL.CPP中,可找到如下代码:
 
| |  MFC\SRC\APPMODUL.CPP:   extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,          LPTSTR lpCmdLine, int nCmdShow) {          // call shared/exported WinMain          return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); }   | 
 | 
   
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
而其中_tWinMain其实就是WinMain函数的宏,定义如下:
 
 
 
| |  #define _tmain      main #define _tWinMain   WinMain #ifdef  _POSIX_ #define _tenviron   environ   | 
 | 
   
 
 
 
 
 
 
 
由此可见,WinMain中调用AfxWinMain进行处理。MFC包含此文件,故将找到此入口并自动调用执行。
 
 
 
2.2  theApp全局对象
 
在Project\CMyFirstMFCApp.CPP中,可找到一行代码发下:
 
| |  Project\CMyFirstMFCApp.CPP:   / // The one and only CMyFistMFCApp object CMyFistMFCApp theApp;   | 
 | 
   
 
 
 
 
 
 
 
 
 
当定义theApp时,将先执行CWinApp(\MFC\SRC\APPCORE.CPP)的构造函数:
 
| |  \MFC\SRC\APPCORE.CPP:   CWinApp::CWinApp(LPCTSTR lpszAppName) // 有在该类定义时有默认值NULL {          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;          ASSERT(AfxGetThread() == NULL);          pThreadState->m_pCurrentWinThread = this;          ASSERT(AfxGetThread() == this);           m_hThread = ::GetCurrentThread();          m_nThreadID = ::GetCurrentThreadId();            // initialize CWinApp state          ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please          pModuleState->m_pCurrentWinApp = this; // handle,this代表子类CMyFirstMFCApp对象          ASSERT(AfxGetApp() == this); …… }   | 
 | 
   
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2.3  AfxWinMain(WINMAIN.CPP)
 
 
 
1.AfxWindMain定义
 
 
 
| |  \MFC\SRC\WINMAIN.CPP:   int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,          LPTSTR lpCmdLine, int nCmdShow) {          CWinThread* pThread = AfxGetThread();          CWinApp* pApp = AfxGetApp();          if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))          if (pApp != NULL && !pApp->InitApplication())                    goto InitFailure;          if (!pThread->InitInstance())          {                    if (pThread->m_pMainWnd != NULL)                    {                             pThread->m_pMainWnd->DestroyWindow();                    }                    goto InitFailure;          }          nReturnCode = pThread->Run(); }   | 
 | 
   
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2.AfxGetThread 
 
AfxGetThread(THRDCORE.CPP)中调用AfxGetApp,和afxGetApp返回同值,代码如下所示:
 
| |  \MFC\SRC\ THRDCORE.CPP:   CWinThread* AFXAPI AfxGetThread() {          // check for current thread in module thread state          AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();          CWinThread* pThread = pState->m_pCurrentWinThread;          // if no CWinThread for the module, then use the global app          if (pThread == NULL)                    pThread = AfxGetApp();          return pThread; }   | 
 | 
   
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3.AfxGetApp
 
AfxGetApp(AFXWIN1.INL)中定义:
 
| |  AFXWIN1.INL:   _AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp(){ return afxCurrentWinApp; }   | 
 | 
   
 
 
 
 
 
 
 
 
 
而afxCurrentWinApp定义位于AFXWIN.H文件中,如下:
 
| |  AFXWIN.H:   #define afxCurrentWinApp AfxGetModuleState()->m_pCurrentWinApp   | 
 | 
   
 
 
 
 
 
 
 
即为CWinApp构造函数时初始化为this的m_pCurrentWinApp。
 
 
 
4.InitInstance
 
类CWinAPP(APPCORE.CPP)中InitInstance函数定义为:
 
| |  \MFC\SRC\ APPCORE.CPP:   // overrides for implementation virtual BOOL InitInstance();   | 
 | 
   
 
 
 
 
 
 
 
类InitInstance即为虚函数,根据多态性,将调用CMyFirstMFCApp类的InitInstance。
 
 
 
2.4  InitInstance(CMyFirstMFCAPP.CPP)
 
| |  \MFC\SRC\ CMyFirstMFCAPP.CPP:   BOOL CMyFistMFCApp::InitInstance() {          CSingleDocTemplate* pDocTemplate;          pDocTemplate = new CSingleDocTemplate(                    IDR_MAINFRAME,                    RUNTIME_CLASS(CMyFistMFCDoc),                    RUNTIME_CLASS(CMainFrame),       // main SDI frame window                    RUNTIME_CLASS(CMyFistMFCView));          AddDocTemplate(pDocTemplate);          m_pMainWnd->ShowWindow(SW_SHOW);          m_pMainWnd->UpdateWindow(); }   | 
 | 
 
  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2.5  MFC框架窗口
 
CFirstMyMFC有两个窗口,其中一个是CMainFrame。
 
 
 
2.5.1 设计和注册窗口
 
 
 
1.       CMainFrame::PreCreateWindow定义(\Project\CMainFrame.cpp)
 
| |  \MFC\SRC\ CMyFirstMFCAPP.CPP:   BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) {          if( !CFrameWnd::PreCreateWindow(cs) )                    return FALSE;          return TRUE; }   | 
 | 
   
 
 
 
 
 
 
 
 
 
 
 
2.       CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) (\MFC\SRC\WINFRM.CPP)
 
 
 
 
 
| |  \MFC\SRC\ CMyFirstMFCAPP.CPP:   BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) {          if (cs.lpszClass == NULL)          {                    VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));                    cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background          }          return TRUE; }   | 
 | 
   
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
其中,AfxDeferRegisterClass即为AfxEndDeferRegisterClass的宏定义,位于AFXIMPL.H文件中:
 
| |  AFXIMPL.H:   #define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)   | 
 | 
   
 
 
 
 
 
 
 
3.       AfxEndDeferRegisterClass (位于WINCORE.CPP中)
 
此处指定DefWindowProc函数来处理回调消息。 (!~)
 
| |  MFC\SRC\WINCORE.CPP:   BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister) {          // mask off all classes that are already registered          AFX_MODULE_STATE* pModuleState = AfxGetModuleState();          fToRegister &= ~pModuleState->m_fRegisteredClasses;          if (fToRegister == 0)                    return TRUE;          LONG fRegisteredClasses = 0;          // common initialization          WNDCLASS wndcls;          memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults          wndcls.lpfnWndProc = DefWindowProc;          wndcls.hInstance = AfxGetInstanceHandle();          wndcls.hCursor = afxData.hcurArrow;          INITCOMMONCONTROLSEX init;          init.dwSize = sizeof(init);          // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go          if (fToRegister & AFX_WND_REG)          {                    // Child windows - no brush, no icon, safest default class styles                    wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;                    wndcls.lpszClassName = _afxWnd;                    if (AfxRegisterClass(&wndcls))                             fRegisteredClasses |= AFX_WND_REG;          }          …… }   | 
 | 
   
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4.       AfxRegisterClass  (位于WINCORE.CPP中)
 
| |  MFC\SRC\WINCORE.CPP:   BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass) {          WNDCLASS wndcls;          if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,                    &wndcls))          {                    // class already registered                    return TRUE;          }          if (!::RegisterClass(lpWndClass))          {                    TRACE1("Can't register window class named %s\n",                             lpWndClass->lpszClassName);                    return FALSE;          }          return TRUE; }   | 
 | 
 
  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2.5.2 创建窗口
 
1. CFrameWnd::Create  (WINFRM.CPP)
 
| |  MFC\SRC\WINFRM.CPP:   BOOL CFrameWnd::Create(LPCTSTR lpszClassName,          LPCTSTR lpszWindowName,          DWORD dwStyle,          const RECT& rect,          CWnd* pParentWnd,          LPCTSTR lpszMenuName,          DWORD dwExStyle,          CCreateContext* pContext) {          HMENU hMenu = NULL;          if (lpszMenuName != NULL)          {                    // load in a menu that will get destroyed when window gets destroyed                    HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU);                    if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)                    {                             TRACE0("Warning: failed to load menu for CFrameWnd.\n");                             PostNcDestroy();            // perhaps delete the C++ object                             return FALSE;                    }          }          m_strTitle = lpszWindowName;    // save title for later          if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,                    rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,                    pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))          {                    TRACE0("Warning: failed to create CFrameWnd.\n");                    if (hMenu != NULL)                             DestroyMenu(hMenu);                    return FALSE;          }          return TRUE; }   | 
 | 
   
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3.       CWnd:CreateEx (WINCORE.CPP)
 
| |  MFC\SRC\WINFRM.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 parameters          CREATESTRUCT cs;          cs.dwExStyle = dwExStyle;          ……          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);          …… }   | 
 | 
 
  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
以下是CREATESTRUCT和CreateWindowEx参数的对比:
 

 
 
由于CREATESTRUCT中的属性都定义为指针,故可在PreCreateWindow中更改属性,在CreateWindowEx中将更改显示。
 
 
 
4.      MFC的调用关系
 
① theApp
 
| |  theApp(CMyFirstMFCApp.CPP) ——> CWinAPP ::CWinAPP(){ pModuleState->m_pCurrentWinApp = this;  }   | 
 | 
   
 
 
 
 
 
 
 
② _tWinMain(APPMODUL.CPP)
 
| |  _tWinMain () { AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); }   | 
 | 
 
  
 
 
 
 
 
 
 
 
 
 
 
 
  
 
 
③ AfxWinMain(WinMain.CPP)
 
| |  int AFXAPI AfxWinMain() { CWinThread* pThread = AfxGetThread(); //——>return AfxGetApp()  (:THRDCORE.CPP)          CWinApp* pApp = AfxGetApp(); //——>return afxCurrentWInApp (:AFXWIN1.INL) //——>return AfxGetModuleState()->m_pCurrentWinApp (:AFXWIN.H) AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow); pApp->InitApplication(); pThread-> InitInstance ();          //——> CMyFirstMFCApp::InitInstance                    //——> AddDocTemplate(pDocTemplate);                             //——> m_pMainWnd->ShowWindow(SW_SHOW);                    //——> m_pMainWnd->UpdateWindow(); pThread->Run(); }   | 
 | 
 
  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
④ 窗口
 
设计和注册窗口:
 
| |  CMainFrame::PreCreateWindow (\Project\ CMainFrame.cpp)          ——>CFrameWnd::PreCreateWindow                    ——>AfxDeferRegisterClass(宏= AfxEndDeferRegisterClass) ——>AfxEndDeferRegisterClass ——>AfxRegisterClass          ——>::RegisterClass (SDK)   | 
 | 
   
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
创建窗口:
 
CFrameWnd::Create()
 
         ——>CFrameWnd::CreateEx()
 
——>CWnd::CreateEx()
 
         ——>virsual CWnd::PreCreateWIndow(虚函数,调用子类中CFrameWnd:: PreCreateWIndow), 
 
:: CreateWIndowEx()