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

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

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





               当窗口函数做消息的比对时,我们就可以想办法导引它沿着这条路走过去: 



170 


…………………………………………………………Page 233……………………………………………………………

                                                           第3章    MFC 六大關鍵技術之模擬 



  CObject 

   CObject 



      CCmdTarget 

       CCmdTarget 



         CWinThread 

          CWinThread 



             CWinApp 

             CWinApp 



                CMyWinApp 

                 CMyWinApp 



         CWnd 

          CWnd 



             CView 



                CMyView 

                 CMyView 



             CFrameWnd 

             CFrameWnd 



                CMyFrameWnd 

                 CMyFrameWnd 



         CDocument 

          CDocument 



             CMyDoc 

             CMyDoc 



但是,MFC 之中用来处理消息的C++ 类别,并不呈单鞭发展。作为application framework 



的重要架构之一的document/view ,也具有处理消息的能力(你现在可能还不清楚什么是 



document/view ,没有关系)。因此,消息藉以攀爬的路线应该有横流的机会: 



  CObject 

   CObject 



      CCmdTarget 

       CCmdTarget 



          CWinThread 

           CWinThread 



              CWinApp 

              CWinApp 



                 CMyWinApp 

                  CMyWinApp 



          CWnd 

           CWnd 



              CView 



                 CMyView 

                  CMyView 



              CFrameWnd 

              CFrameWnd 



                 CMyFrameWnd 

                  CMyFrameWnd 



          CDocument 

           CDocument 



              CMyDoc 

              CMyDoc 



                                                                                                    171 


…………………………………………………………Page 234……………………………………………………………

                  第篇  勿在浮砂築高台 



                  消息如何流动,我们暂时先不管。是直线前进,或是中途换跑道,我们都暂时不管,本 



                  节先把这个攀爬路线网建立起来再说。这整个攀爬路线网就是所谓的消息映射表 



                   (Message Map );说它是一张地图,当然也没有错。将消息与表格中的元素比对,然后 



                  调用对应的处理例程,这种动作我们也称之为消息映射(Message Mapping)。 



                  为了尽量降低对正常(一般)类别声明和定义的影响,我们希望,最好能够像RTTI 和 



                  Dynamic Creation 一样,用一两个宏就完成这巨大蜘蛛网的构造。最好能够像 



                  DECLARE_DYNAMIC 和IMPLEMENT_DYNAMIC 宏那么方便。 



                  首先定义一个数据结构: 



                     struct AFX_MSGMAP 

                      { 

                             AFX_MSGMAP* pBaseMessageMap; 

                             AFX_MSGMAP_ENTRY* lpEntries; 

                      }; 



                   其中的 AFX_MSGMAP_ENTRY 又是另一个数据结构: 



                     struct AFX_MSGMAP_ENTRY  // MFC 4。0 format 

                      { 

                             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) 

                      }; 



                    其中的AFX_PMSG 定义为函数指针: 



                     typedef void (CCmdTarget::*AFX_PMSG)(void); 



                     然后我们定义一个宏: 



                     #define DECLARE_MESSAGE_MAP()  

                             static AFX_MSGMAP_ENTRY _messageEntries'';  

                             static AFX_MSGMAP messageMap;  

                             virtual AFX_MSGMAP* GetMessageMap() const; 



172 


…………………………………………………………Page 235……………………………………………………………

                                                       第3章    MFC 六大關鍵技術之模擬 



 于是,DECLARE_MESSAGE_MAP 就相当于声明了这样一个数据结构: 



                                                        pBaseMessageMap 

                         _messageEntries'' 

                                                            lpEntries 

                nMessage; nCode; nID; nLastID; nSig; pfn 



                                                          messageMap 



这个数据结构的内容填塞工作由三个宏完成: 



#define BEGIN_MESSAGE_MAP (theClass; baseClass)  

        AFX_MSGMAP* theClass::GetMessageMap() const  

                { return &theClass::messageMap; }  

        AFX_MSGMAP theClass::messageMap =  

        { &(baseClass::messageMap);  

                (AFX_MSGMAP_ENTRY*) &(theClass::_messageEntries) };  

        AFX_MSGMAP_ENTRY theClass::_messageEntries'' =  

        { 



#define ON_MAND (id; memberFxn)  

        { WM_MAND; 0; (WORD)id; (WORD)id; AfxSig_vv; (AFX_PMSG)memberFxn }; 



#define END_MESSAGE_MAP ()  

        { 0; 0; 0; 0; AfxSig_end; (AFX_PMSG)0 }  

        }; 



