尽管刚接触MFC不久,但其开发模式已初有感受,抛开复杂的应用不谈,想想我们通常怎样来写一个简单的MFC程序。也许浮现在你脑海里的是程序向导,类向导,资源编辑器,以及程序代码,此时你大概会灵光一现,说MFC程序=向导+资源+代码。看起来确实是这样,但有没有可能更简化一些呢,比如把向导去掉。想想是可以的,向导不过是简化MFC开发的一种手段,虽然没有类向导日子会很难过,但也使你有机会看看纯手工打造的MFC是怎么样的,这对于了解MFC的执行流程非常有帮助。

我试图从一个最简单的MFC程序开始,慢慢丰富它,使它最终成为一个有点用处的程序。这个过程中我会尽力抵挡住使用类向导的诱惑,只使用资源以及程序代码。当然可能需要好几篇文章的篇幅,因为这个程序是我计划好的,用来学习MFC的每一个技术点的实验品。现在,它的另一个目的是证明:MFC程序=资源+代码。

一个最简单的MFC程序

你一定有这样的经验,用MFC的程序向导生成的MFC代码满是宏,注释,条件定义,这些对于程序的健壮性很有必要,不过对于初学者却是可怕的怪兽。

其实MFC程序可以写得非常简单,只用一个头文件和一个源文件就可以了,用程序向导新建一个程序,选择Win32 Application类型的程序,我的工程名是:MiniDraw;在下一步选择“一个空工程”并完成掉它。

生成的工程仅仅是一个工作区,没有任何源文件,手工给它添加一个头文件和一个源文件,分别是:DrawApp.h; DrawApp.cpp。这是它们的代码:

DrawApp.h:

#ifndef LINZHENQUN_DRAWAPP_H_

#define LINZHENQUN_DRAWAPP_H_

class CDrawApp: public CWinApp

{

public:

CDrawApp();

BOOL InitInstance();

};

#endif //LINZHENQUN_DRAWAPP_H_

DrawApp.cpp:

#include <afxwin.h>

#include "DrawApp.h"

CDrawApp DrawApp;

CDrawApp::CDrawApp()

{

}

BOOL CDrawApp::InitInstance()

{

return FALSE;

}

不管你信不信,这就是一个最简单的MFC程序,尽管它什么事情也做不了。在编译的时候会出现错误,这是因为没有添加MFC共享DLL,打开工程设置,在常规页将MFC下拉框选为“使用MFC作为共享DLL”。然后再编译看看,运行后它马上就返回了,我们得在InitInstance里面作点什么。

BOOL CDrawApp::InitInstance()

{

MessageBox(0, "Hello world", "", MB_OK);

return FALSE;

}

MFC版的Hello World完成了,可能你还觉得过于简陋,如果是这样的话,给程序加一个对话框怎么样呢。

对话框的界面通过资源来加,在新建向导的文件页里选“资源脚本”,输入文件名为resource,确定后便生成了resource.rc,并在IDE里可以见到它:

在resource.rc处点击右键菜单,选插入,在插入资源对话框里选Dialog,点新建后,一个对话框模板就生成了。

享受一下快速开发的感觉吧,接下来要将这个对话框资源与一个对话框类关联起来,使用类向导的话会非常简单,不过为了体现纯手工的意义,我决定还是用新建文件的方式。

新建AboutDialog.cpp和AboutDialog.h,代码如下:

AboutDialog.h

#ifndef LINZHENQUN_ABOUTDIALOG_H_

#define LINZHENQUN_ABOUTDIALOG_H_

class CAboutDialog: public CDialog

{

public:

CAboutDialog(CWnd* pParent = NULL);

protected:

virtual OnInitDialog();

DECLARE_MESSAGE_MAP();

};

#endif //LINZHENQUN_ABOUTDIALOG_H_

AboutDialog.cpp

#include <afxwin.h>

#include "AboutDialog.h"

#include "resource.h"

BEGIN_MESSAGE_MAP(CAboutDialog, CDialog)

END_MESSAGE_MAP()

CAboutDialog::CAboutDialog( CWnd* pParent /*== NULL*/ ):

CDialog(IDD_ABOUTDLG, pParent)

{

}

BOOL CAboutDialog::OnInitDialog()

{

return CDialog::OnInitDialog();

}

