孙鑫VC++LESSON3:MFC框架程序剖析
??MFC是微軟提供給我們的基礎類庫,是一套面向對象的函數庫,以類的方式提供給我們使用,利用這些類可以有效地完成基于Windows的應用程序開發。
??對于在main函數之前定義的全局變量,他在進入入口函數之前就分配了內存,如果是類的對象就調用它的構造函數。
??CTestApp 類定義的theApp全局變量->CTestApp 類的構造函數->appmodul.pp中的WinMain函數。
??生成的MFC項目里面并沒有WinMain入口函數,而是在編譯的時候再鏈接到appmodul.pp中的WinMain函數。
??WinMain函數在C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc
??那么這個theApp全局對象有什么作用?這個theApp是個應用程序對象,每一個MFC程序當中有且僅有一個從CWinApp中派生出來的類,也有且僅有一個從這個應用程序類實例化出來的對象,他就表示了我們應用程序本身。在第一堂課寫的Win32SDK程序當中,我們表示一個應用程序實際上是從WinMain入口函數通過一個實例號來表示的,基于MFC的是通過產生一個應用程序類的對象來唯一表示的。這個全局變量再調用構造函數時,會先調用其父類CWinApp的構造函數(微軟提供),也就相應地完成了一些初始化的工作,這樣子類和基類就聯系起來了。
??因為這個基類帶參數的構造函數,這個參數有缺省值,所以子類構造函數可以不用顯示的調用基類構造函數
??CWinApp函數定義在appcore.cpp文件里
??C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc
??這個this指針指向派生類的對象。
https://blog.csdn.net/qq_45662588/article/details/116790909https://blog.csdn.net/qq_45662588/article/details/116790909
基類:
派生類
class Derived : public Base{ public:Derived(){cout << "Derived this : " << typeid(this).name() << endl;cout << "Derived this = " << this << endl;} };main函數
int main(int argc, char* argv[]) {std::cout << "*****************Derived**********************\n";Derived dev;dev.fun();std::cout << "\n*****************Base**********************\n";Base base;base.fun();system("pause");return 0; }結果為:
??接下來是WinMain函數,他是用AfxWinMain這個函數完成WinMain功能,帶afx前綴的函數是屬于應用程序框架的函數,應用程序框架的函數實際上是輔助我們生成這個應用程序框架模型,這個框架模型把很多類與類之間有機的集成提供給我們,我們可以根據它所設計的方案來設計我們自己的應用程序application framwarld
AfxWinMain在文件WinMain.cpp里面
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc
此處這個AfxGetApp()函數獲取一個CWinApp的指針,他所代表的含義同上所述的this指針,指向子類對象的指針。
??這里pApp調用了三個函數在這三個函數當中就完成了做一個應用程序所需要的幾個步驟:設計窗口類、注冊窗口類、創建窗口、顯示窗口、更新窗口、消息循環、窗口過程函數。這里InitApplication主要是MFC內部管理調用的一個函數。
下面pThread調用了InitInstasce(),pThread這個指針同樣是指向子類的對象的指針,CWinApp是從CWinThread派生出來的。
??可以看到InitInstasce是虛函數,根據動態性原理,pThread調用的InitInstasce(),是子類的InitInstasce
??接下來,又調用了RUN方法,實際上是完成了消息循環.
??設計窗口類:在MFC中他預先給我們定義好了幾種缺省的窗口類
??注冊窗口類:函數AfxEndDeferRegisterClass完成了注冊窗口類,他在wincore.cpp中。函數里面很多if根據你提供的類名進行注冊
??框架類
??判斷這個類是否注冊,沒有注冊的話進行注冊,然后第二條是把這個類名賦給lpszclass
??定義這個creatstruct結構體是為了能夠讓我們在生成窗口前有機會進行修改外觀,通過子類修改基類的參數
??顯示窗口
??更新窗口
??消息循環:
??translatemessage將WMKEY_UP和WMKEY_DOWN組合成WMKEY_CHAR消息,然后dispatchmessage將消息路由給操作系統,然后由操作系統交給窗口過程函數進行處理。
??流程:全局-》構造函數-》-》winmain-》initinstance(完成初始化的工作、完成窗口類的注冊、產生、顯示和更新)-》pumpmessage進入消息循環(取出一條消息路由給操作系統,然后由操作系統交給窗口過程函數進行處理),然后在此循環。
??在這個地方他設置的窗口過程函數選擇的是一個缺省的窗口過程函數,實際上在MFC當中所有的消息循環路由給操作系統的消息并不都是交給缺省的窗口過程函數處理的,他在這個里面做了個轉換,采用了一種消息映射的技術,由消息響應函數來進行處理。
總結
??第一步:構建全局對象(通過構建這個全局變量來啟動這個應用程序,正是由于這個全局對象產生了,this指針才能指向這個對象,如果沒有這個全局變量程序的編譯不會出錯但是運行出錯。當我們定義這個全局對象時會調用構造函數,由于構造子類先構造父類,所以CWinApp的構造函數就被調用,在CWinApp的構造函數當中,完成了一些應用程序初始化的一些工作,同時將我們子類的指針保存起來)
??第二步:指針保存起來之后進入到WinMain函數,在AfxWinMain函數當中就可以獲取到子類的指針,利用子類的指針,我們可以調用一個虛擬的函數,利用多態性的原理,相應的就會調用到子類里的函數,也就是InitInstance()函數。這個窗口產生來回進行了好幾個步驟
??第三步:在InitInstance這個函數中,完成初始化的工作、完成窗口類的注冊、創建、顯示和更新
??第三步:消息循環。在這個地方他設置的窗口過程函數選擇的是一個缺省的窗口過程函數,實際上在MFC當中所有的消息循環路由給操作系統的消息并不都是交給缺省的窗口過程函數處理的,他在這個里面做了個轉換,采用了一種消息映射的技術,由消息響應函數來進行處理。
??這個CMainFrame和CTestView類都是窗口類(從CWnd類派生出來的),CMainFrame可以理解為CTestView窗口的副窗口,他是覆蓋在框架窗口之上的。CTestApp表示的應用程序類,所產生對象是應用程序對象,在MFC程序當中,有且只能有一個應用程序對象。這個CTestDoc類實際是從CDocument類(文檔類)派生出來的。文檔視類結構:數據的存儲、加載都由文檔類完成,數據的顯式修改都由View類完成,這樣就把數據本身和數據的處理、顯示分開了。
??那么,是怎么實現CMainFrame、CTestDoc、CTestView三個結合起來呢?
??在InitInstance()中定義了一個單文檔模板指針,這個指針用了一個new,然后將文檔、框架類、View類有機的組合在一起了,通過一個單文檔的模板組合在一起了。然后利用AddDocTemplate函數將這個單文檔模板增加到文檔模板當中。
??這個CAboutDlg表示了一個對話框的類,這個類可有可無,點幫助彈出來一個窗口,它本身也是一個窗口類,從CWnd派生出來
??窗口類、窗口類的對象、窗口之間是什么關系?
??對象和窗口的唯一聯系就是:c++對象內部定義了一個窗口的句柄,這個句柄保存了和他相關的窗口的句柄,窗口銷毀,他的對象銷不銷毀要看它的生命周期結沒結束。
??新建-Win32應用程序-空項目
??::ShowWincow,這里::前不加東西表示這是一個全局函數,是一個Win32平臺SDK的API函數,如果在一個類當中,你想調用的函數是平臺SDK的函數,但是跟你在類中定義的函數重復了,編譯時就會出錯,要加作用域解析符
總結
以上是生活随笔為你收集整理的孙鑫VC++LESSON3:MFC框架程序剖析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人脸识别智能门禁成为流动人口管理、访客管
- 下一篇: 电容式触摸芯片在电容式触摸按键中的应用