MFC程序的启动过程与相关函数执行顺序

合集下载

MFC 执行顺序

MFC 执行顺序

MFC的程序执行顺序很多刚学MFC的人都会被MFC给弄的晕头转向。

以前传统的C语言中的main()不见了,window sdk api 中的WinMain()函数也不见了,到底用MFC编写的程序是如何开始运行的呢?到底MFC有没有遵从最基本的C++的标准呢?到底MFC的代码运行的顺序又是怎么样的呢?那么多个文件,那么多函数,到底哪一个先运行,哪一个后运行,哪一个调用哪一个,哪一个又被哪一个调用(你看晕了吧?那么多“哪一个”^_^)?这里这么复杂,到底最真是的是怎么一回事呢?我开始学习的时候,也是一头雾水,什么都不明白,但是为了能先学习一些其他的,我囫囵吞枣的看了过去,先学习了CDIALOG和CVIEW的一些用法,并能编出了一个很简单的程序。

前几天,上网的时候,看到好多人都在看《孙鑫vc++讲座》视频教程,好像大家反应还不错,于是,我就去找个地方下载下来看了。

刚好今天看到了MFC的运行机制,里面讲到了MFC的运行顺序。

孙同学在视频中是利用实例,利用断点,然后不断的进行调试运行,以实事(实事胜于雄辩啊!!!)告诉我们,MFC是如何开始运行的。

下面,我就根据我看到的教程,和网上一些前辈整理出来的材料在整理:重点:MFC运行机制执行顺序各个函数用途以及调用顺序孙同学在视频中反复说明的是:MFC的程序和C语言的程序,从执行原理上说,是完全一致的。

抓住这一点,那么对于理解MFC程序的运行机制也就相对于简单了。

C中的main函数就相当于MFC中的WinMain函数。

感兴趣的可以利用VC的断点设置自己跟踪下面讲述的各个函数,就明白它的执行顺序了。

一、C语言程序执行步骤在C语言中,大约的步骤如下:1,全局变量内存分配例子如下:#include <iostream.h>int a=88;main(){cout<<a<<endl;}如果我们在main前设置断点,我们就会发现,在进入main之前,a就已经存在了。

MFC程序执行过程

MFC程序执行过程

很是空闲最近.转载一些东西吧..就当是复习...再不看看,就忘光了MFC 应用程序的操作步骤可归结为四步:(1) 创建应用程序对象theApp(2) 执行MFC提供的WinMain()函数(3) WinMain()调用InitInstance()函数,此函数创建文档模板,主框架窗口,文档和视图(4) WinMain()调用Run()函数,此函数执行主消息循环,以获取和分派Windows消息。

WinMain()是函数的入口点,该函数的主要任务是完成一些初始化的工作和维护了一个消息循环。

他们的工作流程如下:入口(WinMain())---->MyRegisterClass()---->InitInstance ()--->while消息循环。

函数由入口开始执行,之后调用 MyRegisterClass()注册窗口类,之后InitInstance ()生成并显示窗口,这样之后,就完成了一个窗口的初始化工作了(当然,在MyRegisterClass(),InitInstance ()中都需要调用相应的API函数来具体的实现),然后就是维护消息循环,至此,程序的基本结构就差不多建立了。

以后程序的运作就靠个消息循环来推动了.1、创建Application object对象theApp程序一开始生产一个(且只有一个)Application object对象theApp,也即一个CWinApp对象,这个全局对象一产生,便执行其构造函数,因为并没有定义CMyWinApp构造函数,所以即执行CWinApp类的构造函数。

该函数定义于APPCORE.CPP第75行,你可以自己搜出来啃一啃,因此,CWinApp之中的成员变量将因为theApp这个全局对象的诞生而获得配置与初值。

2、WinMain登场用SDK编程序时,程序的入口点是WinMain函数,而在MFC程序里我们并没有看到WinMain函数,哦!~ 原来她是被隐藏在MFC代码里面了。

MFC流程

MFC流程