对话框资源的ID是IDD_ABOUTDLG,在resource.h里面声明,所以将这个头文件加进来,这个资源ID传给基类CDialog后,它会帮你处理对话框加载的事情,在上一篇文章提及过。

现在,回到DrawApp,将InitInstance改成这样:

BOOL CDrawApp::InitInstance()

{

CAboutDialog AboutDlg;

AboutDlg.DoModal();

return FALSE;

}

运行程序如下:

看看我们写的代码,总共只有4个文件,并且代码非常简单,学过SDK编程的你可能看出WinMain被CDrawApp::InitInstance()代替了,整个程序流程可以从这里开始,但是那些曾经熟悉的东西却不见了,比如WinMain呢,消息循环呢,毕竟好奇是人类的天性,而要发现答案,必须到框架里去看看。

这一切是怎样发生的

MFC与VCL有一个很大的区别,VCL刚开始用时觉得非常简单,你不需要理解SDK那一套东西,当你想一探究竟时,才发觉那里面的水很深;MFC则相反,一开始你会觉得摸不着头脑,这迫使你必须了解一点SDK的知识,当你理解了程序向导为你生成的这一堆代码之后,你会发现AFX的东西也变得一目了然。

程序的初始流程也是这样,CDrawApp声明了一个全局的类实例,它必须是一个单例,因为它代表着这个程序。而我们直接认为,在某个源文件里有一个WinMain函数,这个函数取得CDrawApp的类实例,然后调用CDrawApp::InitInstance(),然后调用CDrawApp::Run();

就象下面这样:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPTSTR lpCmdLine, int nCmdShow)

{

int nReturnCode = -1;

CWinApp* pApp = AfxGetApp();

If (pApp->InitInstance())

nReturnCode = pApp->Run();

return nReturnCode;

}

实际的MFC代码与上面并没有相差太远,也许你又找回C++程序的那种顺序了。

当然作为一个框架,要考虑的东西远比上面的多,比如线程的信息,模块的信息,如何保存App单例等,实际的代码可以参考WINMAIN.CPP的AfxWinMain函数。

AfxGetApp()取回一个App指针,这个指针就是上面代码定义的DrawApp,CWinApp的构造函数将This指针存放在“全局的地方”,使得用AfxWinApp可以拿到。

我们的InitInstance()返回的是FALSE,因而Run不会执行到,直接就返回了,那么对话框的消息处理是怎么做到的呢,答案在上一篇文章中,就是对话框自己有一个消息循环叫RunModalLoop。

结合MFC实际的代码,概括起来就是下面几个点:

1.         生成CDrawApp类实例,在构造函数中将This保存起来,让AfxGetApp可以拿到。

2.         WinMain开始,拿到App类,初始化程序pApp->InitApplication();

3.         初始化实例pThread->InitInstance(),pThread等于pApp。

4.         开始消息循环pThread->Run()。

5.         WinMain返回,程序结束。

3、4步是整个程序的生命周期,InitInstance是创建窗口,Run是消息循环。用窗口表现界面,以事件驱动程序的模型就这样形成了。

上面所列出来的是经过简化的代码,我认为这也有好处,太关注分枝别叶只会让你头晕目眩,把这些东西摘除,只剩下干干净净的支杆,整个骨架就清清楚楚了,等到实际项目应用的时候,再慢慢丰富这些知识,这种由简到繁的学习方法一直为我所坚持。

