八宝书库 > 文学其他电子书 > 深入浅出MFC第2版(PDF格式) >

第74部分

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

小说: 深入浅出MFC第2版(PDF格式) 字数: 每页4000字

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!






                 。。。 



                 }; 



                 class CMyFrameWnd : public CFrameWnd 



                 { 



                 。。。 



                 }; 



               本章对衍生类别的命名规则是:在基础类别名称的前面加上〃My〃。这种规则真正上战场 



               时不见得适用,大型程序可能会自同一个基础类别衍生出许多自己的类别。不过以教学 



                目的而言,这种命名方式使我们从字面就知道类别之间的从属关系,颇为理想(根据我 



                的经验,初学者会被类别的命名搞得头昏脑胀)。 



358 


…………………………………………………………Page 421……………………………………………………………

                                                         第6章    MFC 程式的生死因果 



CWinApp -取代 WinMain 的地位 



    CWinApp  的衍生对象被称为application object ,可以想见,CWinApp 本身就代表一个程 



    式本体。一个程序的本体是什么?回想第1章的SDK 程序,与程序本身有关而不与视 



    窗有关的资料或动作有些什么? 系统传进来的四个WinMain 参数算不算? 



    InitApplication 和InitInstance 算不算?消息循环算不算?都算,是的,以下是MFC 4。x 



    的CWinApp 声明(节录自AFXWIN。H ): 



      class CWinApp : public CWinThread 

      { 

      // Attributes 

          // Startup args (do not change) 

          HINSTANCE m_hInstance; 

          HINSTANCE m_hPrevInstance; 

          LPTSTR m_lpCmdLine; 

          int m_nCmdShow; 



          // Running args (can be changed in InitInstance) 

          LPCTSTR m_pszAppName;  // human readable name 

          LPCTSTR m_pszRegistryKey;   // used for registry entries 



      public:  // set in constructor to override default 

          LPCTSTR m_pszExeName;       // executable name (no spaces) 

          LPCTSTR m_pszHelpFilePath;  // default based on module path 

          LPCTSTR m_pszProfileName;   // default based on app name 



      public: 

          // hooks for your initialization code 

          virtual BOOL InitApplication(); 



          // overrides for implementation 

          virtual BOOL InitInstance(); 

          virtual int ExitInstance(); 

          virtual int Run(); 

          virtual BOOL OnIdle(LONG lCount); 

      。。。 

      }; 



                                                                                      359 


…………………………………………………………Page 422……………………………………………………………

                   第篇    湷觥 FC  程式設計 



                   几乎可以说CWinApp 用来取代WinMain 在SDK 程序中的地位。这并不是说MFC 程序 



                   没有WinMain  (稍后我会解释),而是说传统上SDK 程序的WinMain 所完成的工作现 



                   在由CWinApp 的三个函数完成: 



                          virtual BOOL InitApplication(); 



                          virtual BOOL InitInstance(); 



                          virtual int Run(); 



                   WinMain 只是扮演役使它们的角色。 



                   会不会觉得CWinApp 的成员变量中少了点什么东西?是不是应该有个成员变量记录主 



                   窗口的handle   (或是主窗口对应之C++ 对象)?的确,在MFC 2。5  中的确有 



                   m_pMainWnd 这么个成员变量(以下节录自MFC 2。5  的AFXWIN。H ): 



                   class CWinApp : public CCmdTarget 

                   { 

                   // Attributes 

                       // Startup args (do not change) 

                       HINSTANCE m_hInstance; 

                       HINSTANCE m_hPrevInstance; 

                       LPSTR m_lpCmdLine; 

                       int m_nCmdShow; 



                       // Running args (can be changed in InitInstance) 

                       CWnd* m_pMainWnd;           // main window (optional) 

                       CWnd* m_pActiveWnd;         // active main window (may not be m_pMainWnd) 

                       const char* m_pszAppName;   // human readable name 



                   public:  // set in constructor to override default 

                       const char* m_pszExeName;       // executable name (no spaces) 

                       const char* m_pszHelpFilePath;  // default based on module path 

                       const char* m_pszProfileName;   // default based on app name 



                   public: 

                       // hooks for your initialization code 

                       virtual BOOL InitApplication(); 

                       virtual BOOL InitInstance(); 



                       // running and idle processing 

                       virtual int Run(); 

                       virtual BOOL OnIdle(LONG lCount); 



360 


…………………………………………………………Page 423……………………………………………………………

                                                     第6章    MFC 程式的生死因果 



    // exiting 

    virtual int ExitInstance(); 

。。。 

}; 



但从MFC 4。x 开始,m_pMainWnd  已经被移往CWinThread 中了(它是CWinApp 的父 



类别)。以下内容节录自MFC 4。x  的AFXWIN。H : 