MFC流程MFC程序文件名为Test.所以产生的5个类分别为1、CAboutDlg继承于CDialog2、CMainFrame继承于CFrameWnd1、CTestApp继承于CWinApp1、CTestDoc继承于CDocument1、CTestView继承于CView一、窗口产生流程1、设计窗口类2、注册窗口类3、产生窗口4、显示窗口5、更新窗口二、MFC中的细节1、WinMain函数的地址在C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\APPMODUL.CPP文件中extern "C" int WINAPI_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow){// call shared/exported WinMainreturn AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);}其中_tWinMain是WinMain的宏定义如下: (此定义在文件C:\Program Files\Microsoft VisualStudio\VC98\Include\TCHAR.H中)#define _tWinMain WinMain而_tWinMain调用的是AfxWinMain.2、theApp全局对象先于WinMain运行产生全局对象,在程序入口函数WinMain加载时,系统就已经为全局变量或全局对象分配了存储空间,并为它们赋了初始值。

存放在静态数据区。

每一个MFC程序有且仅有一个从应用程序类(CWinApp)派生的类。

每一个MFC程序实例有且仅有一个该派生类的实例化对象,也就是theApp全局对象。

该对象表示应用程序本身。

由于在子类的构造之前会先调用其父类的构造函数。

MFC程序流程

MFC程序流程

MFC程序流程程序的诞生application object产生,内存于是获得配置,初值设立afxWinMain执行afxwinInit,调用afxInitThread把消息队列加大afxWinMain执行 InitApplication 是CWinApp的虚函数,通常不该写afxWinMain执行 InitInstance 是CWinApp的虚函数,必须改写CMyFrameWnd构造式调用Create ,产生窗口,回到InitInstance中继续执行ShowWindow 显示窗口执行UpdateWindow 发送WM_PAINT回到AfxWinMain 执行Run,进入循环。

程序开始运作程序获得WM_PAINT消息。

(藉由CWinApp::Run中的::GetMessage循环)WM_PAINT经由DispatchMessage送到窗口函数CWnd::DefWindowProc中。

CWnd::DefWindowProc将消息绕行过消息映射表格(Message Map)绕行过程中发现有吻合项目,于是调用项目中对应的函数,此函数是应用程序利用BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间的宏设立起来的。

标准消息的处理历程亦有标准命名,例如WM_PAINT必然由OnPaint处理程序的死亡:使用者按关闭。

发送WM_CLOSECMyFrameWnd并没有设置WM_CLOSE处理例程,于是交给于设置之处理例程。

预设函数对于WM_CLOSE的处理方式是调用::DestroyWindow并因而发出WM_DESTROY预设之WM_DESTORY处理方式是调用::PostQuitMessge发出WM_QUITCWinApp::Run收到WM_QUIT后会结束内部消息循环,然后调用ExitInstance,CWinApp的虚函数如果CMyWinApp改写了ExitInstance,那么CWinApp::Run就调用CMyWinApp::ExitInstance.回到AfxWinMain 执行 AfxWinTerm,结束程序。

浅析MFC程序基本运行机制

浅析MFC程序基本运行机制

2. CWinApp — 应用程序类
就像标题所说的,CWinApp 的作用是用来产生 MFC 应用程序对象。每个 MFC 程序都要求存在一个派生 自 CWinApp 的子类作为应用程序的类,并且需要我们通过这个子类,改写某些虚函数。可见 CWinApp 的 重要性,显然,CWinApp 是一个很大的类,他得完成很多工作。 以下是 MFC7.1 的 CWinApp 的定义源代码的超精简版本(完整版在FC 的基本运行机制之前,先让我们来回忆一下使用 C++/SDK 写 Windows GUI 程序的顺序: 调用 WinMain 入口函数→注册窗口类→窗口实例化→建立消息循环→处理消息 可以说,几乎每个 Windows GUI 程序的建立和运行,都要经过上面的几个步骤,MFC 程序也不例外。但 是由于 MFC 是以 C++为基础,所以它势必会使用 OOP 思想进行架构。而这一切,都会导致我们研究 MFC 的方式会和 C++/SDK 有那么一点区别。 我们在下面会以 MFC 的 Class 为中心进行研究,而非 Windows 窗体的线性行为。这意味着我们得忍受在 几个类中跳来跳去。是的,你可能会感到身体不适,我同样有这种感觉,我从小就恨透了 goto…… 那么,就让我们先来看看使用 MFC 改如何创建一个简单的窗体,然后在逐步抽丝剥茧,剖析 MFC 程序 的基本运行机理。
/************************************************** ** Project:MFCAppUser ** File:MFCAppUser.cpp
** Edition:NULL ** Coder:KingsamChen [MDSA Group] ** Last Modify:2008-8-9 **************************************************/ #include <afxwin.h> // 必备的头文件,这个头文件间接包含了 windows.h class CMFCApp : public CWinApp // 继承 CWinApp { public: virtual BOOL InitInstance(); // 虚函数 // 这个函数必须重写 }; class CMFCAppWindow : public CFrameWnd { public: CMFCAppWindow() // 在构造函数里创建窗体~ { Create(NULL,"KC's Windows"); // 除前两个参数外,其他参数均有初始值 } // 下面是消息映射的东东 afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); // 左键双击的消息声明 afx_msg void OnPaint(); // WM_PAINT 消息声明 DECLARE_MESSAGE_MAP() // 消息映射宏 }; // MS 叫做消息映射表 BEGIN_MESSAGE_MAP(CMFCAppWindow, CFrameWnd) ON_WM_LBUTTONDBLCLK() ON_WM_PAINT() END_MESSAGE_MAP() // 对应的消息处理,类似 SDK 窗体里面的回调函数处理过程 void CMFCAppWindow::OnLButtonDblClk(UINT nFlags, CPoint point) { MessageBox("KC is a Fucker", NULL, MB_OK); } void CMFCAppWindow::OnPaint() { CPaintDC Paint(this); Paint.TextOut(0, 0, "This is a sample for MFC");

MFC 运行过程

MFC 运行过程

执行一个windows应用程序包括初始化,运行和终止三大任务,MFC中的应用类封装了windows应用程序要做的这三大任务,这三大任务对应的三个主要函数就是InitInstance(),Run()和ExitInstance()。

应用类的基类是CWinApp类,MFC AppWizard自动生成的应用程序框架中的应用类就是由CWinApp类派生的。

注:应用程序必须有而且只能有一个CWinApp派生类,而且这个类只能有一个对象,这个对象是一个全程对象,即theAppCWinApp类有下面几个关键的虚函数,可供用户重载:InitInstance(),Run(),ExitInstance(),OnIdle()其中InitInstance()函数是必须重载的,而通常情况下也只需要重载InitInstance(),其他函数用户根据需要决定是否重载。

由于InitInstance()必须重载,所以在MFC AppWizard自动生成的应用程序框架中就自动重载了应用程序运行过程:InitInstance() 注:因为AppWizard已经重载了InitInstance(),所以这里调用的InitInstance()就是程序中重载的InitInstance() Run()注:WinMain()函数隐藏在应用框架内部,是看不到的。

InitInstance()函数:顾名思义,InitInstance()函数就是初始化实例。

Windows对同一个应用程序可以运行多个实例。

比如,如果已经在运行任务管理器,用户还可以再一次或多次启动任务管理器。

这样,系统就有多个任务管理器同时在运行,这些运行着的任务管理器就是任务管理器应用程序的多个运行实例。

当每次启动某个应用程序的一个实例时,WinMain()函数都要调用InitInstance()函数。

Run()函数:应用程序的大部分时间都是在应用类的Run()成员函数中打转转。

WinMain()函数在调用InitInstance()函数进行初始化完毕之后,就调用Run()函数来处理消息循环。

MFC程序中消息以及函数的处理顺序简介

MFC程序中消息以及函数的处理顺序简介

MFC程序中消息以及函数的处理顺序简介MFC应用程序中处理消息的顺序1.AfxWndProc()该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc2.AfxCallWndProc() 该函数负责保存消息(保存的内容主要是消息标识符和消息参数)供应用程序以后使用,然后调用WindowProc()函数3.WindowProc()该函数负责发送消息到OnWndMsg()函数,如果未被处理,则调用DefWindowProc()函数4.OnWndMsg()该函数的功能首先按字节对消息进行排序,对于WM_COMMAND消息,调用OnCommand()消息响应函数,对于WM_NOTIFY消息调用OnNotify()消息响应函数。

任何被遗漏的消息将是一个窗口消息。

OnWndMsg()函数搜索类的消息映像,以找到一个能处理任何窗口消息的处理函数。

如果OnWndMsg()函数不能找到这样的处理函数的话,则把消息返回到WindowProc()函数,由它将消息发送给DefWindowProc()函数5.OnCommand()该函数查看这是不是一个控件通知(lParam参数不为NULL,如果lParam参数为空的话,说明该消息不是控件通知),如果它是,OnCommand()函数会试图将消息映射到制造通知的控件;如果他不是一个控件通知(或者如果控件拒绝映射的消息)OnCommand()就会调用OnCmdMsg()函数6.OnCmdMsg()根据接收消息的类,OnCmdMsg()函数将在一个称为命令传递(Command Routing)的过程中潜在的传递命令消息和控件通知。

例如:如果拥有该窗口的类是一个框架类,则命令和通知消息也被传递到视图和文档类,并为该类寻找一个消息处理函数MFC应用程序创建窗口的过程1.PreCreateWindow()该函数是一个重载函数,在窗口被创建前,可以在该重载函数中改变创建参数(可以设置窗口风格等等)2.PreSubclassWindow() 这也是一个重载函数,允许首先子分类一个窗口3.OnGetMinMaxInfo()该函数为消息响应函数,响应的是WM_GETMINMAXINFO消息,允许设置窗口的最大或者最小尺寸4.OnNcCreate()该函数也是一个消息响应函数,响应WM_NCCREATE消息,发送消息以告诉窗口的客户区即将被创建5.OnNcCalcSize()该函数也是消息响应函数,响应WM_NCCALCSIZE消息,作用是允许改变窗口客户区大小6.OnCreate()该函数也是一个消息响应函数,响应WM_CREATE消息,发送消息告诉一个窗口已经被创建7.OnSize()该函数也是一个消息响应函数,响应WM_SIZE消息,发送该消息以告诉该窗口大小已经发生变化8.OnMove()消息响应函数,响应WM_MOVE消息,发送此消息说明窗口在移动9.OnChildNotify()该函数为重载函数,作为部分消息映射被调用,告诉父窗口即将被告知一个窗口刚刚被创建MFC应用程序关闭窗口的顺序(非模态窗口)1.OnClose()消息响应函数,响应窗口的WM_CLOSE消息,当关闭按钮被单击的时候发送此消息2.OnDestroy()消息响应函数,响应窗口的WM_DESTROY消息,当一个窗口将被销毁时,发送此消息3.OnNcDestroy()消息响应函数,响应窗口的WM_NCDESTROY消息,当一个窗口被销毁后发送此消息4.PostNcDestroy() 重载函数,作为处理OnNcDestroy()函数的最后动作,被CWnd调用MFC应用程序中打开模式对话框的函数调用顺序1.DoModal()重载函数,重载DoModal()成员函数2.PreSubclassWindow()重载函数,允许首先子分类一个窗口3.OnCreate()消息响应函数,响应WM_CREATE消息,发送此消息以告诉一个窗口已经被创建4.OnSize()消息响应函数,响应WM_SIZE消息,发送此消息以告诉窗口大小发生变化5.OnMove()消息响应函数,响应WM_MOVE消息,发送此消息,以告诉窗口正在移动6.OnSetFont()消息响应函数,响应WM_SETFONT消息,发送此消息,以允许改变对话框中控件的字体7.OnInitDialog()消息响应函数,响应WM_INITDIALOG消息,发送此消息以允许初始化对话框中的控件,或者是创建新控件8.OnShowWindow()消息响应函数,响应WM_SHOWWINDOW消息,该函数被ShowWindow()函数调用9.OnCtlColor()消息响应函数,响应WM_CTLCOLOR消息,被父窗口发送已改变对话框或对话框上面控件的颜色10. OnChildNotify()重载函数,作为WM_CTLCOLOR消息的结果发送MFC应用程序中关闭模式对话框的顺序1.OnClose()消息响应函数,响应WM_CLOSE消息,当"关闭"按钮被单击的时候,该函数被调用2.OnKillFocus()消息响应函数,响应WM_KILLFOCUS消息,当一个窗口即将失去键盘输入焦点以前被发送3.OnDestroy()消息响应函数,响应WM_DESTROY消息,当一个窗口即将被销毁时,被发送4.OnNcDestroy()消息响应函数,响应WM_NCDESTROY消息,当一个窗口被销毁以后被发送5.PostNcDestroy() 重载函数,作为处理OnNcDestroy()函数的最后动作被CWnd调用打开无模式对话框的顺序1.PreSubclassWindow()重载函数,允许用户首先子分类一个窗口2.OnCreate()消息响应函数,响应WM_CREATE消息,发送此消息以告诉一个窗口已经被创建3.OnSize()消息响应函数,响应WM_SIZE消息,发送此消息以告诉窗口大小发生变化4.OnMove()消息响应函数,响应WM_MOVE消息,发送此消息以告诉窗口正在移动5.OnSetFont()消息响应函数,响应WM_SETFONT消息,发送此消息以允许改变对话框中控件的字体。

mfc入门讲义

mfc入门讲义
属性’对话框,在‘标明’编辑框中输入该菜单 项的显示名称。
(3)在生成工程时,已生成了‘IDD_STU1_DIALOG’对话框 类。把该菜单加入到该对话框类:
在‘ResourceView’选项卡中,执行“双击 ‘IDD_STU1_DIALOG ’对话框标识符”,在‘编辑’窗体可 见该对话框轮廓图,执行“右击该对话框轮廓图空白处|属性”, 弹出‘对话 属性’对话框,在‘常规’选项卡中‘菜单’下拉 列表框上选择‘IDR_MENU1’。 (4)执行IDE菜单命令“组建|执行”,可见本工程应用程序的 运行窗体上显示该菜单。
在‘ResourceView’选项卡中,执行“双击 ‘IDD_DIALOG1’对话框标识符”,在‘编辑’窗体可见该对 话框轮廓图,执行“双击该对话框轮廓图空白处”,弹出 ‘Adding a class’对话框;按‘OK’按钮,弹出‘New Class’对 话框,在‘name’编辑框中输入新类名为‘newdlg1’,按‘ok’按 钮;在出现的‘MFC ClassWizard ’对话框中按‘确定’按钮。
2.处理菜单消息
当点击菜单项时会产生消息,该消息会传递到菜单所在窗口,
如果该窗口类设置接受和处理该消息的函数,窗口对象会查到 该类对象对该消息的处理函数。 (1)菜单项标识符(ID)的查找
在IDE ‘工作空间’ 窗体的‘ResourceView’选项卡中, Menu资源下可见一个ID (标识符)为IDR_MENU1的菜单资源。 双击该ID,在IDE工作区会显示该菜单的框架,双击菜单项会 弹出‘菜单项目 属性’对话框,在该对话框中可知道该菜单项 ID。 (2)建立接受菜单项消息的类和消息处理函数
//dxdlg1的窗体
(3)无模式对话框的窗体删除 对话框类对象有一个删除对话框成员函数: virtual BOOL DestroyWindow( ); 例如: dxdlg1. DestroyWindow( ); //删除对话框对象的窗体
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

MFC程序的启动过程与相关函数执行顺序原文地址:/chuntian1919/blog/item/f5b7f5fd898e2c1408244d3c.html了解MFC程序的启动过程,对于初学者来讲,了学习MFC很有帮助;对于不常用VC 的人来说,过一段时间就会忘记。

还是来记下来,方便以后查阅。

1、创建Application object对象theApp程序一开始生产一个(且只有一个)Application object对象theApp,也即一个CWinApp 对象,这个全局对象一产生,便执行其构造函数,因为并没有定义CMyWinApp构造函数,所以即执行CWinApp类的构造函数。

该函数定义于APPCORE.CPP第75行,你可以自己搜出来啃一啃,因此,CWinApp之中的成员变量将因为theApp这个全局对象的诞生而获得配置与初值。

2、WinMain登场用SDK编程序时,程序的入口点是WinMain函数,而在MFC程序里我们并没有看到WinMain函数,哦!~ 原来她是被隐藏在MFC代码里面了。

当theApp配置完成后,WinMain 登场,慢!细看程序,并没连到WinMain函数的代码啊!这个我也不知道,MFC早已准备好并由链接器直接加到应用程序代码中了,原来她在APPMODUL.CPP里面,好,我们就认为当theApp配置完成后,程序就转到APPMODUL.CPP来了。

那执行什么呢?看看下面从APPMODUL.CPP摘出来的代码:extern "C" int WINAPI_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){// call shared/exported WinMainreturn AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);}_tWinMain函数的“_t”是为了支持Unicode而准备的一个宏。

_tWinMain函数返回值是AfxWinMain函数的返回值,AfxWinMain函数定义于WINMAIN.CPP第21行,稍加整理,去芜存菁,就可以看到这个“程序进入点”主要做些什么事:int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){int nReturnCode = -1;CWinApp* pApp = AfxGetApp();AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow);pApp->InitApplication();pApp->InitInstance()nReturnCode = pApp->Run();AfxWinTerm();return nReturnCode;}AfxGetApp()函数是取得CMyWinApp对象指针,故上面函数第6至8行相当于调用:CMyWinApp::InitApplication();CMyWinApp::InitInstance()CMyWinApp::Run();因而导致调用:CWinApp::InitApplication(); //因为CMyWinApp 并没有改写InitApplicationCMyWinApp::InitInstance() //因为CMyWinApp 改写了InitInstanceCWinApp::Run(); //因为CMyWinApp 并没有改写Run用过SDK写程序的朋友,现在可能会发出会心的微笑。

