剖析MFC框架的一些笔记

每个MFC程序都有一个the全局对象,此对象代表了这个应用程序,程序从这里诞生。

 

1、因theApp是全局对象,所以比winmain更早初始化。

 

2、theApp的初始化,先引发了其构造函数。因theApp派生于CWinApp,则也引发了CWinApp的构造函数

 

3、CWinApp中的几条重要的初始化代码:

AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;

pThreadState->m_pCurrentWinThread = this;

pModuleState->m_pCurrentWinApp = this;

可以看到m_pCurrentWinThread与m_pCurrentWinApp现在都指向theApp。

 

4、CWinApp初始化后,进入winmain。winmain中进行了如下调用:

return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

 

5、AfxWinMain中的重要代码:
CWinThread* pThread = AfxGetThread();//AfxGetThread其实就是取得了theApp的指针

CWinApp* pApp = AfxGetApp();//AfxGetApp其实就是取的了theApp的指针

 

AfxGetThread的定义:

CWinThread* AFXAPI AfxGetThread()

{

  AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
  CWinThread* pThread = pState->m_pCurrentWinThread;

 

  if (pThread == NULL)
      pThread = AfxGetApp();

 

 return pThread;//pThread指向theApp

}

 

AfxGetApp的定义:

_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()
 { return afxCurrentWinApp; }

 

#define afxCurrentWinApp    AfxGetModuleState()->m_pCurrentWinApp//AfxGetApp也返回了theApp的指针。

 

AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow);//内部的初始化操作

节选其中的一些重要代码:

// 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();
 }

 

pApp->InitApplication();

这里相当于调用了theApp的InitApplication,但因大多数情况下无需改写此虚函数,所以实际调用的是CWinApp::InitApplication.其中的操作是为MFC内部管理而做,与Document Template有关。

 

pThread->InitInstance();

这里相当于调用了theApp的InitInstance,因theApp中改写了这个虚函数,所以直接调用即可。节选其中的重要代码:

 

//new一个CMultiDocTemplate对象并初始化,用来管理Doccument/view/Frame三者之间的关系

CMultiDocTemplate* pDocTemplate;
 pDocTemplate = new CMultiDocTemplate(
  IDR_MDITYPE,
  RUNTIME_CLASS(CMDIDoc),
  RUNTIME_CLASS(CChildFrame), // custom MDI child frame
  RUNTIME_CLASS(CMDIView));
 AddDocTemplate(pDocTemplate);

 

//主框架窗口的初始化

CMainFrame* pMainFrame = new CMainFrame;

//LoadFrame会触发WM_CREATE消息(中间一系列调用不详述了)
 if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
  return FALSE;

 m_pMainWnd = pMainFrame;

 

CMainFrame::OnCreate中,主要实现工具栏、状态栏的初始化。

 

//显示主框架窗口,并发出更新窗口

 pMainFrame->ShowWindow(m_nCmdShow);
 pMainFrame->UpdateWindow();

 

pThread->Run();

这里相当于调用了theApp的Run,但是theApp通常不会改写这个虚函数,所以实际调用的是CWinApp的Run。节选一些代码:

int CWinApp::Run()

    return CWinThread::Run();

 

int CWinThread::Run()

{

  do
  {
    if (!PumpMessage())
        return ExitInstance();//收到WM_QUIT消息

    if (IsIdleMessage(&m_msgCur))
    {
         bIdle = TRUE;
         lIdleCount = 0;
    }

  } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));

}

 

BOOL CWinThread::PumpMessage()

{

     if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))

          return FALSE;//如取得的消息是WM_QUIT,则返回FALSE

 

      if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
      {
               ::TranslateMessage(&m_msgCur);
               ::DispatchMessage(&m_msgCur);
      }
      return TRUE;

}

 

以上代码非常清楚的显示了,Run其实就是执行了消息循环.

 

通过以上框架的剖析,学到如下知识:

1、虚函数的应用。如子类没有改写了父类的虚函数,使用子类调用该函数时,调用的是父类的函数。

2、类的构造与析构顺序。类的构造,是先构造其父类(如果有),再构造自己。析构时,是先析构自己,在析构父类(如果有)。

你可能感兴趣的:(thread,框架,Module,null,mfc,initialization)