其中的AfxSig_end 定义为: 



enum AfxSig 

{ 

        AfxSig_end = 0;     // 'marks end of message map' 

        AfxSig_vv;    

}; 



 AfxSig_xx 用来描述消息处理例程memberFxn  的类型(参数与回返值)。本例纯为仿真 



 与简化,所以不在这上面作文章。真正讲到MFC 时(第四篇p580 ),我会再解释它。 



                                                                                             173 


…………………………………………………………Page 236……………………………………………………………

                   第篇  勿在浮砂築高台 



                    于是,以CView 为例,下面的源代码: 



                      // in header file 

                      class CView : public CWnd 

                      { 

                      public: 

                        。。。 

                        DECLARE_MESSAGE_MAP() 

                      }; 



                      // in implementation file 

                      #define CViewid 122 

                       。。。 

                      BEGIN_MESSAGE_MAP(CView; CWnd) 

                        ON_MAND(CViewid; 0) 

                      END_MESSAGE_MAP() 



                    就被展开成为: 



                      // in header file 

                      class CView : public CWnd 

                      { 

                      public: 

                        。。。 

                        static AFX_MSGMAP_ENTRY _messageEntries''; 

                        static AFX_MSGMAP messageMap; 

                        virtual AFX_MSGMAP* GetMessageMap() const; 

                      }; 



                      // in implementation file 

                      AFX_MSGMAP* CView::GetMessageMap() const 

                              { return &CView::messageMap; } 

                      AFX_MSGMAP CView::messageMap = 

                      { &(CWnd::messageMap); 

                              (AFX_MSGMAP_ENTRY*) &(CView::_messageEntries) }; 

                      AFX_MSGMAP_ENTRY CView::_messageEntries'' = 

                      { 

                        { WM_MAND; 0; (WORD)122; (WORD)122; 1; (AFX_PMSG)0 }; 

                        { 0; 0; 0; 0; 0; (AFX_PMSG)0 } 

                      }; 



                    以图表示则为: 



174 


…………………………………………………………Page 237……………………………………………………………

                                                     第3章    MFC 六大關鍵技術之模擬 



                                                       CWnd::messageMap 



                                                         pBaseMessageMap 

                   CView::_messageEntries'' 

                                                              lpEntries 

         WM_MAND;  0;  122;  122;   1;  (AFX_PMSG)0 



                 0; 0; 0; 0; 0; (AFX_PMSG)0             CView::messageMap 



  我们还可以定义各种类似ON_MAND 这样的宏,把各式各样的消息与特定的处 



  理例程关联起来。MFC 里头就有名为ON_ WM_PAINT 、ON_ WM_CREATE、ON_ WM_SIZE。。。 



  等等的宏。 



  我在Frame7 范例程序中为CCmdTarget  的每一衍生类别都产生类似上图的消息映射表: 



// in header files 

class CObject 

{ 

     。。。 // 注意:CObject 并不属于消息流动网的一份子。 

}; 

class CCmdTarget : public CObject 

{ 

。。。 

  DECLARE_MESSAGE_MAP() 

}; 

class CWinThread : public CCmdTarget 

{ 

 。。。 // 注意:CWinThread 并不属于消息流动网的一份子。 

}; 

class CWinApp : public CWinThread 

{ 

。。。 

  DECLARE_MESSAGE_MAP() 

}; 

class CDocument : public CCmdTarget 

{ 

。。。 

  DECLARE_MESSAGE_MAP() 

}; 

class CWnd : public CCmdTarget 

{ 

。。。 

  DECLARE_MESSAGE_MAP() 



                                                                                         175 


…………………………………………………………Page 238……………………………………………………………

