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

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 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;
}

该函数首先获得当前线程的状态信息,然后将状态信息中的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 window
		RUNTIME_CLASS(CMFC_6_15View));
	AddDocTemplate(pDocTemplate);

	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);

	// Dispatch commands specified on the command line
	if (!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 function

CWinApp* 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 object

BOOL 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 object

BOOL 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值