MFC程序的启动过程与相关函数的执行顺序
- 格式:doc
- 大小:41.00 KB
- 文档页数:8
很是空闲最近.转载一些东西吧..就当是复习...再不看看,就忘光了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程序流程程序的诞生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(Microsoft Foundation Class Library)是微软提供的一个类库,用于简化Windows应用程序的开发过程。
以下是MFC使用手册的简要介绍:1. 简介:MFC是一个基于C++的类库,它提供了许多用于构建Windows应用程序的类和函数。
通过使用MFC,开发人员可以快速地构建具有一致外观和感觉的应用程序,并利用Windows平台提供的各种功能。
2. 安装和配置:在开始使用MFC之前,您需要安装Microsoft Visual Studio并确保安装了MFC开发工作负载。
安装完成后,您需要创建一个新的MFC项目或打开一个现有的MFC项目。
3. 创建MFC应用程序:要创建一个新的MFC应用程序,您需要使用Microsoft Visual Studio的向导。
选择“File”菜单中的“New”选项,然后选择“Project”。
在弹出的对话框中,选择“MFC Application”并按照向导的提示完成应用程序的创建过程。
4. MFC类库:MFC提供了许多用于构建应用程序的类和函数。
以下是一些常用的MFC类:CWinApp:应用程序对象类,用于管理应用程序级别的操作,例如初始化应用程序和退出应用程序。
CWnd:窗口类,用于管理窗口的各种操作,例如创建窗口、处理消息和绘制窗口。
CDocument:文档类,用于管理应用程序中的文档数据。
CView:视图类,用于管理应用程序中的视图,例如显示文档数据和与用户交互。
5. MFC消息处理:MFC使用消息传递机制来处理用户与应用程序的交互。
每个窗口和控件都处理一组预定义的消息,例如鼠标点击、键盘输入和窗口大小改变等。
通过覆盖类中的虚函数,您可以定义应用程序如何响应这些消息。
6. 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 控件顺序?MFC(Microsoft Foundation Classes)是一个用于开发Windows 应用程序的C++ 类库。
MFC 控件顺序是指在MFC 应用程序中,控件的显示和响应焦点的顺序。
当在界面中有多个控件时,通过控件顺序可以确定用户在操作界面时,按Tab 键或者使用鼠标切换焦点的顺序。
为什么需要MFC 控件顺序?控件顺序在用户界面设计中起到了非常重要的作用。
通过合理设置控件顺序可以提高用户体验和效率,使得用户更加方便地在应用程序中进行操作。
同时,控件顺序也决定了用户在操作界面时焦点的切换,从而影响到用户的输入和交互流程。
如何设置MFC 控件顺序?设置MFC 控件顺序可以通过两种方式实现,一种是使用资源编辑器,另一种是通过代码设置。
使用资源编辑器设置MFC 控件顺序:1. 打开MFC 应用程序的资源文件(通常为 .rc 后缀)。
2. 在资源编辑器中找到对应的对话框资源,双击打开。
3. 确保在对话框资源的编辑模式下,点击工具栏中的"Tab Order" 按钮。
4. 在对话框中,按下Tab 键或使用鼠标点击每个控件,规定每个控件的顺序。
5. 完成设置后,点击工具栏中的"Tab Order" 按钮再次退出控件顺序编辑模式。
6. 保存资源文件并进行编译。
通过代码设置MFC 控件顺序:1. 打开MFC 应用程序的对话框类的源文件(通常以 .cpp 为后缀)。
2. 在对话框的构造函数中,使用`SetWindowPos()` 函数设置每个控件的Tab 键顺序。
例如,`SetWindowPos(IDC_BUTTON1, 0);` 表示将IDC_BUTTON1 设置为第一个控件。
3. 根据需要设置其他控件的顺序。
4. 保存并编译代码。
如何调整MFC 控件顺序?在MFC 应用程序中,可以根据需求调整控件的顺序。
使用资源编辑器调整MFC 控件顺序:1. 打开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程序的运行流程如下:
1.程序启动
程序启动时,首先会调用WinMain函数。
WinMain函数是MFC程序的入口函数,负责程序的初始化和运行。
2.程序初始化
在WinMain函数中,会调用CWinApp::InitInstance()函数进行程序的初始化。
CWinApp::InitInstance()函数负责注册窗口类、创建应用程序对象、创建窗口等工作。
3.窗口创建
在程序初始化完成后,会创建应用程序的窗口。
应用程序窗口是应用程序的入口,用户可以通过应用程序窗口与应用程序进行交互。
4.消息循环
在窗口创建完成后,会进入消息循环。
消息循环是MFC程序的核心,负责处理来自操作系统的消息。
5.程序退出
用户关闭应用程序时,会调用CWinApp::ExitInstance()函数退出程序。
CWinApp::ExitInstance()函数负责释放程序使用的资源。
MFC程序的启动过程与相关函数的执行顺序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 并没有改写 InitApplication CMyWinApp::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成员函数都是在窗口产生之前一刻被调用,准备用来注册窗口类。
如果我们指定的窗口类是NULL,那么就使用系统默认类。
从CWnd及其各个派生类的PreCreateWindow 成员函数可以看出,整个Framework针对不同功能的窗口使用了哪些窗口类。