                  第篇  勿在浮砂築高台 



                  }; 

                  class CFrameWnd : public CWnd 

                  { 

                  。。。 

                    DECLARE_MESSAGE_MAP() 

                  }; 

                  class CView : public CWnd 

                  { 

                  。。。 

                    DECLARE_MESSAGE_MAP() 

                  }; 

                  class CMyWinApp : public CWinApp 

                  { 

                  。。。 

                    DECLARE_MESSAGE_MAP() 

                  }; 

                  class CMyFrameWnd : public CFrameWnd 

                  { 

                  。。。 

                    DECLARE_MESSAGE_MAP() 

                  }; 

                  class CMyDoc : public CDocument 

                  { 

                  。。。 

                    DECLARE_MESSAGE_MAP() 

                  }; 

                  class CMyView : public CView 

                  { 

                  。。。 

                    DECLARE_MESSAGE_MAP() 

                  }; 



                  并且把各消息映射表的关联性架设起来,给予初值(每一个映射表都只有ON_MAND 



                  一个项目): 



                  // in implementation files 

                  BEGIN_MESSAGE_MAP(CWnd; CCmdTarget) 

                  ON_MAND(CWndid; 0) 

                  END_MESSAGE_MAP() 



                  BEGIN_MESSAGE_MAP(CFrameWnd; CWnd) 

                  ON_MAND(CFrameWndid; 0) 

                  END_MESSAGE_MAP() 



                  BEGIN_MESSAGE_MAP(CDocument; CCmdTarget) 



176 


…………………………………………………………Page 239……………………………………………………………

                                                    第3章    MFC 六大關鍵技術之模擬 



ON_MAND(CDocumentid; 0) 

END_MESSAGE_MAP() 



BEGIN_MESSAGE_MAP(CView; CWnd) 

ON_MAND(CViewid; 0) 

END_MESSAGE_MAP() 



BEGIN_MESSAGE_MAP(CWinApp; CCmdTarget) 

ON_MAND(CWinAppid; 0) 

END_MESSAGE_MAP() 



BEGIN_MESSAGE_MAP(CMyWinApp; CWinApp) 

ON_MAND(CMyWinAppid; 0) 

END_MESSAGE_MAP() 



BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd) 

ON_MAND(CMyFrameWndid; 0) 

END_MESSAGE_MAP() 



BEGIN_MESSAGE_MAP(CMyDoc; CDocument) 

ON_MAND(CMyDocid; 0) 

END_MESSAGE_MAP() 



BEGIN_MESSAGE_MAP(CMyView; CView) 

ON_MAND(CMyViewid; 0) 

END_MESSAGE_MAP() 



同时也设定了消息的终极镖靶CCmdTarget  的映射表内容: 



AFX_MSGMAP CCmdTarget::messageMap = 

 { 

        NULL; 

        &CCmdTarget::_messageEntries'0' 

 }; 



AFX_MSGMAP_ENTRY CCmdTarget::_messageEntries'' = 

 { 

        { 0; 0; CCmdTargetid; 0; AfxSig_end; 0 } 

 }; 



于是,整个消息流动网就隐然成形了(图3…5 )。 



                                                                                       177 


…………………………………………………………Page 240……………………………………………………………

                           第篇  勿在浮砂築高台 



                                                    CWinThread       CWinApp        CMyWinApp 



                                                                        ; ; 111; ; ;   ; ; 1111; ; ; 



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

                                                                                                      CView         CMyView 



                                                                                                                                         m 

                                                                                                                                         e 

                             CCmdTarget               CWnd          CFrameWnd       CMyFrameWnd 

                                                                                                                                         s 

                                                                                                       ; ; 122; ; ;    ; ; 1221; ; ; 



                                                                                                       0;0;0;0;0;0    0;0;0;0;0;0        s 

                                                                                                                                         a 



                                                        ; ; 12; ; ;     ; ; 121; ; ;   ; ; 1211; ; ; 

                                  ; ; 1; ; ;                                                                                             g 

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

                                0;0;0;0;0;0                                                                                              e 



                                                    CDocument      CMyDocument 



                                                        ; ; 13; ; ;     ; ; 131; ; ; 



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



                                        图3…5 Frame7  程序所架构起来的消息流动网 (也就是Message Map)。 



                          为了验证整个消息映射表,我必须在映射表中做点记号,等全部构造完成之后,再一一 



                          追踪把记号显示出来。我将为每一个类别的消息映射表加上这个项目: 



                                      ON_MAND(Classid; 0) 



                          这样就可以把Classid 嵌到映射表中当作记号。正式用途(于MFC  中)当然不是这样, 



                          这只不过是权宜之计。 



                          在main  函数中,我先产生四个对象(分别是CMyWinApp、CMyFrameWnd、CMyDoc、 



                          CMyView 对象): 



                           CMyWinApp theApp; // theApp 是CMyWinApp 对象 



                           void main() 

                           { 

                               CWinApp* pApp = AfxGetApp(); 

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