探索MFC读书笔记——MFC初始化

来源:互联网 发布:sql 删除数据表字段 编辑:程序博客网 时间:2024/05/16 14:42

MFC的初始化过程:

一、首先看一下基本的类图:

 

1、从图中可以看出,最原始的基类是CObject;而常见的MFC类CWinThread、CDocument、CWnd都是从CObject的子类CCmdTraget派生而来,CWinApp是从CWinThread派生而来, CFrameWnd、CView从CWnd派生而来。

2、注意CWinApp是一个线程类(作为独立线程运行),有自己的虚函数InitApplication、同时重写父类CWinThread的虚函数InitInstance。同时又两个数据成员:CWinApp* m_pCurrentWinApp, CWnd* m_pMainWnd。

     注意:m_pCurrentWinApp在CWinApp的构造函数中被初始化为this,(因此可以判断m_pCurrentWinApp总是指向当前对象),

     m_pMainWnd用来实现CWnd(或其子类)与CWinApp(或其子类)之间的关联。

3、我们再来看CWnd类,它是窗口类,它实现了虚函数Create、PreCreateWindow;还有非虚函数CreaeEx,在CreateEx函数中调用PreCreateWindow

4、框架窗口CFrameWnd重写了父类CWnd的虚函数Create和PreCreateWIndow;值得注意的是,CFrameWnd::Create函数中调用了CreateEx函数(一般为父类的),此时将导致PreCreateWindow执行。

 

二、初始化过程

1、以MFC单文档程序为例:项目名为:XXX

      根据项目向导生成的程序中主要包含:

       CXXXApp : public CWinApp;

       CXXXDoc : public CDocument;

       CXXXView : public CView;

       CMainFrame : public CFrameWnd;

       同时在CXXXApp.cpp文件中定义了全局变量: CXXXApp theApp;

 

