以前我一直搞不明白,说实话还是沉不下心来研究其中宏的具体含义.候捷的<MFC深入浅出>讲的很详细,其中还有对MFC的简易模拟实现,不过还是直到昨天看了段源码才真正明白了其中原理.
首先,MFC的消息映射采用的数据结构就是一个二维数组
typedef struct _MSGMAP_ENTRY
{
UINT nMessage; //消息ID
void (Wnd::*pfn)(); //函数指针
}MSGMAP_ENTRY;
然后呢就可以声明一个MSGMAP_ENTRY类型的成员变量MSGMAP_ENTRY MessageEntry[];
其实这也就是MESSAGE_MAP_BEGIN的内容:
#define MESSAGE_MAP_BEGIN(ClassName) /
MSGMAP_ENTRY Wnd::MessageEntry[] = /
{
很明显下面就是要为数组赋值
#define MESSAGE(MSG, PEOC) /
{MSG, &PEOC},
MESSAGE(*,*)的作用就是在二维数组中添加一项
结束时调用MESSAGE_MAP_END ()
#define MESSAGE_MAP_END() /
{0, 0} /
};
即以0项结束,即ID为0,指针为NULL的项.
有了这个二维数组,只需要在消息循环的处理函数中
int count = 0;
while((MessageEntry[count].pfn) != 0)
{
if(MessageEntry[count].nMessage == nMsg)
{
(this->*MessageEntry[count].pfn)();
return 0;
}
count++;
}
即实现了消息映射,即对于特定ID调用相应的函数.
现在似乎不提倡使用宏,说会让代码不直观,而且增加调试难度.确实是这样,不过宏的优势是显而易见的.假如上面的功能不用宏,就需要在所有窗口类的基类中为所有的消息构造虚拟函数,性能肯定可以和JAVA比一下了,而宏则对性能无任何影响,这应该也是MFC中采用宏,而非用所谓"面向对象"来设计的原因.