superwei

          導航

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          統計

          常用鏈接

          留言簿(4)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          《深入淺出MFC》學習筆記之二

          《深入淺出MFC》學習筆記之二 - -

          Tag-《深入淺出MFC》學習筆記之                                          

                                              -《深入淺出MFC》學習筆記之二 
                                              作者:XGM 2001-8-14

                       
                       
                          
                      MFC程序也是Windows程序,所以它也有一個WinMain,但是我們在程序中看不到它的蹤影。實際上,在程序進入點之前,有一個(而且只有一個)全局對象(在Hello程序中名為theApp),這是所謂的application
                      object,當操作系統將程序加載并激活時,這個全局對象獲得配置,其構造函數會先執行,比WinMain更早。
                      書中所舉Hello程序,是一個簡單的MFC程序,其主體在于WinMain和WndProc,而這兩個部分其實都有相當程度的不變性。MFC就是把有著相當固定行為的WinMain內部操作封裝在CWinApp中;把有著相當固定行為的WndProc內部操作封裝在CFrameWnd中。也就是說,CWinApp代表程序本體,CFrameWnd代表一個主框窗口

                      雖然WinMain和WndProc內部操作有相當程度的不變性,但面對不同應用程序也需有變化,所以必須以這兩個類為基礎,派生自己的類,并改寫其中一部分成員函數。

                       
                      CWinApp----取代WinMain的地位
                      傳統上SDK程序的WinMain所完成的工作現由CWinApp的三個函數完成:
                      virtual BOOL InitApplication( );
                      virtual BOOL InitInstance( );
                      virtual BOOL Run( );
                      CFrameWnd-----取代WndProc的地位
                      CFrameWnd主要用來掌握一個窗口
                      引爆器------Application object
                      當執行Hello程序時,這個全局對象產生,于是構造函數(見APPCORE.CPP)執行起來,CWinApp之中的成員變量將因為這個全局對象的誕生而獲得配置與初值,配置完成后,WinMain(MFC早已準備好,并由鏈接器直接加到應用程序中去的)登場。

                      AfxWinInit:是繼CWinApp構造函數之后的第一個操作;
                      此后的操作是pApp->InitApplication(其中的pApp指向CMyWinApp對象,即本例中的theApp),因為CMyWinApp繼承自CWinApp,而InitApplication又是CWinApp的一個虛擬函數,我們沒有改寫它(大部分情況下也不需要改它),所以上述操作相當于調用CWinApp::InitApplication。此程序的代碼出現在APPCORE.CPP中;

                      繼InitApplication之后,AfxWinMain調用pApp->InitInstance,InitInstance是CWinApp的一個虛擬函數(應用程序一定要改寫這個函數,因為它在CWinApp中是個空函數,沒有任何默任操作),我們改寫了它,所以上述操作就是調有我們自己的這個InitInstance函數,我們將在該處展開我們的主窗口生命。

                      CMyWinApp::InitInstance一開始new了一個CMyFrameWnd對象,new會引發構造函數CmyFrameWnd::CMyFrameWnd,其中調用了CFrameWnd的成員函數Create,它將產生一個窗口。

                        
                      Create函數共八個參數,第一個,指定WNDCLASS窗口類,如果放置NULL,表示要以MFC內建的窗口類產生一個標準的外框窗口(Create函數在產生窗口之前會引發窗口類的注冊操作,下一段講述這一內容);第二個,指定窗口標題;第三個,指定窗口風格,默認是WS-OVERLAPPEDWINDOW,如果你不想要窗口右上角的極大極小鈕,可以改成WS-OVERLAPPED|WS-CAPTION|WS-SYSMENU|WS-THICKFRAME|WS-MINIMIZEBOX|WS-MAXIMIZEBOX,如果希望有垂直滾動條,再加上WS-VSCROLL;第四個參數,指定窗口的位置與大小,默認值rectDefault
                      ;第五個,指定父窗口,第六個指定菜單;第七個,為擴充風格,唯有以:CreateWindowEx(而非:CreateWindow)函數才能完成,事實上,CFrameWnd:Create最終調用的正是:CreateWindowEx;第八個,是一個指向CCreateContext結構的指針,framework利用它,在具備Document/View結構的程序中初始化外框窗口,默認值NULL

                      CFrameWnd:Create在函數中調用CreateEx(CWnd有這個成員函數,但其派生類CFrameWnd并沒有,所以這里調用的實際上是CWnd:CreateEx);后者又調用PreCreateWindow虛擬函數(它在CWnd及其派生類CFrameWnd都有定義,所以實際上調用的是CFrameWnd::PreCreateWindow),這個函數調用了AfxDeferRegisterClass宏,它表示如果變量afxRegisteredClass的值顯示系統已經注冊了fClass
                      這種窗口類,MFC啥也不做,否則就調用AfxEndDeferRegisterClass(fClass){它調用兩個函數完成實際的窗口類注冊操作,一個是RegisterWithIcon,一個是AfxRegisterClass},準備注冊之。

                      窗口顯示與更新
                      CMyFrameWnd::CMyFrameWnd結束后,窗口已經誕生出來;程序又回到CMyWinApp::InitInstance,于是調用ShowWindow函數令窗口顯示出來,并調用UpdateWindow函數令Hello程序送出WM-PAINT

                      CWinApp::Run----程序生命的活水源頭
                      Run又是CWinApp的一個虛擬函數,我們沒有改寫它(大部分情況下也不需要改它),所以上述操作相當于調用CWinApp::Run
                      WinMain已由MFC提供,窗口類已由MFC注冊完成,連窗口函數也都由MFC提供
                      把消息與處理函數連接在一起:Message Map機制
                      MFC提供給應用程序使用的“很方便的接口”是兩組宏,以Hello為例,第一個操作是在Hello.h的CMyFrameWnd加上DECLARE-MESSAGE-MAP;第二個操作是在Hello.cpp的任何位置(當然不能在函數內)使用宏

                      BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
                         ON_COMMAND(IDM_ABOUT, OnAbout)
                         ON_WM_PAINT()
                      END_MESSAGE_MAP()
                       
                      來龍去脈總整理
                      程序的誕生
                      Application object 產生, 內存于是獲得配置,初值亦設立了。
                        AfxWinMain執行AfxWinInit,后者又調有AfxInitThread,把消息隊列盡量加
                      大到96
                        AfxWinMain執行InitApplication。這是CWinApp的虛擬函數,我們通常不改寫它
                        AfxWinMain執行InitInstance。這是CWinApp的虛擬函數,我們必須改寫它
                        CMyWinApp::InitInstance “new”了一個CMyFrameWnd對象
                       
                      CmyFrameWnd構造函數調用Create,產生主窗口。我們在Create參數中指定的窗口類是NULL,于是MFC根據窗口種類,自行為我們注冊一個名為“AfxFrameOrView42d”的窗口類。

                        回到InitInstance中繼續執行ShowWindow,顯示窗口
                      執行UpdateWindow,于是發出WM-PAINT
                      回到AfxWinMain,執行Run,進入消息循環。
                       
                      程序開始運行:
                        程序獲得WM-PAINT消息(由CWinApp::Run中的::GetMessage循環)
                        WM-PAINT經由::DispatchMessage送到窗口函數CWnd::DefWindowProc中。
                        CWnd::DefWindowProc將消息傳遞到消息映射表格
                       
                      傳遞過程中發現有相符項目,于是調用項目中對應的函數。此函數是利用BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之間的宏設立起來的。

                        標準消息的處理程序亦有標準命名,例如WM-PAINT必由OnPaint處理
                       
                      程序的死亡:
                          使用者單擊File/Close,于是發出WM-CLOSE
                          CMyFrameWnd并沒有設置WM-CLOSE處理程序,于是交給默認的處理程序
                          默認函數對于WM-CLOSE的處理方式是調用::DestroyWindow,并因而發出WM-DESTROY
                          默認的WM-DESTROY處理方式是調用::PostQuitMessage,因此發出WM-QUIT
                         
                      CWinApp::Run收到WM-QUIT后會結束內部之消息循環,然后調用ExitInstance,這是CWinApp的一個虛擬函數;如果CMyWinApp改寫了ExitInstance,那么CWinApp::Run所調用的就是CMyWinApp::ExitInstance,否則就是CWinApp::ExitInstance

                          最后回到AfxWinMain,執行AfxWinTerm,結束程序
                       
                      附Hello程序部分代碼:
                      Hello.cpp
                       
                      #include "Stdafx.h"
                      #include "Hello.h"
                      #include "Resource.h"
                       
                      CMyWinApp theApp;   // application object
                       
                      //--------------------------------------------------------------------

                      // CMyWinApp's member
                      //--------------------------------------------------------------------

                      BOOL CMyWinApp::InitInstance()
                      {
                         m_pMainWnd = new CMyFrameWnd();
                         m_pMainWnd->ShowWindow(m_nCmdShow);
                         m_pMainWnd->UpdateWindow();
                         return TRUE;
                      }
                      //--------------------------------------------------------------------

                      // CMyWinApp's member
                      //--------------------------------------------------------------------

                      BOOL CMyWinApp::OnIdle(LONG lCount)
                      {
                         CMyFrameWnd* pWnd = (CMyFrameWnd*)m_pMainWnd;
                         pWnd->IdleTimeHandler(lCount);
                       
                         return TRUE;
                      }
                      //--------------------------------------------------------------------

                      // CMyFrameWnd's member
                      //--------------------------------------------------------------------

                      CMyFrameWnd::CMyFrameWnd()
                      {
                         Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectDefault,
                                NULL, "MainMenu");     }
                      //--------------------------------------------------------------------

                      BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
                         ON_COMMAND(IDM_ABOUT, OnAbout)
                         ON_WM_PAINT()
                      END_MESSAGE_MAP()
                      //--------------------------------------------------------------------

                      void CMyFrameWnd::OnPaint()
                      {
                      CPaintDC dc(this);
                      CRect rect;
                       
                         GetClientRect(rect);
                       
                         dc.SetTextAlign(TA_BOTTOM | TA_CENTER);
                       
                         ::LineDDA(rect.right/2, 0, rect.right/2, rect.bottom/2,
                             (LINEDDAPROC) LineDDACallback, (LPARAM) (LPVOID) &dc);
                      }
                      //--------------------------------------------------------------------

                      VOID CALLBACK CMyFrameWnd::LineDDACallback(int x, int y, LPARAM
                      lpdc)
                      {
                      static char szText[] = "Hello, MFC";
                       
                         ((CDC*)lpdc)->TextOut(x, y, szText, sizeof(szText)-1);
                         for(int i=1; i<50000; i++); 
                      }
                      //--------------------------------------------------------------------

                      void CMyFrameWnd::OnAbout()
                      {
                         CDialog about("AboutBox", this);  // "AboutBox"
                         about.DoModal();
                      }
                      //--------------------------------------------------------------------

                      void CMyFrameWnd::IdleTimeHandler(LONG lCount)
                      {
                        CString str;
                        CRect rect(10,10,200,30);
                        CDC* pDC = new CClientDC(this);
                       
                        str.Format("%010d", lCount);
                        pDC->DrawText(str, &rect, DT_LEFT | DT_TOP);
                      }
                       
                      Hello.h
                       
                      class CMyWinApp : public CWinApp
                      {
                      public:
                         virtual BOOL InitInstance();       //
                         virtual BOOL OnIdle(LONG lCount);  // OnIdle e?^
                      };
                       
                      //--------------------------------------------------------------------

                      class CMyFrameWnd : public CFrameWnd
                      {
                      public:
                         CMyFrameWnd();            // constructor
                         afx_msg void OnPaint();   // for WM_PAINT
                         afx_msg void OnAbout();   // for WM_COMMAND (IDM_ABOUT)
                         void IdleTimeHandler(LONG lCount);  // we want it call by
                      CMyWinApp::OnIdle
                       
                      private:
                         DECLARE_MESSAGE_MAP()     // Declare Message Map
                         static VOID CALLBACK LineDDACallback(int,int,LPARAM);
                         //?C
                      };

          posted on 2005-11-01 14:39 小辭猬 閱讀(229) 評論(0)  編輯  收藏 所屬分類: C++


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 资中县| 赣州市| 台南市| 舟曲县| 温泉县| 长白| 宁国市| 新竹市| 浦东新区| 江陵县| 句容市| 金寨县| 柘荣县| 遂宁市| 宜都市| 孟津县| 上饶县| 方山县| 莎车县| 普格县| 邵阳市| 铜山县| 滦平县| 垫江县| 托克托县| 曲麻莱县| 禄丰县| 桓台县| 宁陕县| 建平县| 陇川县| 宁武县| 古丈县| 宁明县| 时尚| 行唐县| 四平市| 无锡市| 陈巴尔虎旗| 顺昌县| 松溪县|