class CWinThread : public CCmdTarget 

{ 

// Attributes 

                         

    CWnd* m_pMainWnd;      // main window (usually same AfxGetApp()…》m_pMainWnd) 

    CWnd* m_pActiveWnd;   // active main window (may not be m_pMainWnd) 



    // only valid while running 

    HANDLE m_hThread;       // this thread's HANDLE 

    DWORD m_nThreadID;      // this thread's ID 



    int GetThreadPriority(); 

    BOOL SetThreadPriority(int nPriority); 



// Operations 

    DWORD SuspendThread(); 

    DWORD ResumeThread(); 



// Overridables 

    // thread initialization 

    virtual BOOL InitInstance(); 



    // running and idle processing 

    virtual int Run(); 

    virtual BOOL PreTranslateMessage(MSG* pMsg); 

    virtual BOOL PumpMessage();     // low level message pump 

    virtual BOOL OnIdle(LONG lCount); // return TRUE if more idle processing 



public: 

    // valid after construction 

    AFX_THREADPROC m_pfnThreadProc; 

。。。 

}; 



熟悉Win32  的朋友,看到CWinThread 类别之中的SuspendThread 和ResumeThread 成 



员函数,可能会发出会心微笑。 



                                                                                  361 


…………………………………………………………Page 424……………………………………………………………

                    第篇    湷觥 FC  程式設計 



             CFrameWnd -取代 WndProc 的地位 



                    CFrameWnd 主要用来掌握一个窗口,几乎你可以说它是用来取代SDK 程序中的窗口函 



                    式的地位。传统的SDK 窗口函数写法是: 



                    long FAR PASCAL WndProc(HWND hWnd; UNIT msg; WORD wParam; LONG lParam) 

                    { 

                       switch(msg) { 

                           case WM_MAND : 

                                switch(wParam) { 

                                    case IDM_ABOUT : 

                                         OnAbout(hWnd; wParam; lParam); 

                                         break; 

                                } 

                                break; 

                           case WM_PAINT : 

                                OnPaint(hWnd; wParam; lParam); 

                                break; 

                           default : 

                                DefWindowProc(hWnd; msg; wParam; lParam); 

                       } 

                    } 



                   MFC 程序有新的作法,我们在Hello 程序中也为CMyFrameWnd 准备了两个消息处理 



                   例程,声明如下: 



                    class CMyFrameWnd : public CFrameWnd 

                    { 

                    public: 

                           CMyFrameWnd(); 

                           afx_msg void OnPaint(); 

                           afx_msg void OnAbout(); 

                           DECLARE_MESSAGE_MAP () 

                    }; 



                   OnPaint 处理什么消息?OnAbout 又是处理什么消息?我想你很容易猜到,前者处理 



                   WM_PAINT ,后者处理WM_MAND 的IDM_ABOUT 。这看起来十分俐落,但让人搞 



                   不懂来龙去脉。程序中是不是应该有「把消息和处理函数关联在一起」的设定动作?是 



                   的,这些设定在HELLO。CPP 才看得到。但让我先着一鞭:DECLARE_MESSAGE_MAP 



                   宏与此有关。 



362 


…………………………………………………………Page 425……………………………………………………………

                                            第6章    MFC 程式的生死因果 



这种写法非常奇特,原因是MFC  内建了一个所谓的Message Map 机制,会把消息自动 



送到「与消息对映之特定函数」去;消息与处理函数之间的对映关系由程序员指定。 



DECLARE_MESSAGE_MAP  另搭配其它宏,就可以很便利地将消息与其处理函数关联 



在一起: 



   BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd) 



    ON_WM_PAINT() 



    ON_MAND(IDM_ABOUT; OnAbout) 



   END_MESSAGE_MAP() 



稍后我就来探讨这些神秘的宏。 



                                                                      363 


…………………………………………………………Page 426……………………………………………………………

                    第篇    湷觥 FC  程式設計 



             引爆器-Application object 



                    我们已经看过HELLO。H 声明的两个类别,现在把目光转到HELLO。CPP 身上。这个档 



                    案将两个类别实作出来,并产生一个所谓的application object 。故事就从这里展开。 



                    下面这张图包括右半部的Hello 源代码与左半部的MFC 源代码。从这一节以降,我将 



                    以此图解释MFC 程序的激活、运行、与结束。不同小节的图将标示出当时的程序进行 



                    状况。 



                                                           HELLO。CPP 



                                                        1  CMyWinApp theApp;   // application object 



                                                           BOOL CMyWinApp::InitInstance() 

                    WINMAIN。CPP 

                                                           { 

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

                     int AFXAPI AfxWinMain (。。。) 

                     {

返回目录 上一页 下一页 回到顶部 0 0

你可能喜欢的