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

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

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




                                                                                     BOOL CMyWinApp::InitInstance() 

                              WINMAIN。CPP 

                                                                                     { 

                                                                                      5 

                              int AFXAPI AfxWinMain (。。。)                              m_pMainWnd = new CMyFrameWnd(); 

                              {                                                        m_pMainWnd…》ShowWindow(m_nCmdShow); 

                                                                                      7 

                                  CWinApp* pApp = AfxGetApp();                         m_pMainWnd…》UpdateWindow(); 

                                                                                      8 

                                                                                       return TRUE; 

                                2                                                    } 

                                  AfxWinInit(。。。); 



                                3                                                    CMyFrameWnd::CMyFrameWnd() 

                                  pApp…》InitApplication(); 

                                  pApp…》InitInstance();                              { 

                                4 

                                                                                      6 

                                  nReturnCode = pApp…》Run();                           Create(NULL; 〃Hello MFC〃; 。。。; 

                                9 

                                                                                              〃MainMenu〃); 

                                  AfxWinTerm();                                      } 

                              } 

                                                                                    void CMyFrameWnd::OnPaint()  { 。。。 } 11 



                                      AfxWndProc                                     void CMyFrameWnd::OnAbout()  { 。。。 } 

                                                         m                      m 

                                                         e                      e 

                                                         s                      s    BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd) 

                                                         s                      s 

                                                         a                      a 

                                      WM_PAINT                      WM_PAINT 

                                                         g                      g      ON_MAND(IDM_ABOUT; OnAbout) 

                                                         e 

                                                          r                     e  

                                                         o                             ON_WM_PAINT() 

                                                         u                      m 

                                                         t                      a 

                                                         i 

                                                         n 

                                          10                                         END_MESSAGE_MAP() 

                                                         g                      p 



                                                              。 

                                                              。 

                                                              。 



                            基本上Message Map 机制是为了提供更方便的程序接口(例如宏或表格),让程序员 



                            很方便就可以建立起消息与处理例程的对应关系。这并不是什么新发明,我在第1章示 



                            范了一种风格简明的SDK 程序写法,就已经展现出这种精神。 



                            MFC 提供给应用程序使用的「很方便的接口」是两组宏。以Hello  的主窗口为例, 



                            第一个动作是在HELLO。H  的CMyFrameWnd 加上DECLARE_MESSAGE_MAP : 



394 


…………………………………………………………Page 457……………………………………………………………

                                                    第6章    MFC 程式的生死因果 



    class CMyFrameWnd : public CFrameWnd 

    { 

    public: 

           CMyFrameWnd(); 

           afx_msg void OnPaint(); 

           afx_msg void OnAbout(); 

           DECLARE_MESSAGE_MAP() 

    }; 



第二个动作是在HELLO。CPP  的任何位置(当然不能在函数之内)使用宏如下: 



    BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd) 

        ON_WM_PAINT() 

        ON_MAND(IDM_ABOUT; OnAbout) 

    END_MESSAGE_MAP() 



这么一来就把消息WM_PAINT  导到OnPaint 函数, 把WM_MAND 



 (IDM_ABOUT )导到OnAbout 函数去了。但是,单凭一个ON_WM_PAINT 宏,没 



有任何参数,如何使WM_PAINT 流到OnPaint 函数呢? 



MFC 把消息主要分为三大类,Message Map 机制中对于消息与函数间的对映关系也明定 



以下三种: 



■ 标准Windows 消息(WM_xxx )的对映规则: 



  宏名称                  对映消息            消息处理函数(名称已由系统预设) 



ON_WM_CHAR                WM_CHAR              OnChar 



ON_WM_CLOSE               WM_CLOSE             OnClose 



ON_WM_CREATE              WM_CREATE            OnCreate 



ON_WM_DESTROY             WM_DESTROY           OnDestroy 



ON_WM_LBUTTONDOWN         WM_LBUTTONDOWN        OnLButtonDown 



ON_WM_LBUTTONUP           WM_LBUTTONUP          OnLButtonUp 



ON_WM_MOUSEMOVE           WM_MOUSEMOVE         OnMouseMove 



ON_WM_PAINT               WM_PAINT              OnPaint 



。。。 



                                                                                 395 


