090922(星期二):MFC消息路由7, Frame8代码分析,消息链表的访问

Tuesday, 0922

一、Frame8消息的打印显示

1、主函数中的代码:

       // test Message Routing

       cout << endl << "pMyFrame received a WM_CREATE, routing path :" << endl;

       AfxWndProc(0, WM_CREATE, 0, 0, pMyFrame);

对应的执行代码:

 

LRESULT CMyFrameWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)

{

       AFX_MSGMAP* pMessageMap;

       AFX_MSGMAP_ENTRY* lpEntry;

       if (nMsg == WM_COMMAND) // special case for commands

       {

              if (OnCommand(wParam, lParam))

                     return 1L; // command handled

              else

                     return (LRESULT)DefWindowProc(nMsg, wParam, lParam);

       }

       pMessageMap = GetMessageMap();

       for (; pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMessageMap)

       {

              lpEntry = pMessageMap->lpEntries;

              printlpEntries(lpEntry);

       }

       return 0; // add by JJHou. if find, should call lpEntry->pfn,

       // otherwise should call DefWindowProc.

}

 

2MSGMAP的本质是链表

struct AFX_MSGMAP

{

       AFX_MSGMAP* pBaseMessageMap;

       AFX_MSGMAP_ENTRY* lpEntries;

};

AFX_MSGMAP就是一个链表Node

pBaseMessageMap就是next指针;

AFX_MSGMAP_ENTRY* lpEntries;就是链表Nodedata

 

而且这个链表只有尾部没有头部,头部无限延伸,尾部如下:

CCmdTarget处打住,next强制为NULL

AFX_MSGMAP* CCmdTarget::GetMessageMap() const

{

       return &CCmdTarget::messageMap;

}

 

AFX_MSGMAP CCmdTarget::messageMap =

{

       NULL,

       &CCmdTarget::_messageEntries[0]

};

 

AFX_MSGMAP_ENTRY CCmdTarget::_messageEntries[] =

{

       { 0, 0, CCmdTargetid, 0, AfxSig_end, 0 }

};

 

3、链表NodeDATA

是一个指针,这只是形式,本质上DATA就是一个AFX_MSGMAP_ENTRY型的数组。

struct AFX_MSGMAP_ENTRY // MFC 4.0

{

       UINT nMessage; // windows message

       UINT nCode; // control code or WM_NOTIFY code

       UINT nID; // control ID (or 0 for windows messages)

       UINT nLastID; // used for entries specifying a range of control id's

       UINT nSig; // signature type (action) or pointer to message #

       AFX_PMSG pfn; // routine to call (or special value)

};

 

4、打印一个DATA结构的函数

void printlpEntries(AFX_MSGMAP_ENTRY* lpEntry)

{

       struct {

       UINT classid;

       char* classname;

       } classinfo[] = {

                                          CCmdTargetid , "CCmdTarget ",

                                          CWinThreadid , "CWinThread ",

                                          CWinAppid , "CWinApp ",

                                          CMyWinAppid , "CMyWinApp ",

                                          CWndid , "CWnd ",

                                          CFrameWndid , "CFrameWnd ",

                                          CMyFrameWndid, "CMyFrameWnd ",

                                          CViewid , "CView ",

                                          CMyViewid , "CMyView ",

                                          CDocumentid , "CDocument ",

                                          CMyDocid , "CMyDoc ",

                                          0 , " "

                                   };

 

       for (int i=0; classinfo[i].classid != 0; i++)

       {

// 090922commentsAFX_MSGMAP_ENTRY* lpEntrylpEntry是指向一个AFX_MSGMAP_ENTRY数组的第一个元素。

// 但是这个for循环只检查了lpEntry的第一个元素,没有再类似lpEntry++去进行后续遍历。

// 这个for循环只是对打印机制的循环,根本就还没开始对链表的遍历,要遍历链表也是一个O(n^2)

              if (classinfo[i].classid == lpEntry->nID)

              {

                     cout << lpEntry->nID << " ";

                     cout << classinfo[i].classname << endl;

                     break;

              }

       }

}

 

5printlpEntries的实现有点小问题

按照这种方式即使给CMyFrameCmd加上了WM_CREATE的消息映射,也不会被遍历到。

比如:

AFX_MSGMAP_ENTRY CMyFrameWnd::_messageEntries[] =

{

    { WM_COMMAND, 0, (WORD) CMyFrameWndid, (WORD) CMyFrameWndid,  AfxSig_vv, (AFX_PMSG)0 },

// 在现有的基础上加上:

{ WM_CREATE, 0, (WORD) CMyFrameWndid, (WORD) CMyFrameWndid,  AfxSig_vv, (AFX_PMSG)1 },

    { 0,          0,                     0,                   0, AfxSig_end, (AFX_PMSG)0 }  

};

 

AfxWndProc(0, WM_CREATE, 0, 0, pMyFrame); 还是无法访问到,因为printlpEntries不会访问其入参lpEntry的第2个元素。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值