友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
第三电子书 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

深入浅出MFC第2版(PDF格式)-第106部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!




         WNDPROC pfnWndProc; 

         if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL) 

                 return  ::DefWindowProc(m_hWnd; nMsg; wParam; lParam); 

         else 

                 return ::CallWindowProc(pfnWndProc; m_hWnd; nMsg; wParam; lParam); 

     } 



直线上溯(一般Windows 消息) 



     CWnd::WindowProc 调用的OnWndMsg 是用来分辨并处理消息的专职机构;如果是命令 



     消息,就交给Onmand 处理,如果是通告消息(Notification ),就交给OnNotify 处 



     理。WM_ACTIVATE  和WM_SETCURSOR 也都有特定的处理函数。而一般的Windows 讯 



     息,就直接在消息映射表中上溯,寻找其归宿(消息处理例程)。为什么要特别区隔出 



     命令消息WM_MAND 和通告消息WM_NOTIFY 两类呢?因为它们的上溯路径不 



     是那么单纯地只往父类别去,它们可能需要拐个弯。 



                               (        ) 

     #0001  // in WINCORE。CPP  MFC 4。0 

     #0002  BOOL CWnd::OnWndMsg (UINT message; WPARAM wParam; LPARAM lParam; LRESULT* pResult) 

     #0003  { 

     #0004      LRESULT lResult = 0; 

     #0005 

     #0006      // special case for mands 

     #0007      if (message == WM_MAND) 

     #0008      { 

     #0009          Onmand (wParam; lParam); 

     #0010          。。。 

     #0011      } 

     #0012 



                                                                                          567 


…………………………………………………………Page 630……………………………………………………………

                    第篇    深入  MFC  程式設計 



                    #0013      // special case for notifies 

                    #0014      if (message == WM_NOTIFY) 

                    #0015      { 

                    #0016          OnNotify (wParam; lParam; &lResult); 

                    #0017          。。。 

                    #0018      } 

                    #0019      。。。 

                    #0020      const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap(); 

                    #0021      UINT iHash; iHash = (LOWORD((DWORD)pMessageMap) ^ message) & (iHashMax…1); 

                    #0022      AfxLockGlobals(CRIT_WINMSGCACHE); 

                    #0023      AFX_MSG_CACHE msgCache; msgCache = _afxMsgCache'iHash'; 

                    #0024      AfxUnlockGlobals(CRIT_WINMSGCACHE); 

                    #0025 

                    #0026      const AFX_MSGMAP_ENTRY* lpEntry; 

                    #0027      if  (。。。)  //检查是否在chche 之中 

                    #0028      { 

                    #0029          // cache hit 

                    #0030          lpEntry = msgCache。lpEntry; 

                    #0031          if (lpEntry == NULL) 

                    #0032                  return FALSE; 

                    #0033 

                    #0034          // cache hit; and it needs to be handled 

                    #0035          if (message 《 0xC000) 

                    #0036                  goto LDispatch; 

                    #0037          else 

                    #0038                  goto LDispatchRegistered; 

                    #0039      } 

                    #0040      else 

                    #0041      { 

                    #0042          // not in cache; look for it 

                    #0043          msgCache。nMsg = message; 

                    #0044          msgCache。pMessageMap = pMessageMap; 

                    #0045 

                    #0046          for (/* pMessageMap already init'ed */; pMessageMap != NULL; 

                    #0047                  pMessageMap = pMessageMap…》pBaseMap) 

                    #0048          { 

                    #0049              //利用AfxFindMessageEntry 寻找消息映射表中 

                    #0050              //对应的消息处理例程。如果找到,再依nMsg 为一般消息 

                    #0051              // (《 0xC000)或自行注册之消息(》 0xC000)分别跳到 

                    #0052              // LDispatch: 或LDispatchRegistered: 去执行。 

                    #0053 

                    #0054              // Note: catch not so mon but fatal mistake!! 

                    #0055              //      BEGIN_MESSAGE_MAP(CMyWnd; CMyWnd) 

                    #0056 

                    #0057              if (message 《 0xC000) 

                    #0058              { 



568 


…………………………………………………………Page 631……………………………………………………………

                                                        第9章   訊息映射與命令繞行   



#0059                  // constant window message 

#0060                  if ((lpEntry = AfxFindMessageEntry (pMessageMap…》lpEntries; 

#0061                      message; 0; 0)) != NULL) 

#0062                  { 

#0063                      msgCache。lpEntry = lpEntry; 

#0064                      goto LDispatch; 

#0065                  } 

#0066              } 

#0067              else 

#0068              { 

#0069                  // registered windows message 

#0070                  lpEntry = pMessageMap…》lpEntries; 

#0071                  while ((lpEntry = AfxFindMessageEntry (lpEntry; 0xC000; 0; 0)) 

#0072                      != NULL) 

#0073                  { 

#0074                      UINT* pnID = (UINT*)(lpEntry…》nSig); 

#0075                      ASSERT(*pnID 》= 0xC000); 

#0076                              // must be successfully registered 

#0077                      if (*pnID == message) 

#0078                      { 