…………………………………………………………Page 458……………………………………………………………

                第篇    湷觥 FC  程式設計 



                ■  命令消息(WM_MAND)的一般性对映规则是: 



                    ON_MAND(;) 



                例如: 



                   ON_MAND(IDM_ABOUT; OnAbout) 



                   ON_MAND(IDM_FILENEW; OnFileNew) 



                   ON_MAND(IDM_FILEOPEN; OnFileOpen) 



                   ON_MAND(IDM_FILESAVE; OnFileSave) 



                ■   「Notification 消息」(由控制组件产生,例如BN_xxx )的对映机制的宏分 



                    为好几种(因为控制组件本就分为好几种),以下各举一例做代表: 



                 控制组件         宏名称                       消息处理函数 



                Button    ON_BN_CLICKED(;) memberFxn 



                boBox  ON_CBN_DBLCLK(;) memberFxn 



                Edit      ON_EN_SETFOCUS(;) memberFxn 



                ListBox   ON_LBN_DBLCLK(;) memberFxn 



                 各个消息处理函数均应以afx_msg void 为函数型式。 



                 为什么经过这样的宏之后,消息就会自动流往指定的函数去呢?谜底在于Message Map 



                 的结构设计。如果你把第3章的Message Map 仿真程序好好研究过,现在应该已是成竹 



                 在胸。我将在第9章再讨论MFC  的Message Map 。 



                 好奇心摆两旁,还是先把实用上的问题放中间吧。如果某个消息在Message Map 中找不 



                 到对映记录,消息何去何从?答案是它会往基础类别流窜,这个消息流窜动作称为 



                  「Message Routing」。如果一直窜到最基础的类别仍找不到对映的处理例程,自会有预 



                 设函数来处理,就像SDK 中的DefWindowProc 一样。 



                 MFC  的CCmdTarget 所衍生下来的每一个类别都可以设定自己的Message Map ,因为 



                 它们都可能(可以)收到消息。 



396 


…………………………………………………………Page 459……………………………………………………………

                                                第6章    MFC 程式的生死因果 



     消息流动是个颇为复杂的机制,它和Document/View 、动态生成(Dynamic Creation ), 



     文件读写(Serialization)一样,都是需要特别留心的地方。 



来龙去脉总整理 



     前面各节的目的就是如何将表面上看来不知所以然的MFC 程序对映到我们在SDK 程序 



     设计中学习到的消息流动观念,从而清楚地掌握MFC 程序的诞生与死亡。让我对MFC 



     程序的来龙去脉再做一次总整理。 



  程序的诞生: 



       ■ Application object 产生,内存于是获得配置,初值亦设立了。 



       ■ Afx WinMain 执行AfxWinInit,后者又调用AfxInitThread ,把消息队列尽量加大到 



          96。 



       ■ Afx WinMain  执行InitApplication 。这是CWinApp 的虚拟函数,但我们通常不改 



         写它。 



       ■ AfxWinMain 执行InitInstance 。这是CWinApp 的虚拟函数,我们必须改写它。 



       ■ CMyWinApp ::InitInstance 'new'  了一个CMyFrameWnd 对象。 



       ■ CMyFrameWnd 构造式调用Create,产生主窗口。我们在Create 参数中指定的 



         窗口类别是NULL , 于是MFC 根据窗口种类, 自行为我们注册一个名为 



         〃AfxFrameOrView42d〃  的窗口类别。 



       ■ 回到InitInstance  中继续执行ShowWindow ,显示窗口。 



       ■ 执行UpdateWindow ,于是发出WM_PAIN T。 



       ■ 回到AfxWinMain,执行Run ,进入消息循环。 



   程序开始运作: 



       ■  程序获得WM_PAINT 消息(藉由CWinApp::Run  中的::GetMessage 循环)。 



       ■   WM_PAINT 经由::DispatchMessage 送到窗口函数CWnd::DefWindowProc  中。 



                                                                         397 


…………………………………………………………Page 460……………………………………………………………

                第篇    湷觥 FC  程式設計 



                ■  CWnd::DefWindowProc 将消息绕行过消息映射表格(Message Map )。 



                ■  绕行过程中发现有吻合项目,于是调用项目中对应的函数。此函数是应用程序 



                  利用BEGIN_MESSAGE_MAP 和END_MESSAGE_MAP 之间的宏设立起来的。 



                ■  标准消息的处理例程亦有标准命名,例如WM_PAINT 必然由OnPaint 处理。 



                以下是程序的死亡: 



                ■  使用者选按【File/Close】,于是发出WM_CLOSE 。 



                ■  CMyFrameWnd 并没有设置WM_CLOSE 处理例程,于是交给预设之处理例程。 



                ■  预设函数对于WM_CLOSE  的处理方式是调用::DestroyWindow , 并因而发出 



                   WM_DESTRO Y。 



                ■  预设之WM_DESTROY 处理方式是调用::PostQuitMessage,因此发出WM_QUIT 。 



                ■  CWinApp::Run 收到WM_QUIT 后会结束其内部之消息循环, 然后调用 



                  ExitInstance,这是CWinApp 的一个虚拟函数。 



                ■  如果CMyWinApp 改写了ExitInstance  , 那么CWinApp::Run 所调用的就是 



                  CMyWinApp ::ExitInstance,否则就是CWinApp::ExitInstance 。 



                ■  最后回到AfxWinMain,执行AfxWinTerm,结束程序。 



           Callback 函数 



                Hello  的OnPaint 在程序收到WM_PAINT 之后开始运作。为了让〃Hello; MFC〃 字样从 



                天而降并有动画效果,程序采用LineDDA API  函数。我的目的一方面是为了示范消息的 



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