MFC学习笔记7 MFC基础

本系列文章后续部分主要来自《Visual C++编程实战宝典 清华大学出版社》学习笔记
后续部分学习基于VS2010+

简介

微软基础类库(Microsoft Foundation Class Library,MFC)是一个编写Windows应用程序的框架类库。使用MFC类库编写 C++ 程序,可以便捷地实现界面功能、网络功能、多媒体功能和数据访问功能等各种常用功能。

MFC 类层次结构

这里写图片描述

CObject类是所有类的基类。在此基础之上,派生了CCmdTarget类,用于表示命令目标对象,CWnd类就是继承于此类。而在CWnd类上又派生了包括对话框、视图、控件、属性页、窗体框架和控制栏等在内的扩展对话框类。

MFC 全局函数

MFC中除了MFC类外,还包括部分宏和全局成员,这些都不属于类的成员,如全局函数和全局变量。常用的MFC全局函数有:

  • AfxAbort:MFC提供的默认终止函数
  • AfxBeginThread:开始一个新的线程
  • AfxCheckError():检测代码是否为错误代码
  • AfxCheckMemory():检测是否发生有关内存的错误
  • AfxDaoInit():初始化DAO数据库引擎
  • AfxDaoTerm():终止DAO数据库引擎
  • AfxDbInitModule():初始化MFC数据库DLL
  • AfxDoForAllClasses():在应用程序内存空间中,枚举所有序列化派生类
  • AfxDump():调试程序时,列出对象所有的状态
  • AfxDumpStack():列出当前堆栈的情况
  • AfxEndThread:结束一个旧的线程
  • AfxFormatString1:类似printf一般地将字符串格式化
  • AfxFormatString2:类似printf一般地将字符串格式化
  • AfxMessageBox:类似Windows API 函数 MessageBox
  • AfxOuputDebugString:将字符串输往除错装置
  • AfxGetApp:获得application object (CwinApp派生对象)的指针
  • AfxGetMainWnd:获得程序主窗口的指针
  • AfxGetInstance:获得程序的instance handle

MFC应用程序框架分析

入口函数 WinMain()

基于MFC框架的应用程序必有有一个派生自CWinApp类的对象,此对象在创建窗体前进行初始化。而CWinApp类派生自CWinThread类,代表应用程序执行的主线程,但一个应用程序可能具有一个或多个线程。CWinThread类中具有InitInstance()、Run()、ExitInstance()和OnIdle()成员函数。这些函数在CWinApp中也被重载使用,但是它们是作为应用程序对象执行而不是主线程。

MFC 应用程序也有一个WinMain()入口函数,我们一般不需要重写WinMain()函数,由类库提供。

派生自CWinApp的应用程序对象

CWinApp类是从Windows应用程序对象中派生而来的应用程序基类。应用程序提供初始化应用程序和实例的成员函数,并提供运行应用程序和终止应用程序的函数。每个使用MFC的应用程序只能包含一个派生自CWinApp的对象。当构造完C++全局对象后,框架会构造此对象,因此,当Windows调用MFC类库提供的WinMain()函数时,应用程序对象已经生效了。
当从CWinApp类派生应用程序类,重写InitInstance()成员函数创建应用程序的主对话框对象时,除了CWinApp的成员函数,MFC类库提供了几个全局函数来访问CWinApp对象和其它全局对象:

  • AfxGetApp()
  • AfxGetInstanceHandle()
  • AfxGetResourceHandle()
  • AfxGetAppName()
初始化应用程序的InitInstance()函数

Windows允许同时运行同一个程序的一个或多个实例。WinMain()函数在每次启动新的应用程序实例时,会调用InitInstance()函数。应用向导创建的标准的InitInstance()函数主要完成以下工作:

  • 创建文档模板,依次创建文档对象、视图对象和框架对话框
  • 从.ini文件中或windows注册表中装载标准文件选项,包括最近使用的文件名称等信息
  • 注册一个或多个文档模板
  • 对于MDI应用程序,创建一个主框架对话框
  • 从命令行上处理命令行打开文档,或打开新的空文档。

InitInstace()示例:

