1、宏就是用宏定义指令#define定义一个标识符,用它来表示一个字符串或一段源代码。

MFC宏作为MFC类库的一个组成部分在MFC应用程序中经常出现。

MFC宏在路径

".../Microsoft Visual Studio/VC/atlmfc/include"

下的Afxwin.h、Afx.h及Afxmsg_.h等MFC头文件中分别进行了定义。

(1)常用的MFC宏

包括消息映射宏运行时类型识别宏序列化宏调试宏异常宏等。

要想真正了解MFC的内部机制和熟练运用MFC,必须掌握MFC宏的基本原理和使用方法。

(2)有关运行时类型识别的宏

运行时类型识别(RTTI)是指在程序运行时能够确定一个对象的类型。

MFC扩充了一般C++中运行时类型识别的功能,当一个类支持MFC的运行时类型识别功能时,它允许程序获取对象的信息(如类名、所占存储空间大小及版本号等)和基类信息(RTCI)。

1.运行时基础宏:RUNTIME_CLASS(class_name)

返回参数class_name所指定类的静态成员变量class##class_name的指针,该指针指向一个CRuntime结构。

宏定义如下:

#define RUNTIME_CLASS(class_name)
((CRuntimeClass*)(&class_name::class##class_name))

程序能够利用RUNTIME_CLASS宏实时创建类的实例。

为了让这个宏起作用,定义的类必须是类CObject的派生类,并且在派生类的定义中必须使用宏DECLARE_DYNAMIC、DECLARE_DYNCREATE或DECLARE_SERIAL,

在派生类的实现源文件中使用宏IMPLEMENT_DYNAMIC、IMPLEMENT_DYNCREATE或IMPLEMENT_SERIAL。

这三个宏使MFC类及其派生类具有三个不同等级的功能。

2.动态支持宏:DECLARE_DYNAMIC(class_name)和IMPELMENT_DYNAMIC(class_name,base_class_name)

使用动态支持宏能够使CObject派生类的对象具有基本的类型识别机能,可以通过调用成员函数CObject::IsKindOf(ClassName)测试对象与给定类Class_Name的关系。

DECLARE_DYNAMIC()宏定义如下:

#define DECLARE_DYNAMIC(class_name) \
public: \
static const CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \

例1: 定义一个类MyClass,使用RUNTIME_CLASS()宏的基本对象识别功能

//在头文件MyClass.h
class CMyClass:public CObject
{
DECLARE_DYNAMIC(CMyClass)
public:
void someFunction(void);
}; //在实现源文件MyClass.cpp中
#include "MyClass.h"
IMPLEMENT_DYNAMIC(CMyClass,CObject) void CMyClass::SomeFunction(void)
{
CObject* pObject=new CMyClass;
if(pObject->IsKindOf(RUNTIME_CLASS(CMyClass)))
{
CMyClass* pMyObject=(CMyClass*)pObject;
AfxMessageBox("MyObject is an object of the class CMyClass");
}
else
AfxMessageBox("MyObject is not an object of the class CMyClass");
delete pObject;
}

3.动态创建宏:DECLARE_DYNCREATE(class_name)和 IMPLEMENT_DYNCREATE(class_name,base_class_name)

动态创建是动态支持的一个超集,除了基本的类型识别机能,使用动态创建宏能够使CObject类的派生类具有运行时动态创建对象的功能。

注意,支持动态创建的类必须有一个默认的不带参数的构造函数,用于一个稳定的对象。

MFC应用程序框架利用这个机能动态创建新的对象。

例如,当序列化期间从磁盘读取一个对象时,应用程序框架将利用文档类、视图类和框类的动态创建功能业动态创建它们的运行时对象。

在MFC应用程序框架中,向导为MFC派生类自动添加了这两个动态创建宏。

4.序列化:DECLARE_SERIAL()和IMPLEMENT_SERIAL()

序列化是动态支持和动态创建的一个超集,除了基本的类别识别和动态创建机能,使用序列化宏能够使CObject类的派生类具有实现对象持久性的序列化功能。


MFC调试宏

1.TRACE跟踪声明宏

TRACE()宏语法说明如下:

TRACE(<输出格式>,<表达式>)

其中的参数是由输出格式和表达式组成,其形式与函数printf()的参数一样。

TRACE宏的功能是在调试运行时把表达式的值输出到Output调试窗口。

TRACE宏只在MFC应用程序Debug版的调试运行状态下才起作用,并且必须保证在Developer Studio中的Enable tracing设置,这需要执行Tools|MFC Tracer命令。

例2 对于以下代码:

    char* szName="LiMing";  

    int nAge=;  

    TRACE("Name=%s,Age=%",szName,nAge); 

调试运行时在Ouput窗口将输出以下内容:

      Name=LiMing,Age=

2.ASSERT断言宏

 ASSERT(<表达式>)

当执行该宏时,如果表达式为真,则程序继续执行;否则暂停程序的运行,并弹出一个对话框,告诉用户程序暂停运行的行及所在文件的信息。用户可选择终止运行、调试程序或继续运行。

例如,在视图派生类的成员函数GetDocument()中,MFC使用了ASSERT()宏判断当前文档是否是运行时类的对象。

例3 :设已自定义一个名为CMyFrame的框架窗口类,它也是CFrameWnd的派生类。在程序中构建一个与CMyFrame相关联的文档模板对象,并为构建的文档模板创建框架窗口。然后可以编写如下代码使用这个框架窗口。

      CMyFrame* pFrame=(CMyFrame*)AfxGetMainWnd();  

      ASSERT(pFrame->IsKindOf(RUNTIME_CLASS(CMyFrame)));   //判断pFrame的类型

      pFrame->DoSomeOperation();        //调用成员函数完成某些操作

AfxGetMainWnd()是一个全局函数,返回值向应用程序主窗口的指针,类型为CWnd*,因此必须对它进行强制类型转换。但如何知道是否转换成功?

CMyFrame类也是CObject的派生类,可以结合成员函数IsKindOf()使用ASSERT()宏来检查pFrame的类型。

在pFrame->DoSomeOperation()语句之前插入ASSERT()宏,就可以在运行机制时做类型检查,当类型不匹配时,引发一个断方,可以中断程序执行。

ASSERT宏只在Debug版本中才起作用,它在Release版本中是不会被编译的,

在Release版本中可以使用VERIFY宏。VERIFY宏与ASSERT宏在Debug版本中的作用一致,

区别在于在Release版本中VERIFY宏仍然有效,它会对参数表达式求值,但不管结果如何都不会暂停程序的运行。

为了避免给程序带来不良的后果,使用ASSERT宏时必须保证参数表达式中不能有函数调用语句,

因为ASSERT宏中的函数调用语句在Release版本中根本不在。

出现这种情况时,可以使用VERIFY宏取代ASSERT宏。

3.ASSERT_VALID断言有效宏

ASSERT_VALID()宏语法说明如下:

ASSERT_VALID(<指针>)

ASSERT_VALID宏用于检查指针和对象的有效性。对于一般指针,只检查指针是否为空。

对于MFC类对象指针,通过调用CObject类的成员函数AssertValid()判断对象的舍法性。

ASSERT_VALID宏提示指针或对象无效的方式与ASSERT宏一样,弹出一个信息对话框。

ASSERT_VALID宏也是只在Debug版本中才起作用。

MFC宏常识的更多相关文章

  1. 常用MFC宏

    最近我在用MFC开发一个智能家居监控平台的软件(用到了MSCOMM串口通信控件),当我通过在一个对话框类A中定义另一个对话框类B的对象访问B的public成员时,提示不可访问.后来经过多天的向朋友求救 ...

  2. MFC宏

    1,DECLARE_MESSAGE_MAP:在头文件中声明源文件中所含有的消息映射 2,BEGIN_MESSAGE_MAP:标记源文件消息映射的开始 3,END_MESSAGE_MA:标记源文件消息映 ...

  3. MFC宏—DECLARE_DYNCREATE

    DECLARE_DYNCREATE( class_name ) 参数: class_name 类的实际名字(不用引号括起来). 说明: 使用DECLARE_DYNCREATE宏可以使每个CObject ...

  4. MFC如何添加系统消息处理函数?

    http://zhidao.baidu.com/question/318026804.html 在MFC程序中,我们并不经常直接调用Windows API,而是从MFC类创建对象并调用属于这些对象的成 ...

  5. MFC 总体理解

    在MFC程序中,我们并不经常直接调用Windows API,而是从MFC类创建对象并调用属于这些对象的成员函数.也就是说MFC封装了Windows API 你说你喜欢C++而MFC换一种说法就是一个用 ...

  6. MFC命名规范

    属性部分 全局变量:g_ 常量:c_ c++类成员变量:m_ 静态变量:s_ 类型部分 指针:p 函数:fn 无效:v 句柄:h 长整型:l 布尔:b 浮点型(有时也指文件):f 双字:dw 字符串: ...

  7. 深入浅出MFC——MFC六大关键技术仿真(二)

    1. 仿真MFC目的:以MFC为例,学习application framework的内部运行.MFC六大关键技术: (1)MFC程序的初始化过程 (2)RTTI(Runtime Type Inform ...

  8. MFC异常处理的问题

    参考文献:http://technet.microsoft.com/zh-cn/library/t078xe4f(v=vs.85).aspx MFC中异常处理的语法和语义构建在标准C++异常处理语法和 ...

  9. MFC类别概述

    MFC 类别主要可分为下列数大群组: ■ General Purpose classes - 提供字符串类别.数据处理类别(如数组与串行),异 常情况处理类别.文件类别...等等. ■ Windows ...

随机推荐

  1. NOIP2009 codevs1173 洛谷P1073 最优贸易

    Description: 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通 ...

  2. The Usage of Pymongo

    Install pymongo document install pymongo from the tar package download from website python setup.y i ...

  3. NYOJ 740 DP

    “炫舞家“ST 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 ST是一个酷爱炫舞的玩家.TA很喜欢玩QQ炫舞,因此TA也爱屋及乌的喜欢玩跳舞机(Dance Danc ...

  4. sub-G 无线芯片基础知识

    1.典型无线收发机编码 2.前导码的作用是使接收机的时钟和发射机同步(有待验证),如果接收机工作在WOR模式,前导码还有唤醒接收机的功能(接收一定数量的前导码),此时发射机必须发送较长的前导码才能把接 ...

  5. Debug模式下加载文件,运行程序异常的慢

    今天在进行单元测试的时候,debug模式下加载速度很慢,但是run模式下速度很快. 原因:在debug模式下,断点位置不当,解决办法 移除编译器中的所有断点.

  6. mysql 事务,锁,与四大隔离级别

    概念 事务 原子性:事务必须是一个自动工作的单元,要么全部执行,要么全部不执行. 一致性:事务结束的时候,所有的内部数据都是正确的. 隔离性:并发多个事务时,各个事务不干涉内部数据,处理的都是另外一个 ...

  7. 2017 济南综合班 Day 4

    T1 外星人 二维前缀和 #include<cstdio> #define N 1001 using namespace std; bool v[N][N]; int sum[N][N]; ...

  8. hdu 3689 Infinite monkey theorem

    Infinite monkey theorem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/ ...

  9. C语言数据结构-栈

    一.栈的定义 栈(statck)这种数据结构在计算机中是相当出名的.栈中的数据是先进后出的(First In Last Out, FILO).栈只有一个出口,允许新增元素(只能在栈顶上增加). 移出元 ...

  10. 【POJ】1830 开关问题(高斯消元)

    http://poj.org/problem?id=1830 高斯消元无解的条件:当存在非法的左式=0而右式不等于0的情况,即为非法.这个可以在消元后,对没有使用过的方程验证是否右式不等于0(此时因为 ...