2、关于入口点WinMain

 (1)、运行时启动代码调用 _tWinMain

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow){ // call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);}

(2)、由上述代码可知,_tWinMain调用AfxWinMain函数,其简化代码(仅为表述初始化而为)如下:

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow){     ASSERT(hPrevInstance == NULL);     int nReturnCode = -1;     CWinThread* pThread = AfxGetThread();     CWinApp* pApp = AfxGetApp();     // AFX internal initialization     if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))     goto InitFailure;     // App global initializations (rare)     if (pApp != NULL && !pApp->InitApplication())     goto InitFailure;     // Perform specific initializations     if (!pThread->InitInstance())     {         nReturnCode = pThread->ExitInstance();         goto InitFailure;     }     nReturnCode = pThread->Run();     InitFailure:          AfxWinTerm();     return nReturnCode;}

(3)、下面来分析一下,AfxWinMain中执行的几个函数:

       1**、首先是AfxGetThread

CWinThread* AFXAPI AfxGetThread(){// check for current thread in module thread stateAFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();CWinThread* pThread = pState->m_pCurrentWinThread;// if no CWinThread for the module, then use the global appif (pThread == NULL)pThread = AfxGetApp();return pThread;}

该函数首先获得当前线程的状态信息,然后将状态信息中的m_pCurrentWinThread指针赋给pThread;接着判断pThread,如果为NULL,则通过AfxGetApp函数来再次赋值。

      2**、CWndApp* pApp = AfxGetApp();可以看出pThread与pApp的值,在“获取当前线程状态信息失败”的条件下,是相等的。

      3**、接下来是AfxWinInit,做一些线程初始化

      4**、然后就是我们熟悉的InitApplication 和 InitInstance,此处值得注意的是pApp->InitApplication和pThread->InitInstance函数,

从此处可以推断pApp与pThread的值在正常情况下应该是相等的。

      5**、最后调用pThread的Run函数,从此处可以看出来,MFC的动力源就在此处,消息循环应该就在这个Run函数之中。

3、初始化过程

     (1)、首先是InitApplication、然后是InitInstance,

     (2)、调用CXXXApp::InitInstance的简化代码如下:

    

BOOL CMFC_6_15App::InitInstance(){        //AfxEnableControlContainer();   
        CSingleDocTemplate* pDocTemplate;pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CMFC_6_15Doc),RUNTIME_CLASS(CMainFrame),       // main SDI frame windowRUNTIME_CLASS(CMFC_6_15View));AddDocTemplate(pDocTemplate);// Parse command line for standard shell commands, DDE, file openCCommandLineInfo cmdInfo;ParseCommandLine(cmdInfo);// Dispatch commands specified on the command lineif (!ProcessShellCommand(cmdInfo))return FALSE;// The one and only window has been initialized, so show and update it.m_pMainWnd->ShowWindow(SW_SHOW);m_pMainWnd->UpdateWindow();return TRUE;}

        1**、首先是创建单文档模板,添加模板,

        2**、然后是ParseCommandLine(cmdInfo)和ProcessShellCommand(cmdInfo);(初始化时)ParseCommandLine函数会cmdInfo的m_nShellCommand成员的值设置为:FileNew(枚举类型)。

        在执行ProcessShellCommand(cmdInfo)时,调用CWinApp::OnFileNew()

        ProcessShellCommand部分代码如下:

        switch (rCmdInfo.m_nShellCommand){case CCommandLineInfo::FileNew:if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL))OnFileNew();if (m_pMainWnd == NULL)bResult = FALSE;break;

       CWinApp::OnFileNew()代码如下:

void CWinApp::OnFileNew(){if (m_pDocManager != NULL)m_pDocManager->OnFileNew();}

      CDocManager::OnFileNew()函数中调用“pTemplate->OpenDocumentFile(NULL)”函数;

      因为此处创建的是单文档,根据多态性,该语句将执行CSingleDocTemplate::OpenDocumentFile函数;

      CSingleDocTemplate::OpenDocumentFile中执行“pThread->m_pMainWnd = pFrame;”(也可以追踪pFrame,pFrame应该是CMainFrame的地址)。此过程中要创建CMainFrame对象,
     (3)、CMainFrame的构造函数中会调用Create函数;是CFrameWnd::Create函数;

     (4)、CFrame::Create函数中还会调用CreateEx,这里的CreateEx是其父类CWnd::CreateEx;

     (5)、在CWnd::CreateEx中会调用PreCreateWindow。

4、MFC初始化过程总结

     初始化过程可以简化描述为:   

     CWinApp* pApp = AfxGetApp();

     pApp->InitApplication();
     pApp->InitInstance();//在此过程中调用了PreCreateWindow和Create函数。
     pApp->Run();

5、附上书中的仿真程序:

//MFC.h
#define BOOL int#define TRUE 1#define FALSE 0#include <iostream>using namespace std;class CObject{public:CObject(){cout<< "CObject Constructor"<<endl;}~CObject(){cout<< "CObject Destructor"<<endl;}};class CCmdTraget : public CObject{public:CCmdTraget(){cout<<"CCmdTraget Constructor"<<endl;}~CCmdTraget(){cout<<"CCmdTraget Destructor"<<endl;}};class CWinThread : public CCmdTraget{public:CWinThread(){cout<<"CWinThread Constructor"<<endl;}~CWinThread(){cout<<"CWinThread Destructor"<<endl;}virtual BOOL InitInstance(){cout<<"CWinThread::InitInstance"<<endl;return TRUE;}virtual int Run(){cout<<"CWinThread::Run"<<endl;return 1;}};class CWnd;class CWinApp : public CWinThread{public:CWinApp* m_pCurrentWinApp;CWnd* m_pMainWnd;public:CWinApp(){    m_pCurrentWinApp = this;cout<<"CWinApp Constructor"<<endl;}~CWinApp(){cout<<"CWinApp Destructor"<<endl;}virtual BOOL InitApplication(){cout<<"CWinApp::InitApplication"<<endl;return TRUE;}virtual BOOL InitInstance(){cout<<"CWinApp::InitInstance"<<endl;return TRUE;}virtual int Run(){cout<<"CWinApp::Run"<<endl;return CWinThread::Run();}};class CDocument : public CCmdTraget{public:CDocument(){cout<<"CDocument Constructor"<<endl;}~CDocument(){cout<<"CDocument Destructor"<<endl;}};class CWnd : public CCmdTraget{public:CWnd(){cout<<"CWnd Constructor"<<endl;}~CWnd(){cout<<"CWnd Destructor"<<endl;}virtual BOOL Create();BOOL CreateEx();virtual BOOL PreCreateWindow();};class CFrameWnd : public CWnd{public:CFrameWnd(){cout<<"CFrame Constructor"<<endl;}~CFrameWnd(){cout<<"CFrameWnd Destructor"<<endl;}BOOL Create();virtual BOOL PreCreateWindow();};class CView : public CWnd{public:CView(){cout<<"CView Constructor"<<endl;}~CView(){cout<<"CView Destructor"<<endl;}};//global functionCWinApp* AfxGetApp();
////////////////////////////////////////////////////////////////////
//MFC.cpp
#include "My.h"extern CMyWinApp theApp;CWinApp* AfxGetApp(){return theApp.m_pCurrentWinApp;}BOOL CWnd::Create(){cout<<"CWnd::Create"<<endl;return TRUE;}BOOL CWnd::CreateEx(){cout<<"CWnd::CreateEx"<<endl;PreCreateWindow();return TRUE;}BOOL CWnd::PreCreateWindow(){cout<<"CWnd::PreCreateWindow"<<endl;return TRUE;}BOOL CFrameWnd::Create(){cout<<"CFrameWnd::Create"<<endl;CreateEx();return TRUE;}BOOL CFrameWnd::PreCreateWindow(){cout<<"CFrameWnd::PreCreateWindow"<<endl;return TRUE;}
/////////////////////////////////////////////////////////////////////
//My.h#include <iostream>#include "MFC.h"using namespace std;class CMyWinApp : public CWinApp{public:    CMyWinApp(){        cout<<"CMyWinApp Constructor"<<endl;}~CMyWinApp(){        cout<<"CMyWinApp Destructor"<<endl;}    virtual BOOL InitInstance();};class CMyFrameWnd : public CFrameWnd{public:    CMyFrameWnd(){        cout<<"CMyFrameWnd Constructor"<<endl;Create();}    ~CMyFrameWnd(){        cout<<"CMyFrameWnd Destructor"<<endl;}    BOOL PreCreateWindow(){        cout<<"CMyFrameWnd::PreCreateWindow"<<endl;return CWnd::PreCreateWindow();}};
////////////////////////////////////////////////////////////////////////
<pre class="cpp" name="code">//My.cpp#include "My.h"CMyWinApp theApp;//global objectBOOL CMyWinApp::InitInstance(){    cout<<"CMyWinApp::InitInstance"<<endl;m_pMainWnd = new CMyFrameWnd;return TRUE;}int main(int argc, char** argv){cout<<"------------------------------"<<endl;CWinApp* pApp = AfxGetApp();//CMyWinApp myApp; pApp->InitApplication();pApp->InitInstance();pApp->Run();return 0;}

//My.cpp#include "My.h"CMyWinApp theApp;//global objectBOOL CMyWinApp::InitInstance(){    cout<<"CMyWinApp::InitInstance"<<endl;m_pMainWnd = new CMyFrameWnd;return TRUE;}int main(int argc, char** argv){cout<<"------------------------------"<<endl;CWinApp* pApp = AfxGetApp();//CMyWinApp myApp; pApp->InitApplication();pApp->InitInstance();pApp->Run();return 0;}


 

0 0
原创粉丝点击