`
isiqi
  • 浏览: 16485282 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

MFC-最简单的MFC程序

阅读更多

尽管刚接触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里可以见到它:

<shapetype id="_x0000_t75" path=" m@4@5 l@4@11@9@11@9@5 xe" stroked="f" filled="f" o:spt="75" o:preferrelative="t" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0 "></f><f eqn="sum @0 1 0 "></f><f eqn="sum 0 0 @1 "></f><f eqn="prod @2 1 2 "></f><f eqn="prod @3 21600 pixelWidth "></f><f eqn="prod @3 21600 pixelHeight "></f><f eqn="sum @0 0 1 "></f><f eqn="prod @6 1 2 "></f><f eqn="prod @7 21600 pixelWidth "></f><f eqn="sum @8 21600 0 "></f><f eqn="prod @7 21600 pixelHeight "></f><f eqn="sum @10 21600 0 "></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 414.75pt; HEIGHT: 329.25pt" coordsize="21600,21600" type="#_x0000_t75"><imagedata src="MFC%EF%BC%8D%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84MFC%E7%A8%8B%E5%BA%8F_files/image001.png" o:title=""></imagedata></shape>

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

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

新建AboutDialog.cppAboutDialog.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();

}

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

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

BOOL CDrawApp::InitInstance()

{

CAboutDialog AboutDlg;

AboutDlg.DoModal();

return FALSE;

}

运行程序如下:

<shape id="_x0000_i1026" style="WIDTH: 285pt; HEIGHT: 165pt" coordsize="21600,21600" type="#_x0000_t75"><imagedata src="MFC%EF%BC%8D%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84MFC%E7%A8%8B%E5%BA%8F_files/image003.png" o:title=""></imagedata></shape>

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

这一切是怎样发生的

MFCVCL有一个很大的区别,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.CPPAfxWinMain函数。

AfxGetApp()取回一个App指针,这个指针就是上面代码定义的DrawAppCWinApp的构造函数将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返回,程序结束。

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

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

分享到:
评论

相关推荐

    -----MFC-简单加法器------0

    在IT行业中,MFC(Microsoft ...通过学习和实践这个MFC简单加法器项目,开发者不仅可以深入了解MFC框架,还能提升Windows应用程序开发的能力。同时,这也是一个很好的起点,帮助开发者逐步过渡到更复杂的MFC应用开发。

    mfc:最简单的mfc程序

    在这个主题中,我们将深入探讨如何创建一个最简单的MFC程序。 首先,我们需要了解MFC的基本结构。一个MFC程序通常包括以下组件: 1. **应用程序类**(CWinApp):这是整个应用程序的入口点,负责初始化和关闭应用...

    第一个MFC程序---计算器

    标题中的“第一个MFC程序---计算器”指的是利用MFC库编写一个基本的计算器应用程序。这是一个常见的实践项目,用于初学者学习MFC的基本概念和操作流程。虽然这个计算器可能包含一些错误(BUG),但它仍然是一个有...

    最简单的MFC程序

    在这个“最简单的MFC程序”中,我们可以学习到以下几个关键的知识点: 1. **CWinApp类**:MFC程序的入口点,继承自CWinThread类。CWinApp负责应用程序的初始化、运行和退出过程。在创建MFC程序时,通常需要自定义一...

    BROTHER兄弟 MFC-295CN多功能一体机驱动A版For WinXP-64_Vista-64.zip

    描述中的"打印机驱动"简单明了地告诉我们,这个压缩包包含的是用于BROTHER MFC-295CN多功能一体机的驱动程序软件,使得计算机能够识别和控制这台设备进行打印操作。 【标签解析】 "打印机驱动"的标签再次强调了主要...

    MFC的一个简单注册小程序

    MFC,全称为Microsoft Foundation Classes,是微软提供的一套C++类库,用于构建Windows应用程序。这个简单的注册小程序是基于MFC框架构建的,旨在帮助初学者熟悉MFC的架构和编程模式。通过分析和学习这个小程序,...

    MFC--加法计算器

    在本文中,我们将深入探讨如何使用Microsoft Foundation Class (MFC) 库来创建一个简单的加法计算器。MFC 是微软为Windows平台开发的C++类库,它为开发者提供了构建图形用户界面(GUI)应用程序的强大工具。这个...

    MFC-Control.rar_MFC vs2008_mfc control_vs2008 MFC

    1. **新建MFC工程**:首先,你需要创建一个新的MFC应用程序项目,选择适当的工程模板,例如MFC对话框或MFC应用程序。 2. **添加控件**:在对话框编辑器中,你可以通过工具箱窗口选择需要的控件,并将其拖放到对话框...

    一个最简单的MFC程序实例.doc

    "一个最简单的MFC程序实例" MFC(Microsoft Foundation Classes)是一种基于C++的应用程序框架,用于开发Windows桌面应用程序。下面是从给定的文件中生成的相关知识点: 1. 什么是MFC? MFC是一个C++类库,用于...

    聊天室--网络编程MFC-WinSocket

    本文将深入探讨使用MFC(Microsoft Foundation Classes)库和WinSocket API在VC++环境下创建一个简单的聊天室应用。这个聊天室能够实现在局域网内的通信,允许用户通过指定的端口号进行互动。 首先,我们需要了解...

    初识MFC-MFC视频播放器

    在本文中,我们将深入探讨如何使用Microsoft Foundation Class (MFC) 库来创建一个简单的视频播放器,重点是集成Windows Media Player控件。MFC是一个C++类库,由微软提供,它为开发者提供了构建Windows应用程序的...

    VS2015-MFC-SOCKET DEMO亲测

    "VS2015-MFC-SOCKET DEMO亲测"是一个示例项目,旨在展示如何在MFC环境中创建一个简单的Socket应用程序。通过这个DEMO,我们可以学习到如何配置环境、创建Socket对象、连接到服务器以及进行数据交换。 首先,让我们...

    mfc-ado-database.zip_MFC DataBase_mfc 数据库

    MFC是微软提供的一套C++类库,它封装了Windows API,简化了Windows应用程序的开发。在数据库应用方面,MFC提供了ODBC(Open Database Connectivity)和DAO(Data Access Object)等接口,但更现代且功能强大的方式是...

    MFC-ADO.zip_MFC_mfc 数据库

    然而,由于ADO的出现,MFC也提供了对ADO的支持,因为ADO提供了更高级的功能和更简单的API。 1. **MFC ADO基础**:MFC中的CDatabase类是与数据库连接的核心,它代表了数据库连接。使用CDatabase类,你可以打开、关闭...

    mfc-draw.rar_MFC_MFC 画图工具_MFC画图_mfc draw_mfc 画图

    在"MFC简单画图"中,PEN对象用于定义线条的样式、颜色和宽度。MFC提供了CPen类来封装GDI的PEN,我们可以通过创建CPen对象,设置其属性,然后使用CDC的SelectObject()函数选择这个笔来进行绘制。例如: ```cpp CPen ...

    MFC-OpenGL-DrawTeapot.zip

    Visual Studio 2015是开发环境,它支持MFC,一个用于构建Windows应用程序的类库。下面我们将深入探讨MFC和OpenGL在3D图形渲染中的应用。 **MFC(Microsoft Foundation Classes)** 是微软为Windows API提供的一组...

    MFC 编写的最简单的程序 Helloworld

    MFC 编写的最简单的程序 Helloworld MFC 编写的最简单的程序 Helloworld MFC 编写的最简单的程序 Helloworld

    MFC-Bar-Pie.zip

    MFC(Microsoft Foundation Class)是微软提供的一种C++类库,用于构建Windows应用程序。它封装了Windows API,使得开发者能够更方便地使用Windows编程接口。在这个"MFC-Bar-Pie.zip"压缩包中,包含了使用MFC实现...

Global site tag (gtag.js) - Google Analytics