以前我一直搞不明白,說實話還是沉不下心來研究其中宏的具體含義.候捷的<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中採用宏,而非用所謂"面向對象"來設計的原因.