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程序的运行过程
// call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); }
(WinMain 函数实现:E:Program FilesMicrosoft Visual StudioVC98MFCSRC 下的 APPMODUL.CPP 文件中) 4.在 WinMain 函数中,实际上是通过调用 AfxWinMain 函数来完成其功能的
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTestDoc),
RUNTIME_CLASS(CMainFrame),
// main SDI frame window
RUNTIME_CLASS(CTestView));
// such as the name of your company or organization. SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(); // Load standard INI file options (including MRU)
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程序基本运行机制
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使用手册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程序中消息以及函数的处理顺序简介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 控件顺序?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的人都会被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.程序启动
程序启动时,首先会调用WinMain函数。
WinMain函数是MFC程序的入口函数,负责程序的初始化和运行。
2.程序初始化
在WinMain函数中,会调用CWinApp::InitInstance()函数进行程序的初始化。
CWinApp::InitInstance()函数负责注册窗口类、创建应用程序对象、创建窗口等工作。
3.窗口创建
在程序初始化完成后,会创建应用程序的窗口。
应用程序窗口是应用程序的入口,用户可以通过应用程序窗口与应用程序进行交互。
4.消息循环
在窗口创建完成后,会进入消息循环。
消息循环是MFC程序的核心,负责处理来自操作系统的消息。
5.程序退出
用户关闭应用程序时,会调用CWinApp::ExitInstance()函数退出程序。
CWinApp::ExitInstance()函数负责释放程序使用的资源。
第三章 MFC程序的工作流程和结构
杭州电子科技大学通信工程学院
3.2学习MFC的方法
unsigned long
unsigned long long long const char * char * void * long unsigned int unsigned short unsigned int
说明
布尔值 32位字符指针 8位无符号整数
用作颜色值的32位值
32位无符号整数,段地址和相关的偏移地址 32位带符号整数 作为参数传递给窗口过程或回调函数的32位值 指向字符串常量的32位指针 指向字符串的32位指针 指向未定义类型的32位指针 来自窗口过程或回调函数的32位返回值 32位无符号整数 16位无符号整数 当作参数传递给窗口过程或回调函数的32位值
首先要对Windows API有一定的了解,否则无法深 入学习MFC。至少要知道Windows对程序员来说 意味着什么,它能完成什么工作,它的一些常用数 据结构等。 其次,不要过分依赖于Wizards。Wizards能做许多 工作,但同时掩饰了太多的细节。应当看看 AppWizard和ClassWizard为你所做的工作。除非 你理解了生成的代码的含义,否则无法了解程序是 如何运行的。
MFC程序的 工作流程和结构
杭州电子科技大学通信工程学院
本章内容
•3.1 1Windows编程 •3.2学习MFC的方法 •3.3 MFC的应用程序框架 •3.4 ClassWizard •绍
mfc框架的基本运行原理
mfc框架的基本运行原理
MFC(Microsoft Foundation Class)是一个基于Windows操作
系统的GUI(图形用户界面)开发工具集,它构建在Win32 API上,提供了许多用于Windows应用程序开发的类和函数。
MFC框架的基本运行原理可以概括为以下几个步骤:
1. 应用程序启动时,会创建一个主窗口对象,并将其显示在屏幕上。
2. 主窗口对象包含一个消息循环,用于响应用户的输入和操作,并调用相应的处理函数来处理这些消息。
3. 当用户对某个控件(如按钮、菜单、文本框等)进行操作时,该控件会生成一个事件(事件通常由Windows系统内部生成),该事件将被传递到主窗口对象,由主窗口对象的消息循环接收并传递给相应的处理函数处理。
4. 处理函数根据事件的类型和参数来改变应用程序的状态或修改相关控件的属性,然后更新主窗口或其他相关窗口的显示内容。
5. 当用户关闭应用程序时,主窗口对象会收到一条关闭消息,然后销毁所有相关窗口和资源,最终结束应用程序的运行。
总的来说,MFC框架的基本运行原理就是通过消息循环和事
件处理机制来处理用户的输入和操作,从而实现应用程序的界面交互和业务逻辑。
mfc 控件顺序 -回复
mfc 控件顺序-回复关于MFC(Microsoft Foundation Class)控件顺序的话题,我将一步一步回答并解释相关的概念和使用方法。
MFC是微软公司提供的一种用于开发Windows应用程序的框架。
它使用C++语言编写,提供了一系列强大的类和方法,用于创建用户界面和处理用户交互。
在MFC中,控件是用户界面的基本构建块,用于显示和接收用户输入。
控件顺序指的是控件在界面上的布局顺序,即用户按下Tab键时,焦点将依次转移到下一个控件。
要实现控件顺序,我们需要以下步骤:1. 创建一个对话框或窗口类:MFC应用程序通常由对话框或窗口组成。
对话框是一个独立的窗口,它包含了一组控件,用于与用户进行交互。
窗口是一个包含在框架窗口中的独立区域,可以包含子控件。
2. 在对话框或窗口中添加控件:使用MFC提供的资源编辑器,我们可以很方便地在对话框或窗口中添加控件。
选择合适的控件类型,如按钮、文本框、复选框等,并将其拖放到对话框或窗口上。
3. 设置控件的tab顺序:默认情况下,MFC将控件的tab顺序设置为它们在对话框资源中的添加顺序。
但如果我们想自定义tab顺序,可以按照以下步骤操作:a. 打开对话框或窗口资源,选择要设置tab顺序的控件。
b. 在属性框中找到“TabStop”属性,并将其设置为TRUE。
这将允许该控件参与tab顺序切换。
c. 在属性框中找到“ID”属性,将其设置为唯一的非零值。
这将确定控件的tab顺序。
4. 处理tab键消息:在MFC应用程序中,如果我们想要自定义tab键的行为,可以处理WM_NEXTDLGCTL消息。
这个消息在用户按下tab键时会被发送到当前具有键盘焦点的窗口。
通过处理这个消息,我们可以指定下一个具有焦点的控件。
a. 在对话框、窗口或控件的消息映射中添加一个处理WM_NEXTDLGCTL消息的函数。
b. 在这个函数中,使用CWnd类的NextDlgCtrl函数获取下一个具有焦点的控件的句柄,并使用SetFocus函数将焦点设置在该控件上。
mfc 控件顺序 -回复
mfc 控件顺序-回复MFCTest组件的顺序,指的是在进行MFC应用程序开发时,组件的创建和初始化顺序。
正确的组件顺序对于应用程序的正常运行至关重要。
下面我将一步一步回答关于MFC控件顺序的问题。
1. 了解MFC控件首先,了解MFC控件是至关重要的。
MFC(Microsoft Foundation Classes),是微软开发的一种用于开发Windows应用程序的库。
MFC框架提供了很多控件,例如按钮、文本框、列表框等,开发人员可以使用这些控件创建用户界面。
2. 了解控件创建的过程在进行MFC应用程序开发时,控件的创建是一个重要的步骤。
控件的创建包括两个主要的过程,即资源文件的设计和控件的初始化。
通过资源文件可以进行控件的布局设计,而控件的初始化包括控件的创建和控件属性的设置。
3. 控件的创建顺序控件的创建顺序对于应用程序的运行至关重要。
通常,控件的创建顺序应该从上到下,从左到右进行。
这是因为在应用程序的布局设计中,通常会按照这个顺序来进行控件的排列。
4. 控件管理在MFC应用程序中,控件的管理是一个关键的任务。
通常,开发人员可以使用一种叫做控件变量的方式对控件进行管理。
控件变量是一个指向控件的指针,在程序中可以使用控件变量来对控件进行操作。
5. 控件的初始化顺序在进行控件的初始化时,应该按照控件的创建顺序进行。
这意味着先初始化上方的控件,再初始化下方的控件,先初始化左边的控件,再初始化右边的控件。
这样可以确保控件的正确创建和初始化。
6. 对控件属性的设置在控件的初始化过程中,可以对控件的属性进行设置。
通常,可以设置控件的大小、位置、字体、颜色等属性。
根据实际需求,开发人员可以根据控件的类型进行不同的设置。
7. 控件事件处理在应用程序中,控件的事件处理是一个重要的部分。
MFC框架提供了很多事件处理机制,例如按钮的点击事件、文本框的变化事件等。
开发人员可以通过重写相应的函数来进行事件的处理。
8. 控件之间的交互在应用程序中,控件之间的交互是一个常见的需求。
MFC操作步骤
第一步:建MFC工程第二步:resource.h里填加#define ID_tian 32771第三步:~view.h 里PublicBOOL t; //如果左击鼠标,t为true,否则为fasleint n; //代表定点的个数CPoint p[100]; //定义点的对象数组(数据成员为点的x,y坐标)void boundaryfill4(int x,int y ,int FilledColor,int BoundaryColor); //实现种子四连通算法(这是填充算法中的一种)pretectedafx_msg void OnLButtonDown(UINT nFlags,CPoint point );afx_msg void OnRButtonDown(UINT nFlags,CPoint point );afx_msg void Ontian();第四步:~view.cpp在BEGIN_MESSAGE_MAP(CMyView, CView)下定义:ON_WM_LBUTTONDOWN()ON_WM_RBUTTONDOWN()ON_COMMAND(ID_tian, Ontian)ON_WM_CREATE()1、构造函数n=0;t=TRUE;2、修改成员函数OnDraw()pDC->TextOut(1,65," 先用左击画线,右击用于区域闭合");pDC->TextOut(1,88,"区域闭合后,点击菜单栏中的'填'!!");3、定义消息函数和成员函数#include <windows.h> // include all the windows headers#include <windowsx.h> // include useful macros#include <stdio.h>#include <stdlib.h>//#include"window.h"void CMyView::boundaryfill4(int x,int y ,int FilledColor,int BoundaryColor){}void CMyView::OnLButtonDown(UINT nFlags,CPoint point ){}}void CMyView::OnRButtonDown(UINT nFlags,CPoint point ){}void CMyView::Ontian(){ t=FALSE;MessageBox("请单击选取种子点") ;}。
MFC内部运行来龙去脉追踪
MFC内部运行来龙去脉追踪1.全局对象theApp先于WinMain函数构造,而theApp是一个派生类的对象,故先调用基类CWinApp的构造函数,再调用派生类对象的构造函数。
CWinApp的构造函数定义于APPCORE.CPP文件中CWinApp::CWinApp(LPCTSTR lpszAppName){if (lpszAppName != NULL)m_pszAppName = _tcsdup(lpszAppName);elsem_pszAppName = NULL;// initialize CWinThread stateAFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread; ASSERT(AfxGetThread() == NULL);pThreadState->m_pCurrentWinThread = this;ASSERT(AfxGetThread() == this);m_hThread = ::GetCurrentThread();m_nThreadID = ::GetCurrentThreadId();// initialize CWinApp stateASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please pModuleState->m_pCurrentWinApp = this;ASSERT(AfxGetApp() == this);// in non-running state until WinMainm_hInstance = NULL;m_pszHelpFilePath = NULL;m_pszProfileName = NULL;m_pszRegistryKey = NULL;m_pszExeName = NULL;m_pRecentFileList = NULL;m_pDocManager = NULL;m_atomApp = m_atomSystemTopic = NULL;m_lpCmdLine = NULL;m_pCmdInfo = NULL;// initialize wait cursor statem_nWaitCursorCount = 0;m_hcurWaitCursorRestore = NULL;// initialize current printer statem_hDevMode = NULL;m_hDevNames = NULL;m_nNumPreviewPages = 0; // not specified (defaults to 1)// initialize DAO statem_lpfnDaoTerm = NULL; // will be set if AfxDaoInit called// other initializationm_bHelpMode = FALSE;m_nSafetyPoolSize = 512; // default size}CWinApp构造函数主要完成this指针的赋值,将全局对象theApp的this指针赋值给全局唯一实例。
mfc项目执行流程
mfc项目执行流程MFC(Microsoft Foundation Class)是一个C++库,用于创建Windows桌面应用程序。
MFC项目的执行流程通常遵循以下一般步骤:1. 创建MFC应用程序项目:使用Visual Studio或其他适用的开发环境创建一个MFC应用程序项目。
在创建项目时,您可以选择项目类型(如单文档、多文档、对话框等)和其他项目属性。
2. 初始化应用程序:MFC应用程序的入口点通常是_tWinMain 函数。
在此函数中,您可以执行应用程序级别的初始化工作,例如创建主窗口对象、初始化MFC框架等。
3. 创建主窗口:通常,MFC应用程序会创建一个主窗口,这是应用程序的主要用户界面。
主窗口通常是派生自CFrameWnd或CDialog的窗口类,具有菜单、工具栏、状态栏等。
4. 消息循环:MFC应用程序通过消息循环来处理用户输入和操作系统事件。
消息循环是一个无限循环,等待用户输入、消息和事件,然后分派它们到相应的窗口和控件。
5. 响应事件和消息:在主窗口、对话框和其他控件中,您可以处理并响应用户操作和事件,例如按钮点击、菜单项选择、窗口关闭等。
这通常涉及到处理MFC消息处理函数,如OnCommand、OnPaint 等。
6. 窗口绘图:如果应用程序需要绘制图形、文本或其他内容,您可以重写OnPaint消息处理函数,然后在其中进行绘图操作。
7. 资源管理:MFC应用程序通常使用资源文件(如对话框资源、位图、图标等)来定义界面元素和图形资源。
您可以使用Visual Studio的资源编辑器管理这些资源。
8. 保存和加载数据:如果应用程序需要保存和加载数据,您可以实现相关的数据持久性功能,如将数据保存到文件、数据库或其他存储介质。
9. 编译和构建:完成代码编写后,您需要编译和构建MFC应用程序,以生成可执行文件(.exe)。
10. 测试和调试:对应用程序进行测试和调试,确保其正常运行,以处理潜在的错误和异常情况。
MFC程序运行机理
MFC程序的构造过程和运行机理初探我们先看一个例子:打开VC6.0,依次点击:文件(File)->新建(New)->工程(Project)->MFC AppWizard(exe)之后在右边输入路径和工程名称,这里暂定为:Test单击确定(OK)按钮进入下一页面,选择单文本(Single Document),然后点击完成。
好了,一个基于MFC的应用程序框架已经完成。
现在我们来编译看看:Ctrl+F5看到了效果图没?看到了对不?好了,下面我们一起来看看这个我们没有添加一行代码的MFC程序。
看到左边的资源管理框,选择“ClassView”标签,可以看到下面几个类:CAboutDlg,CMainFrame,CTestApp,CTestDoc,CTestView和一个全局变量:theApp我们就从这个全局变量说起。
看看这个MFC程序的执行过程。
我们知道创建一个完整的窗口需要经过下面四个操作步骤:1.设计一个窗口类;2.注册窗口类;3.创建窗口;4.显示及更新窗口。
1.设计一个窗口类我们知道全局对象的构造函数会在main 函数之前执行,那么这个全局类对象:theApp再main函数执行前就已经分配好了内存空间,由其定义class CTestApp : public CWinApp{....}可知,该全局类继承自CWinApp,那么可知在该对象创建的时候,CWinApp的构造函数会被调用。
之后,系统进入main函数,在MFC程序中,main函数是_tWinMain 函数,可以看看_tWinMain 的定义会发现,其实_tWinMain 就是WinMain。
_tWinMain 函数在Microsoft Visual Studio\VC98\MFC\SRC\APPMODUL.CPPextern "C" int WINAPI_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow){// call shared/exported WinMainreturn AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);}其实里面就一行代码,又调用了AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow) 函数,AfxWinMain 函数在Microsoft Visual Studio\VC98\MFC\SRC\WINMAIN.CPP 文件中在AfxWinMain 函数里,先声明了一个CWinThread 类对象pThreadCWinThread* pThread = AfxGetThread();然后调用pThread->InitInstance() 函数,这个函数很重要,我们看看它的定义:在CWinThread类的头文件AFXWIN.H 中,可以发现如下代码,virtual BOOL InitInstance();这说明InitInstance() 函数是个虚函数,这里我们可以看看继承关系:class CTestApp : public CWinApp{....}class CWinApp : public CWinThread{....}这样我们就可以明白CTestApp其实继承自CWinThread,好的,明白这一点后,我们再看看CWinApp的构造函数:CWinApp::CWinApp(LPCTSTR lpszAppName){.....pThreadState->m_pCurrentWinThread = this;.....}这里我们看到了上面的一行代码,这里的这个this指针到底指向谁呢?根据虚拟函数的特性和继承性原理我们知道它指向的是CWinApp的派生类CTestApp的对象,至此我们明白在AfxWinMain 函数里,CWinThread* pThread = AfxGetThread();CWinApp* pApp = AfxGetApp();表明pApp、pThread 实际指向的都是CTestApp 类对象,那么在后面的pThread->InitInstance() 函数实际调用的是CTestApp 类的成员函数InitInstance() 。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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针对不同功能的窗口使用了哪些窗口类。