#0079                              msgCache。lpEntry = lpEntry; 

#0080                              goto LDispatchRegistered; 

#0081                      } 

#0082                      lpEntry++;      // keep looking past this one 

#0083                  } 

#0084              } 

#0085          } 

#0086          msgCache。lpEntry = NULL; 

#0087          return FALSE; 

#0088      } 

#0089      ASSERT(FALSE);      // not reached 

#0090 

#0091  LDispatch: 

#0092      union MessageMapFunctions mmf; 

#0093      mmf。pfn = lpEntry…》pfn; 

#0094 

#0095      switch (lpEntry…》nSig) 

#0096      { 

#0097      case AfxSig_bD: 

#0098              lResult = (this…》*mmf。pfn_bD)(CDC::FromHandle((HDC)wParam)); 

#0099              break; 

#0100 

#0101      case AfxSig_bb:     // AfxSig_bb; AfxSig_bw; AfxSig_bh 

#0102              lResult = (this…》*mmf。pfn_bb)((BOOL)wParam); 

#0103              break; 

#0104 



                                                                                         569 


…………………………………………………………Page 632……………………………………………………………

                   第篇    深入  MFC  程式設計 



                   #0105      case AfxSig_bWww:   // really AfxSig_bWiw 

                   #0106              lResult = (this…》*mmf。pfn_bWww)(CWnd::FromHandle((HWND)wParam); 

                   #0107                      (short)LOWORD(lParam); HIWORD(lParam)); 

                   #0108              break; 

                   #0109 

                   #0110      case AfxSig_bHELPINFO: 

                   #0111              lResult = (this…》*mmf。pfn_bHELPINFO)((HELPINFO*)lParam); 

                   #0112              break; 

                   #0113 

                   #0114      case AfxSig_is: 

                   #0115              lResult = (this…》*mmf。pfn_is)((LPTSTR)lParam); 

                   #0116              break; 

                   #0117 

                   #0118      case AfxSig_lwl: 

                   #0119              lResult = (this…》*mmf。pfn_lwl)(wParam; lParam); 

                   #0120              break; 

                   #0121 

                   #0122      case AfxSig_vv: 

                   #0123              (this…》*mmf。pfn_vv)(); 

                   #0124              break; 

                   #0125      。。。 

                   #0126      } 

                   #0127      goto LReturnTrue; 

                   #0128 

                   #0129  LDispatchRegistered:    // for registered windows messages 

                   #0130      ASSERT(message 》= 0xC000); 

                   #0131      mmf。pfn = lpEntry…》pfn; 

                   #0132      lResult = (this…》*mmf。pfn_lwl)(wParam; lParam); 

                   #0133 

                   #0134  LReturnTrue: 

                   #0135      if (pResult != NULL) 

                   #0136              *pResult = lResult; 

                   #0137      return TRUE; 

                   #0138  } 



                   #0001  AfxFindMessageEntry (const AFX_MSGMAP_ENTRY* lpEntry; 

                   #0002          UINT nMsg; UINT nCode; UINT nID) 

                   #0003  { 

                   #0004  #if defined(_M_IX86) && !defined(_AFX_PORTABLE) 

                   #0005  // 32…bit Intel 386/486 version。 

                   #0006          。。。 //以汇编语言码处理,加快速度。 

                   #0007  #else  // _AFX_PORTABLE 

                   #0008          // C version of search routine 

                   #0009          while (lpEntry…》nSig != AfxSig_end) 

                   #0010          { 

                   #0011              if (lpEntry…》nMessage == nMsg && lpEntry…》nCode == nCode && 



570 


…………………………………………………………Page 633……………………………………………………………

                                                                          第9章   訊息映射與命令繞行   



#0012                  nID 》= lpEntry…》nID && nID nLastID) 

#0013              { 

#0014                  return lpEntry; 

#0015              } 

#0016              lpEntry++; 

#0017          } 

#0018          return NULL;    // not found 

#0019  #endif  // _AFX_PORTABLE 

#0020  } 



 直线上溯的逻辑实在是相当单纯的了,唯一做的动作就是比对消息映射表,如果吻合就 



 调用表中项目所记录的函数。比对的对象有二,一个是原原本本的消息映射表(那个巨 



 大的结构),另一个是MFC 为求快速所设计的一个cache                                         (cache  的实作太过复杂,我并 



 没有把它的源代码表现出来)。比对成功后,调用对应之函数时,有一个巨大的switch/case 



 动作,那是为了确保类型安全(type…safe )。稍后我有一个小节详细讨论之。 



                          CWinThread        CWinApp         CMyWinApp 



                                                                                这就是在CMyView 窗口 



                                                                                所发生的WM_PAINT消 

                                                ; ; ; ; ;        ; ; ; ; ;       息的流动路线 



                                              0;0;0;0;0;0      0;0;0;0;0;0 

                                                                              CView           CMyView 



                                                                                                                   m 

                                                                                                                    e 

  CCmdTarget                 CWnd          CFrameWnd        CMyFrameWnd 

                                                                            
返回目录 上一页 下一页 回到顶部 0 0
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!