3、AfxWinInit——AFX内部初始化操作AfxWinInit是继CWinApp构造函数之后的第一个操作,主要做的是AFX内部初始化操作,该函数定义于APPINIT.CPP第24行,这里就不掏出来了,你自己搜出来啃吧!4、执行CWinApp::InitApplicationAfxWinInit之后的操作是pApp->InitApplication,我们已知道pApp指向CMyWinApp 对象,当调用:pApp->InitApplication();相当于调用:CMyWinApp::InitApplication();但是你要知道,CMyWinApp继承自CWinApp,而InitApplication又是CWinApp的一个虚拟函数,我们并没有改写它(大部分情况下不需改写它),所以上述操作相当于调用:CWinApp::InitApplication();此函数定义于APPCORE.CPP第125行,你自己搜出来看吧!我就不搬出来了,里面的操作都是MFC为了内部管理而做的(其实我也看不懂,知道有这回事就好了)。

5、执行CWinApp::InitInstance继InitApplication函数之后,AfxWinMain调用pApp->InitInstance。

当程序调用:pApp->InitInstance();相当于调用:CMyWinApp::InitInstance();但是你要知道,CMyWinApp继承自CWinApp,而InitInstance又是CWinApp的一个虚拟函数。

由于我们改写了它,所以上述操作就是调用我们自己(CMyWinApp)的这个InitInstance函数。

