【科普】非常简单的MFC程序
acmilan2015/06/17软件综合 IP:四川
其实MFC的原理很简单,不要被AppWizard生成的代码吓住了。MFC程序是从CWinApp类和InitInstance()函数开始的。

MFC的原理:
1. 开发者定义一个基于CWinApp的类,初始化它的唯一的对象,内置构造函数会向MFC注册这个对象。
2. MFC会在自身初始化完毕后调用该对象的InitInstance()函数,开发者可以重写这个函数来对程序进行初始化:
(1) InitInstance()可以初始化主窗口m_pMainWnd,也可以进行其它的操作,如显示对话框。
(2) InitInstance()函数初始化并设置主窗口后返回TRUE进入消息循环,等待WM_QUIT退出;如不设置主窗口或返回FALSE,则直接退出。

3. CWinApp可以调用其它类(如CDialog或CFrameWnd)来实现程序的功能,通过继承重写这些类,可以对它们进行编程。
4. 通过BEGIN_MESSAGE_MAP和END_MESSAGE_MAP等宏定义,将各种菜单命令、Windows消息、控件通知映射到成员函数。

而以上这些,基本都可以由Visual C++各种向导自动化地完成。

MFC并不是没有WinMain函数,而是在程序库的内部实现了WinMain函数。MFC也不是没有WndProc函数,实际上也是在内部实现,并通过某种机制,将消息映射到各MFC类的成员函数。

MFC通过message map宏定义来处理消息,其中:
1. CWinApp等继承自CCmdTarget的类均可以收到WM_COMMAND消息——通常是菜单命令
2. CFrameWnd和CDialog等继承自CWnd的类可以收到WM_COMMAND命令消息,WM_NOTIFY控件通知,以及其它窗口消息。

最简单的MFC程序只有25行,简单吧:
<code class="lang-cpp">// 最简单的MFC程序
                                          
#include "stdafx.h"
                                          
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
                                          
class CSimpleProg1App : public CWinApp
{
public:
    CSimpleProg1App() {
    }
                                          
    virtual BOOL InitInstance() {
        return FALSE; // 直接退出
    }
                                                                            
    DECLARE_MESSAGE_MAP()
};
                                 
BEGIN_MESSAGE_MAP(CSimpleProg1App, CWinApp)
END_MESSAGE_MAP()       
                                 
CSimpleProg1App theApp; // 唯一的一个CSimpleProg1App对象</code>

基于对话框的最简单的程序:
<code class="lang-cpp">// SimpleProg1.h : PROJECT_NAME 应用程序的主头文件
//
                                                                          
#pragma once
                                                                          
#ifndef __AFXWIN_H__
    #error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif
                                                                          
#define IDD_SIMPLEPROG1_DIALOG 102 // 对话框资源
                                                                          
                                                                          
// CSimpleProg1App:
// 有关此类的实现,请参阅 SimpleProg1.cpp
//
                                                                          
class CSimpleProg1App : public CWinApp
{
public:
    CSimpleProg1App();
                                                                          
// 重写
public:
    virtual BOOL InitInstance();
                                                                          
// 实现
                                                                          
    DECLARE_MESSAGE_MAP()
};
                                                                          
extern CSimpleProg1App theApp;</code>
<code class="lang-cpp">// SimpleProg1.cpp : 定义应用程序的类行为。
//
                                                                         
#include "stdafx.h"
#include "SimpleProg1.h"
                                                                         
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
                                                                         
                                                                         
// CSimpleProg1App
                                                                         
BEGIN_MESSAGE_MAP(CSimpleProg1App, CWinApp)
END_MESSAGE_MAP()
                                                                         
                                                                         
// CSimpleProg1App 构造
                                                                         
CSimpleProg1App::CSimpleProg1App()
{
    // TODO: 在此处添加构造代码,
    // 将所有重要的初始化放置在 InitInstance 中
}
                                                                         
                                                                         
// 唯一的一个 CSimpleProg1App 对象
                                                                         
CSimpleProg1App theApp;
                                                                         
                                                                         
// CSimpleProg1App 初始化
                                                                         
BOOL CSimpleProg1App::InitInstance()
{
    CDialog dlg(IDD_SIMPLEPROG1_DIALOG);
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
        // TODO: 在此放置处理何时用
        //  “确定”来关闭对话框的代码
    }
    else if (nResponse == IDCANCEL)
    {
        // TODO: 在此放置处理何时用
        //  “取消”来关闭对话框的代码
    }
                                                                         
    // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
    //  而不是启动应用程序的消息泵。
    return FALSE;
}</code>

上面的是基于对话框的程序,用Win32API编写对话框程序同样比较简单,但是用Win32API编写框架窗口就太困难了——要自己注册窗口类,自己创建窗口,自己显示窗口,自己编写消息循环,还要自己编写WndProc函数,太麻烦了。如果你使用MFC,就会和对话框一样简单:
<code class="lang-cpp">// SimpleProg2.h : SimpleProg2 应用程序的主头文件
//
#pragma once
                                                                       
