WEB开发网
开发学院软件开发VC MFC教程(4)-- 消息映射的实现(2) 阅读

MFC教程(4)-- 消息映射的实现(2)

 2010-03-25 20:33:48 来源:WEB开发网   
核心提示:MFC用哈希查找来查询消息映射缓冲池,消息缓冲池相当于一个哈希表,MFC教程(4)-- 消息映射的实现(2)(2),它是应用程序的一个全局变量,可以放512条最新用到的消息映射条目的缓冲信息,在使用函数AfxFindMessageEntry得到匹配结果之后,还必须判断nSig是否等于message,每一条缓冲信息是哈希

MFC用哈希查找来查询消息映射缓冲池。消息缓冲池相当于一个哈希表,它是应用程序的一个全局变量,可以放512条最新用到的消息映射条目的缓冲信息,每一条缓冲信息是哈希表的一个入口。

采用AFX_MSG_CACHE结构描述每条缓冲信息,其定义如下:

struct AFX_MSG_CACHE

{

UINT nMsg;

const AFX_MSGMAP_ENTRY* lpEntry;

const AFX_MSGMAP* pMessageMap;

};

nMsg存放消息ID,每个哈希表入口有不同的nMsg。

lpEnty存放和消息ID匹配的消息映射条目的地址,它可能是this所指对象的类的映射条目,也可能是这个类的某个基类的映射条目,也可能是空。

pMessageMap存放消息处理函数匹配成功时进行消息处理的当前类(this所指对象的类)的静态成员变量messageMap的地址,它唯一的标识了一个类(每个类的messageMap变量都不一样)。

this所指对象是一个CWnd或其派生类的实例,是正在处理消息的MFC窗口对象。

哈希查找:使用消息ID的值作为关键值进行哈希查找,如果成功,即可从lpEntry获得消息映射条目的地址,从而得到消息处理函数及其原型。

如何判断是否成功匹配呢?有两条标准:

第一,当前要处理的消息message在哈希表(缓冲池)中有入口;第二,当前窗口对象(this所指对象)的类的静态变量messageMap的地址应该等于本条缓冲信息的pMessagMap。MFC通过虚拟函数GetMessagMap得到messageMap的地址。

如果在消息缓冲池中没有找到匹配,则搜索当前对象的消息映射数组,看是否有合适的消息处理函数。

如果匹配到一个消息处理函数,则把匹配结果加入到消息缓冲池中,即填写该条消息对应的哈希表入口:

nMsg=message;

pMessageMap=this->GetMessageMap;

lpEntry=查找结果

然后,调用匹配到的消息处理函数。否则(没有找到),使用_GetBaseMessageMap得到基类的消息映射数组,查找和匹配;直到匹配成功或搜寻了所有的基类(到CCmdTarget)为止。

如果最后没有找到,则也把该条消息的匹配结果加入到缓冲池中。和匹配成功不同的是:指定lpEntry为空。这样OnWndMsg返回,把控制权返还给AfxCallWndProc函数,AfxCallWndProc将继续调用DefWndProc进行缺省处理。

消息映射数组的搜索在CCmdTarget::OnCmdMsg函数中也用到了,而且算法相同。为了提高速度,MFC把和消息映射数组条目逐一比较、匹配的函数AfxFindMessageEntry用汇编书写。

const AFX_MSGMAP_ENTRY* AFXAPI

AfxFindMessageEntry(const AFX_MSGMAP_ENTRY* lpEntry,

UINT nMsg, UINT nCode, UINT nID)

第一个参数是要搜索的映射数组的入口;第二个参数是Windows消息标识;第三个参数是控制通知消息标识;第四个参数是命令消息标识。

对Windows消息来说,nMsg是每条消息不同的,nID和nCode为0。

对命令消息来说,nMsg固定为WM_COMMAND,nID是每条消息不同,nCode都是CN_COMMAND(定义为0)。

对控制通知消息来说,nMsg固定为WM_COMMAND或者WM_NOTIFY,nID和nCode是每条消息不同。

对于Register消息,nMsg指定为0XC000,nID和nCode为0。在使用函数AfxFindMessageEntry得到匹配结果之后,还必须判断nSig是否等于message,只有相等才调用对应的消息处理函数。

上一页  1 2 3 4 5 6 7  下一页

Tags:MFC 教程 消息

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接