6、CFrameWnd::Create产生主窗口(并先注册窗口类)现在已经来到CWinApp::InitInstance了,该函数先new一个CMyFrameWnd对象,从而产生主窗口。

在创建CMyFrameWnd对之前,要先执行构造函数CMyFrameWnd::CMyFrameWnd(),该函数用Create函数产生窗口:CMyFrameWnd::CMyFrameWnd(){Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectDefault, NULL, "MainMenu");}其中Create是CFrameWnd的成员函数,它将产生一个窗口,用过SDK编程序的朋友都知道,要创建主窗口时要先注册一个窗口类,规定窗口的属性等,但,这里使用哪一个窗口类呢?Create函数第一个参数(其它参数请参考MSDN或《深出浅出MFC》详解)指定窗口类设为NULL又是什么意思啊?意思是要以MFC内建的空中类产生一个标准的外框窗口,但,我们的程序一般都没有注册任何窗口类呀!噢,Create函数在产生窗口之前会引发窗口类的注册操作。

让我们先挖出Create函数都做了些什么操作,Create函数定义于WINFRM.CPP的第538行(在此我就不把代码Copy过来了,你自己打开出来看吧),函数在562行调用CreateEx 函数,由于CreateEx是CWnd的成员函数,而CFrameWnd是从CWnd继而来,故将调用CWnd::CreateEx。