#ifndef __AFXWIN_H__
    #error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif
                                                                       
#define IDD_ABOUTBOX                100 // “关于”对话框资源
#define IDR_MAINFRAME               128 // 与主框架有关的菜单、标题文字、图标等资源
                                                                       
// CSimpleProg2App:
// 有关此类的实现,请参阅 SimpleProg2.cpp
//
                                                                       
class CSimpleProg2App : public CWinApp
{
public:
    CSimpleProg2App();
                                                                       
                                                                       
// 重写
public:
    virtual BOOL InitInstance();
                                                                       
// 实现
                                                                       
public:
    afx_msg void OnAppAbout();
    DECLARE_MESSAGE_MAP()
};
                                                                       
extern CSimpleProg2App theApp;</code>
<code class="lang-cpp">// SimpleProg2.cpp : 定义应用程序的类行为。
//
                                                                       
#include "stdafx.h"
#include "SimpleProg2.h"
                                                                       
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
                                                                       
                                                                       
// CSimpleProg2App
                                                                       
BEGIN_MESSAGE_MAP(CSimpleProg2App, CWinApp)
    ON_COMMAND(ID_APP_ABOUT, &CSimpleProg2App::OnAppAbout)
END_MESSAGE_MAP()
                                                                       
                                                                       
// CSimpleProg2App 构造
                                                                       
CSimpleProg2App::CSimpleProg2App()
{
    // TODO: 在此处添加构造代码,
    // 将所有重要的初始化放置在 InitInstance 中
}
                                                                       
// 唯一的一个 CSimpleProg2App 对象
                                                                       
CSimpleProg2App theApp;
                                                                       
                                                                       
// CSimpleProg2App 初始化
                                                                       
BOOL CSimpleProg2App::InitInstance()
{
    // 若要创建主窗口,此代码将创建新的框架窗口
    // 对象,然后将其设置为应用程序的主窗口对象
    CFrameWnd* pFrame = new CFrameWnd;
    if (!pFrame)
        return FALSE;
    m_pMainWnd = pFrame;
    // 创建并加载框架及其资源
    pFrame->LoadFrame(IDR_MAINFRAME,
        WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,
        NULL);
                                                                       
    // 唯一的一个窗口已初始化,因此显示它并对其进行更新
    pFrame->ShowWindow(SW_SHOW);
    pFrame->UpdateWindow();
                                                                         
    return TRUE;
}
                                                                       
// CSimpleProg2App 消息处理程序
                                                                       
// 用于运行对话框的应用程序命令
void CSimpleProg2App::OnAppAbout()
{
    CDialog aboutDlg(IDD_ABOUTBOX);
    aboutDlg.DoModal();
}</code>

可以发现这里根本没有Win32程序繁杂的窗口类注册、消息循环和WndProc函数——因为MFC已经帮我们实现了。我们要做的只是创建窗口并显示它。这里还定义了一个ID_APP_ABOUT“关于”菜单命令并在CWinApp里实现了它。ID_APP_ABOUT的值是系统内置的,所以不用手工定义。

[修改于 8年11个月前 - 2015/06/22 18:46:15]

来自:计算机科学 / 软件综合
3
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
acmilan 作者
8年11个月前 IP:四川
773781
MFC也能编写控制台应用程序,只是控制台应用程序没法新建主窗口,只能新建对话框:
<code class="lang-cpp">// MfcConsole.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#include "MfcConsole.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
 
 
// 唯一的应用程序对象
 
CWinApp theApp;
 
using namespace std;
 
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;
 
    HMODULE hModule = ::GetModuleHandle(NULL);
 
    if (hModule != NULL)
    {
        // 初始化 MFC 并在失败时显示错误
        if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
        {
            // TODO: 更改错误代码以符合您的需要
            _tprintf(_T("错误: MFC 初始化失败\n"));
            nRetCode = 1;
        }
        else
        {
            // TODO: 在此处为应用程序的行为编写代码。
            CDialog dlg(IDD_DIALOG1);
            dlg.DoModal();
        }
    }
    else
    {
        // TODO: 更改错误代码以符合您的需要
        _tprintf(_T("错误: GetModuleHandle 失败\n"));
        nRetCode = 1;
    }
 
    return nRetCode;
}</code>
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
novakon
8年11个月前 IP:广东
774161
能讲得这么清楚,很厉害。
我当年看到MFC的第一反应就是吓死爹了。从此不敢碰。一直都用.NET偷懒。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
8年11个月前 修改于 8年11个月前 IP:四川
776357
引用 novakon:
能讲得这么清楚,很厉害。
我当年看到MFC的第一反应就是吓死爹了。从此不敢碰。一直都用.NET偷懒。
实际上国内最流行的小型软件大多是用WTL和DirectUI做的
当然也有一些用MFC的,比如分区助手
就是很少看到用.NET做的流行的,国外反而比较偏爱.NET,可能和国内XP泛滥有关
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
所属分类
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,5年3个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}