BOOL CMFCApplication1App::InitInstance()
{
    // 如果一个运行在 Windows XP 上的应用程序清单指定要
    // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
    //则需要 InitCommonControlsEx()。否则,将无法创建窗口。
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    // 将它设置为包括所有要在应用程序中使用的
    // 公共控件类。
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);

    CWinAppEx::InitInstance();


    // 初始化 OLE 库
    if (!AfxOleInit())
    {
        AfxMessageBox(IDP_OLE_INIT_FAILED);
        return FALSE;
    }

    AfxEnableControlContainer();

    EnableTaskbarInteraction(FALSE);

    // 使用 RichEdit 控件需要  AfxInitRichEdit2() 
    // AfxInitRichEdit2();

    // 标准初始化
    // 如果未使用这些功能并希望减小
    // 最终可执行文件的大小,则应移除下列
    // 不需要的特定初始化例程
    // 更改用于存储设置的注册表项
    // TODO: 应适当修改该字符串,
    // 例如修改为公司或组织名
    SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
    LoadStdProfileSettings(4);  // 加载标准 INI 文件选项(包括 MRU)


    InitContextMenuManager();

    InitKeyboardManager();

    InitTooltipManager();
    CMFCToolTipInfo ttParams;
    ttParams.m_bVislManagerTheme = TRUE;
    theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
        RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);

    // 注册应用程序的文档模板。文档模板
    // 将用作文档、框架窗口和视图之间的连接
    CSingleDocTemplate* pDocTemplate;
    pDocTemplate = new CSingleDocTemplate(
        IDR_MAINFRAME,
        RUNTIME_CLASS(CMFCApplication1Doc),
        RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口
        RUNTIME_CLASS(CMFCApplication1View));
    if (!pDocTemplate)
        return FALSE;
    AddDocTemplate(pDocTemplate);


    // 分析标准 shell 命令、DDE、打开文件操作的命令行
    CCommandLineInfo cmdInfo;
    ParseCommandLine(cmdInfo);



    // 调度在命令行中指定的命令。如果
    // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
    if (!ProcessShellCommand(cmdInfo))
        return FALSE;

    // 唯一的一个窗口已初始化,因此显示它并对其进行更新
    m_pMainWnd->ShowWindow(SW_SHOW);
    m_pMainWnd->UpdateWindow();
    return TRUE;
}
框架程序的运行核心Run()函数

框架应用程序运行时就是运行CWinApp类的Run()函数。

MFC 的消息映射

在Windows系统中,消息一般由从CWnd派生而来的对象处理,包括CFrameWnd、CMDIFrameWnd、CMDIChildWnd、CView、CDialog和其它从这些类派生而来的对象,这些对象封装了代表Windows窗口句柄的HWND。

传统的Windows应用程序中,MFC使用switch语句处理发送给窗口的消息。
VC中使用消息映射来处理消息。

标准Windows消息

Windows系统提供了一组标准Windows消息,一般由对话框类和视图类根据参数的取值进行处理。 比如:创建窗口、销毁窗口和窗口重绘等。每个标准Windows消息都有一个以WM开头的消息ID和对应的宏,格式是ON_WM_xxx,其中xxx是消息名称,如ON_WM_CREATE宏表示创建对话框消息。
标准Windows消息对应的处理函数名根据消息宏派生而来,格式是onXxx,消息处理函数的参数顺序依次是wParam和lParam。
示例:


protected:
    DECLARE_MESSAGE_MAP()


// CMFCApplication1App

BEGIN_MESSAGE_MAP(CMFCApplication1App, CWinAppEx)
    ON_COMMAND(ID_APP_ABOUT, &CMFCApplication1App::OnAppAbout)
    // 基于文件的标准文档命令
    ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew)
    ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
    // 标准打印设置命令
    ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinAppEx::OnFilePrintSetup)
END_MESSAGE_MAP()

DECLARE_MESSAGE_MAP宏表明消息映射。

触发菜单/快捷键产生的命令消息

MFC除了支持标准Windos消息外,还支持命令消息。
使用ON_COMMAND宏可以在消息映射表中指定命令消息对应的处理函数。
使用ON_UPDATE_COMMAND宏可以在消息映射表中指定命令更新消息对应的处理函数

宏的第一个参数是命令ID,第二个参数是命令消息的处理函数。

命令处理函数没有参数和返回值,命令更新处理函数只有一个CCmdUI类型的参数并且没有返回值,其定义方式为:

ON_COMAND(id,memberFxn)   //命令消息宏
ON_UPDATE_COMMAND_UI(id,memberFxn)  //命令更新消息定义。

使用ON_MESSAGE宏自定义消息

MFC还支持用户自定义消息。使用ON_MESSAGE宏可以在消息映射表中指定消息对应的处理函数。
示例:

#define WM_MYMESSAGE WM_USER + 100 //自定义消息值
//自定义消息处理函数
afx_msg LRESULT OnMyMessage(WPARAM wParam,LPARAM lParam);
//在类的实现文件中,自定义消息映射函数
BEGIN_MESSAGE_MAP(CMyWnd,CMyParentWndClass)
   ON_MESSAGE(WM_MYMESSAGE,OnMyMessage)
END_MESSAGE_MAP()

发送自定义消息:

CWnd* pWnd = ...;
pWnd->SendMessage(WM_MYMESSAGE);

用户自定义消息的消息ID值的范围是从WM_USER~0x7fff。

注册系统消息

上面3种消息都是基于同一个窗口下的消息处理。要在系统中定义一个独立于窗口的唯一的消息处理,可以使用Windows注册消息。使用RegisterWindowMessage()函数可以创建在系统中唯一的消息ID。
使用ON_REGISTERED_MESSAGE宏可以在消息映射表中指定Windows注册消息对应的处理函数,宏的参数为使用RegisterWindowMessage()函数返回的UINT类型的消息ID。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程圈子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值