此函数定义于WINCORE.CPP第665行,下面是部分代码: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 parametersCREATESTRUCT cs;cs.dwExStyle = dwExStyle;cs.lpszClass = lpszClassName;cs.lpszName = lpszWindowName;cs.style = dwStyle;cs.x = x;cs.y = y;cs.cx = nWidth;cs.cy = nHeight;cs.hwndParent = hWndParent;cs.hMenu = nIDorHMenu;cs.hInstance = AfxGetInstanceHandle();cs.lpCreateParams = lpParam;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);...}用过SDK编程序的朋友,看到上面代码应该有一点感觉了吧,函数中调用的PreCreateWindows是虚拟函数,在CWnd和CFrameWnd之中都有定义。

由于this指针所指对象的缘故,这里应该调用的是CFrameWnd::PreCreateWindow。

该函数定义于WINFRM.CPP第521行,以下是部分代码:BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs){if (cs.lpszClass == NULL){VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background }...}其中AfxDeferRegisterClass是一个定义于AFXIMPL.H中的宏。

该宏如下:#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass) 注:这里有宏和《深入浅出MFC》的不一样,以上代码是从Visual C++ 6.0摘取。

AfxEndDeferRegisterClass定义于WINCORE.CPP第3619行,该函数很复杂,主要是注册五个窗口类(哇!终于看到窗口类了,怎么用5个呢?我还不清楚),不同类的PreCreateWindow成员函数都是在窗口产生之前一刻被调用,准备用来注册窗口类。

相关文档
最新文档