MFC-最简单的MFC程序相关推荐

  1. MFC一个简单的计算器程序

    1,简介 某个晚上帮人做的一个MFC课程设计的作业.大概花了两三个小时. (2017-6-6: 抱歉很多人反馈下载链接失效,原因是我的百度网盘之前被人恶意登录清空了所有资源.已重写工程上传,但由于目前 ...

  2. 【MFC】一个最简单的MFC程序(9)

    了解完MFC程序的流程后,会有 "果然不需要了解这些东西,直接用就可以了" 的感觉.这应该是MFC的初衷吧--按照框架来,集中精力做应用.但是没有了解呢? 最简单的MFC程序 步骤 ...

  3. 使用visual studio 2019 创建简单的MFC窗口「使用C++」

    ```cpp 使用visual studio 2019 创建过程请参考Bili的上一篇文章⬇⬇ →!使用visual studio 2019 创建简单的MFC窗口「使用底层的C语言」 划重点:项目-& ...

  4. 基于MFC的桌面时钟应用程序

    前言: 其实在做这个应用程序之前是已经接触过MFC,之前的对于MFC的应用只是绘制了简单的图形界面用于承载核心的局域网聊天的程序的界面显示而已,主体部分在于核心的局域网聊天的实现. 但是这次对于MFC ...

  5. VC2012/VS2012 MFC串口通讯上位机程序教程笔记(转)

    使用MFC来编写串口程序,需要有一定的c++语言功底,要清楚MFC代码的组织方式. 鉴于绝大多数的教程还停留在vc6.0这个骨灰级的环境,特在此说明一下VC2012下的代码组织方式,和大家一起交流下~ ...

  6. C++之MFC制作简单计算器(VS2019实现),附带完整代码

    资源下载 代码下载 代码失效可以联系本人: 15377920718 效果演示 MFC制作简单的计算器(VS2019实现) VS2019可以用于制作简单的计算器,用的是MFC,通过设立button以及编 ...

  7. 用MFC制作一个倒计时小程序

    用MFC制作一个倒计时小程序 1.思路: 1)初始步骤1:新建一个工程,选择MFC AppWizard(exe),工程名命名为CdTimer,选择基于对话框形式的应用程序,将此主对话框用于显示剩余的时 ...

  8. 【Visual Studio 2019】创建 MFC 桌面程序 ( 安装 MFC 开发组件 | 创建 MFC 应用 | MFC 应用窗口编辑 | 为按钮添加点击事件 | 修改按钮文字 | 打开应用 )

    文章目录 一.安装 MFC 开发组件 二.创建 MFC 应用 三.MFC 应用窗口编辑 四.为按钮添加点击事件 五.修改按钮文字 六.打开系统其它应用 七.博客源码 一.安装 MFC 开发组件 打开 ...

  9. VC++ MFC单文档应用程序SDI下调用glGenBuffersARB(1, pbo)方法编译通过但执行时出错原因分析及解决办法:glewInit()初始化的错误...

    1.问题症状 在VC++环境下,利用MFC单文档应用程序SDI下开发OpenGL程序,当调用glGenBuffersARB(1, &pbo)方法编译通过但执行时出错,出错代码如下: OpenG ...

最新文章

  1. TVM编译机器学习到 WASM 和 WebGPU
  2. android mvp简书,Android_MVP学习
  3. LogMiner学习笔记
  4. caffe学习笔记--跑个SampleCode
  5. 如何定制化SAP Fiori标准应用里UI字段的标签
  6. ant man 什么意思_浅谈为什么很多蓝牙模块厂家选择nRF52832?
  7. 泰晤士“中国学科评级”结果出炉,中国数学学科评级榜单公示!
  8. 服务器虚拟化的几种方式,服务器虚拟化究竟应当选择哪种方式?
  9. 2012年读书年度小结
  10. java-commons-pool2--(1)--连接池详解
  11. 300万数据导入导出优化方案,从80s优化到8s(实测)
  12. 加密解密和CA证书杂记
  13. 蚂蚁课堂 - springboot入门(非常详细)讲解人:(余胜军)
  14. 医院病历管理系统java版本二
  15. mb_detect_encoding php,php mb_detect_encoding检测字符串编码有误的问题
  16. 基于社交模型的权证交易概念产品-废话性前言
  17. 使用this调用已有的有参构造函数_加倍提升开发效率,继续深挖一下Lombok的使用
  18. Android实战开发-Kotlin教程(入门篇-RecyclerView数据列表的实现)
  19. 怎么听外国 播客_设计您想听的播客
  20. 2021年危险化学品生产单位安全生产管理人员考试题库及危险化学品生产单位安全生产管理人员模拟考试题

热门文章

  1. 【web前端面试宝典】经典10问(上篇)
  2. Python之数据分析(numpy裁剪、压缩、累乘,样本相关性曲线的绘制)
  3. SQL注入-常用函数和语句
  4. 干货 | 万字长文详解携程酒店订单缓存 存储系统升级实践
  5. 实测十款连锁店管理系统,专为纠结的连锁店老板打造!
  6. 猪齿鱼V2.1.0 发布 移动办公、知识在线协作, 项目管理快人一步
  7. Python基础知识学习(一)——Python语言概述、安装、运行、变量、数据类型概述
  8. matlab获取全局变量的值_MATLAB中搜索、查询和全局变量的用法(摘录)
  9. 写个rpc调用,试试自己了解多少
  10. SR研究(2)双三次插值法的图像退化