探索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;}
- 探索MFC读书笔记——MFC初始化
- 探索MFC读书笔记——C Runtime
- 探索MFC读书笔记——RTTI
- 探索MFC读书笔记——WinMain函数的优化
- 探索MFC读书笔记——CommandRouting(命令绕行)
- 探索MFC笔记——消息映射
- 【深入浅出MFC】 仿真—重要类初始化
- 探索MFC中单文档中m_pMainWnd的初始化过程
- MFC学习笔记三——MFC程序的初始化过程
- MFC六大关键技术之(一)—— 初始化过程
- MFC 六大关键技术之仿真——初始化过程
- MFC六大关键技术之(一)—— 初始化过程
- MFC第二天——基类2及程序初始化
- MFC通用控件初始化 —— InitCommonControlsEx Function
- MFC六大关键技术之(一)—— 初始化过程
- MFC六大关键技术之(一)—— 初始化过程
- MFC基础知识(八)——GridCtrl控件配置与初始化
- 深入浅出MFC读书笔记——c++对象重要性质
- 每天自动备份mysql脚本
- WebRequest.Credentials 属性
- SQL server 使用存储过程生成流水号
- Passing multiple POST parameters to Web API Controller Methods
- 面相与招聘
- 探索MFC读书笔记——MFC初始化
- POJ训练计划3295_Tautology(构造/类栈处理)
- Baidu open source projects
- Mahout学习之Mahout简介、安装、配置、入门程序测试
- AT 汇编
- 如何利用诊断文件监督数据库实例
- 我的竞争力是,有你们的帮助。
- C# 语言和 .NET Framework 介绍
- hdoj 1052 Tian Ji -- The Horse Racing【田忌赛马】 【贪心】