(轉載)VS2010/MFC編程入門之四(MFC應用程序框架分析)

上一講雞啄米講的是VS2010應用程序工程中文件的組成結構,可能大家對工程的運行原理還是很模糊,理不出頭緒,畢竟跟C++編程入門系列中的例程差別太大。這一節雞啄米就為大家分析下MFC應用程序框架的運行流程。

???????一.SDK應用程序與MFC應用程序運行過程的對比

?????? 程序運行都要有入口函數,在之前的C++教程中都是main函數,而Windows應用程序的入口函數是WinMain函數,MFC程序也是從WinMain函數開始的。下面雞啄米就給出用Windows SDK寫的“HelloWorld”程序,與應用程序框架進行對比,這樣能更好的了解框架是怎樣運行的。Windows SDK開發程序就是不使用MFC類庫,直接用Windows API函數進行軟件開發。雞啄米不是要講解SDK開發,只是為了對比而簡單介紹,至于SDK開發可以在大家學完MFC以后選擇是否要研究,一般來說有簡單了解就可以了。

???????SDK應用程序

?????? 首先,給出Windows SDK應用程序“HelloWorld”的源碼:??

C++代碼
  1. #include?<windows.h>????
  2. ??
  3. LRESULT?CALLBACK?myWndProc(HWND?hWindow,?UINT?msg,?WPARAM?wParam,?LPARAM?lParam); ??
  4. ?? ??
  5. int?WINAPI?WinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,?PSTR?szCmdLine,?int?iCmdShow)??? ??
  6. {??? ??
  7. ??const?static?TCHAR?appName[]?=?TEXT("Hello?world");??? ??
  8. ??WNDCLASSEX?myWin;??? ??
  9. ??myWin.cbSize?=?sizeof(myWin);??? ??
  10. ??myWin.style?=?CS_HREDRAW?|?CS_VREDRAW;??? ??
  11. ??myWin.lpfnWndProc?=?myWndProc;??? ??
  12. ??myWin.cbClsExtra?=?0;??? ??
  13. ??myWin.cbWndExtra?=?0;??? ??
  14. ??myWin.hInstance?=?hInstance;??? ??
  15. ??myWin.hIcon?=?0;??? ??
  16. ??myWin.hIconSm??=?0;??? ??
  17. ??myWin.hCursor?=?0;??? ??
  18. ??myWin.hbrBackground?=?(HBRUSH)(COLOR_WINDOW?+?1);??? ??
  19. ??myWin.lpszMenuName?=?0;??? ??
  20. ??myWin.lpszClassName?=?appName;??? ??
  21. ??//Register??????
  22. ??if?(!RegisterClassEx(&myWin))?return?0;??? ??
  23. ??const?HWND?hWindow?=?CreateWindow(??? ??
  24. ????appName,??? ??
  25. ????appName,??? ??
  26. ????WS_OVERLAPPEDWINDOW,??? ??
  27. ????CW_USEDEFAULT,??? ??
  28. ????CW_USEDEFAULT,??? ??
  29. ????CW_USEDEFAULT,??? ??
  30. ????CW_USEDEFAULT,??? ??
  31. ????0,??? ??
  32. ????0,??? ??
  33. ????hInstance,??? ??
  34. ????0);??? ??
  35. ??ShowWindow(hWindow,iCmdShow);??? ??
  36. ??UpdateWindow(hWindow);??? ??
  37. ??{??? ??
  38. ????MSG?msg;??? ??
  39. ????while(GetMessage(&msg,0,0,0))??? ??
  40. ????{??? ??
  41. ??????TranslateMessage(&msg);??? ??
  42. ??????DispatchMessage(&msg);??? ??
  43. ????}??? ??
  44. ????return?(int)msg.wParam;??? ??
  45. ??}??? ??
  46. }??? ??
  47. ?? ??
  48. LRESULT?CALLBACK?myWndProc(HWND?hWindow,?UINT?msg,?WPARAM?wParam,?LPARAM?lParam)??? ??
  49. {??? ??
  50. ??if?(msg==WM_PAINT)??? ??
  51. ??{??? ??
  52. ????PAINTSTRUCT?ps;??? ??
  53. ????const?HDC?hDC?=?BeginPaint(hWindow,&ps);??? ??
  54. ????RECT?rect;??? ??
  55. ????GetClientRect(hWindow,&rect);??? ??
  56. ????DrawText(hDC,TEXT("HELLO?WORLD"),-1,&rect,?DT_SINGLELINE?|?DT_CENTER?|?DT_VCENTER);??? ??
  57. ????EndPaint(hWindow,&ps);??? ??
  58. ????return?0;??? ??
  59. ??}??? ??
  60. ??else?if?(msg==WM_DESTROY)??? ??
  61. ??{??? ??
  62. ????PostQuitMessage(0);??? ??
  63. ????return?0;??? ??
  64. ??}??? ??
  65. ??return?DefWindowProc(hWindow,msg,wParam,lParam);??? ??
  66. }??

???????上面的程序運行的流程是:進入WinMain函數->初始化WNDCLASSEX,調用RegisterClassEx函數注冊窗口類->調用ShowWindow和UpdateWindow函數顯示并更新窗口->進入消息循環。關于消息循環再簡單說下,Windows應用程序是消息驅動的,系統或用戶讓應用程序進行某項操作或完成某個任務時會發送消息,進入程序的消息隊列,然后消息循環會將消息隊列中的消息取出,交予相應的窗口過程處理,此程序的窗口過程函數就是myWndProc函數,窗口過程函數處理完消息就完成了某項操作或任務。本例是要顯示“HELLO WORLD”字符串,UpdateWindow函數會發送WM_PAINT消息,但是此消息不經過消息隊列而是直接送到窗口過程處理,在窗口過程函數中最終繪制了“HELLO WORLD”字符串。

VS2010/MFC編程入門之四(MFC應用程序框架分析)

???????MFC應用程序

?????? 下面是MFC應用程序的運行流程,通過MFC庫中代碼進行分析:

?????? 首先在HelloWorld.cpp中定義全局對象theApp:CHelloWorldApp theApp;。調用CWinApp和CHelloWorldApp的構造函數后,進入WinMain函數(位于appmodul.cpp中)。

C++代碼
  1. extern?"C"?int?WINAPI ??
  2. _tWinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance, ??
  3. ????_In_?LPTSTR?lpCmdLine,?int?nCmdShow) ??
  4. #pragma?warning(suppress:?4985)???
  5. { ??
  6. ????//?call?shared/exported?WinMain???
  7. ????return?AfxWinMain(hInstance,?hPrevInstance,?lpCmdLine,?nCmdShow); ??
  8. }??

???????在TCHAR.h中,有此定義:#define _tWinMain???WinMain,所以這里的_tWinMain就是WinMain函數。它調用了AfxWinMain函數(位于WinMain.cpp中)。

C++代碼
  1. int?AFXAPI?AfxWinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,LPTSTR?lpCmdLine,?int?nCmdShow) ??
  2. {? ??
  3. ???????.............略 ??
  4. ???????//?App?global?initializations?(rare)???
  5. ???????if?(pApp?!=?NULL?&&?!pApp->InitApplication()) ??
  6. ??????????????goto?InitFailure; ??
  7. ??
  8. ???????if?(!pThread->InitInstance()) ??
  9. ???????{ ??
  10. ??????????????.........略 ??
  11. ???????} ??
  12. ??
  13. ???????// Run函數位于THRDCORE.cpp中,由此函數進入消息循環???
  14. ???????nReturnCode?=?pThread->Run(); ??
  15. ??
  16. ???????..............略 ??
  17. ??
  18. ???????return?nReturnCode; ??
  19. } ??

?????? 上面InitInstance函數的代碼如下:

C++代碼
  1. BOOL?CTestApp::InitInstance()????? ??
  2. {???? ??
  3. ???????.............略???? ??
  4. ???????CSingleDocTemplate*?pDocTemplate;???? ??
  5. ???????pDocTemplate?=?new?CSingleDocTemplate(???? ??
  6. ??????????????IDR_MAINFRAME,???? ??
  7. ??????????????RUNTIME_CLASS(CTestDoc),???? ??
  8. ??????????????RUNTIME_CLASS(CMainFrame),??????//?main?SDI?frame?window???????
  9. ??????????????RUNTIME_CLASS(CTestView));?? ??
  10. ???????if?(!pDocTemplate) ??
  11. ?????????????return?FALSE;?? ??
  12. ???????AddDocTemplate(pDocTemplate);???? ??
  13. ???????//?Parse?command?line?for?standard?shell?commands,?DDE,?file?open???????
  14. ??? ??
  15. ???????CCommandLineInfo?cmdInfo;???? ??
  16. ???????ParseCommandLine(cmdInfo);???? ??
  17. ??? ??
  18. ???????//ProcessShellCommand位于AppUI2.cpp中,注冊并創建窗口???????
  19. ???????if?(!ProcessShellCommand(cmdInfo))???? ??
  20. ?????????????return?FALSE;???? ??
  21. ??? ??
  22. ???????m_pMainWnd->ShowWindow(SW_SHOW);???? ??
  23. ???????m_pMainWnd->UpdateWindow();???? ??
  24. ??? ??
  25. ???????return?TRUE;???? ??
  26. }??? ??

???????InitInstance中的ProcessShellCommand函數又調用了CMainFrame的LoadFrame函數注冊并創建了窗口,執行完ProcessShellCommand函數以后,調用了m_pMainWnd的ShowWindow和UpdateWindow函數顯示并更新框架窗口。這些是不是與上面的SDK程序十分類似?

???????接下來該是消息循環了,上面的AfxWinMain函數中調用了pThread的Run函數(位于THRDCORE.cpp中),在Run中包含了消息循環。Run函數的代碼如下:

C++代碼
  1. int?CWinThread::Run()???? ??
  2. {???? ??
  3. ????????.............略???? ??
  4. ????????//?phase2:?pump?messages?while?available???????
  5. ????????do??? ??
  6. ????????{???? ??
  7. ??????????????//?pump?message,?but?quit?on?WM_QUIT???????
  8. ??????????????if?(!PumpMessage())???? ??
  9. ?????????????????????return?ExitInstance();???? ??
  10. ??? ??
  11. ??????????????//?reset?"no?idle"?state?after?pumping?"normal"?message???????
  12. ??????????????if?(IsIdleMessage(&m_msgCur))???? ??
  13. ??????????????{???? ??
  14. ?????????????????????bIdle?=?TRUE;???? ??
  15. ??? ??
  16. ?????????????????????lIdleCount?=?0;???? ??
  17. ??? ??
  18. ??????????????}???? ??
  19. ???????}?while?(::PeekMessage(&m_msgCur,?NULL,?NULL,?NULL,?PM_NOREMOVE));???? ??
  20. ???????..............略???? ??
  21. }???? ??
  22. ????? ??
  23. BOOL?CWinThread::PumpMessage()???? ??
  24. {?? ??
  25. ???????return?AfxInternalPumpMessage();? ??
  26. }? ??
  27. ??
  28. BOOL?AFXAPI?AfxInternalPumpMessage() ??
  29. { ??
  30. ???????_AFX_THREAD_STATE?*pState?=?AfxGetThreadState(); ??
  31. ??? ??
  32. ???????if?(!::GetMessage(&(pState->m_msgCur),?NULL,?NULL,?NULL))??????? ??
  33. ???????{???? ??
  34. ?????????????.............略???? ??
  35. ???????}???? ??
  36. ???????...............略???? ??
  37. ???????if?(pState->m_msgCur.message?!=?WM_KICKIDLE?&&?!AfxPreTranslateMessage(&(pState->m_msgCur))) ??
  38. ???????{ ??
  39. ???????????? ::TranslateMessage(&(pState->m_msgCur)); ??
  40. ???????????? ::DispatchMessage(&(pState->m_msgCur)); ??
  41. ???????}?? ??
  42. ??? ??
  43. ???????return?TRUE;???? ??
  44. }???? ??

???????我們看到PumpMessage中通過調用GetMessage、TranslateMessage、DispatchMessage等建立了消息循環并投遞消息。

???????窗口過程函數AfxWinProc形式如下:

C++代碼
  1. LRESULT?CALLBACK?AfxWndProc(HWND?hWnd,UINT?nMsg,WPARAM?wParam,?LPARAM?lParam) ??
  2. { ??
  3. ??????…… ??
  4. ??????CWnd*pWnd=CWnd::FromHandlePermanent(hWnd);??
  5. ??????ReturnAfxCallWndProc(pWnd,hWnd,nMsg,wParam,lParam); ??
  6. }??

???????兩者運行過程對比

?????? 到此,通過對比可以發現,MFC應用程序的運行流程與SDK程序是類似的,都是先進行一些初始化過程,再注冊并創建窗口,然后顯示、更新窗口,最后進入消息循環,消息都由窗口過程函數處理。現在大家是不是覺得有些頭緒了?在運行流程上有基本的掌握即可。

???????二.MFC應用程序框架主要類之間的關系

?????? 在第二講中,給大家演示了如何利用應用程序向導生成單文檔應用程序框架,可以看到程序的基本框架和必要的代碼都自動生成了,上一講又講解了文件組成結構,實際上在前面自動生成的框架中比較重要的類包括以下幾個:CHelloWorldApp、CMainFrame、CHelloWorldDoc和CHelloWorldView,至于其他的類比如CClassView、CFileView等都是在框架窗口(CMainFrame)上創建的面板等,不是必要的。

???????雞啄米就四個主要類的關系簡單講下,CHelloWorldApp類處理消息,將收到的消息分發給相應的對象。CMainFrame是視圖CHelloWorldView的父窗口,視圖CHelloWorldView就顯示在CMainFrame的客戶區中。視圖類CHelloWorldView用來顯示文檔類CHelloWorldDoc中的數據,并根據對視圖類的操作修改文檔類的數據。一個視圖類只能跟一個文檔類相聯系,而一個文檔類可以跟多個視圖類相聯系。關于視圖類和文檔類的關系后面會詳細講解。

?????? 本節VC++/MFC編程入門教程內容比較多,主要是讓大家對MFC應用程序的運行原理有大概的了解。對于以后的MFC開發有很多好處。如果有問題請在雞啄米博客留言交流。謝謝。

?

原文地址:http://www.jizhuomi.com/software/145.html

轉載于:https://www.cnblogs.com/wodehao0808/p/6702660.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/283904.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/283904.shtml
英文地址,請注明出處:http://en.pswp.cn/news/283904.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

個人博客開發-開篇

邁出第一步&#xff1a; 很久以前就有這個想法&#xff0c;自己動手開發一套個人博客系統&#xff0c;終于&#xff0c;現在開始邁出了第一步。做這件事一點是做一個有個人風格的博客系統&#xff0c;第二點是對做這件事所使用的技術棧進行學習&#xff0c;所謂最好的學習就是實…

2022年中國中小學教育信息化行業研究報告

教育信息化丨研究報告 核心摘要&#xff1a; 背景篇 目前&#xff0c;我國中小學教育主要呈現信息時代教育的特征&#xff0c;智能時代教育特征初露端倪&#xff1b;中小學教育信息化正從量變邁向質變&#xff0c;創新引領與生態變革成為行業縱深的主旋律&#xff1b; 2021年…

使用curl指令發起websocket請求

昨日的文章沒指出websocket請求協商切換的精髓&#xff0c;刪除重發。前文相關&#xff1a;? .NET WebSockets 核心原理初體驗[1]? SignalR 從開發到生產部署避坑指南[2]tag&#xff1a;瀏覽器--->nginx--> server其中提到nginx默認不會為客戶端轉發Upgrade、Connectio…

Yii 2 的安裝 之 踩坑歷程

由于剛接觸yii2 ,決定先裝個試試&#xff1b;可是這一路安裝差點整吐血&#xff0c;可能還是水平有限吧&#xff0c; 但還是想把這個過程分享出來&#xff0c;讓遇到同樣問題的同學有個小小的參考&#xff0c;好了言歸正傳&#xff01;&#xff01; <(~.~)> 下面是安裝流…

設計模式之代理模式(上) 靜態代理與JDK動態代理

2019獨角獸企業重金招聘Python工程師標準>>> 代理模式 給某一個對象提供一個代理&#xff0c;并由代理對象控制對原對象的引用。靜態代理 靜態代理是由我們編寫好的類&#xff0c;在程序運行之前就已經編譯好的的類&#xff0c;此時就叫靜態代理。 說理論還是比較懵…

mysql 分頁查詢

使用limit函數 limit關鍵字的用法&#xff1a; LIMIT [offset,] rows offset指定要返回的第一行的偏移量&#xff0c;rows第二個指定返回行的最大數目。初始行的偏移量是0(不是1)。轉載于:https://www.cnblogs.com/xping/p/6703986.html

WPF 實現更換主題色

WPF 實現更換主題色WPF 使用 WPFDevelopers.Minimal 如何更換主題色作者&#xff1a;WPFDevelopersOrg原文鏈接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal框架使用大于等于.NET40&#xff1b;Visual Studio 2022;項目使用 MIT 開源許可協議&a…

vue3與vue2的區別

先來說說當下市場開發使用的問題&#xff0c;目前2021年使用vue3開發的企業還是少&#xff0c;基本上都還是以vue2的形式進行開發&#xff0c;vue3的開發模式跟react很像&#xff0c;這時候有人就會想那我學vue3有用么&#xff0c;淦&#xff0c;他喵的&#xff0c;先別激動&am…

Spring Data REST API集成Springfox、Swagger

原文: Documenting a Spring Data REST API with Springfox and Swagger 使用Spring Date REST&#xff0c;你可以迅速為Spring Date repositories的創建REST API&#xff0c;并提供CRUD和更多功能。然而&#xff0c;在嚴謹的API開發過成功&#xff0c;您還希望擁有自動生成的最…

【系統設計】S3 對象存儲

在本文中&#xff0c;我們設計了一個類似于 Amazon Simple Storage Service (S3) 的對象存儲服務。S3 是 Amazon Web Services (AWS) 提供的一項服務&#xff0c; 它通過基于 RESTful API 的接口提供對象存儲。根據亞馬遜的報告&#xff0c;到 2021 年&#xff0c;有超過 100 萬…

轉: telnet命令學習

1.每天一個linux命令&#xff08;58&#xff09;&#xff1a;telnet命令 轉自&#xff1a; http://www.cnblogs.com/peida/archive/2013/03/13/2956992.html telnet命令通常用來遠程登錄。telnet程序是基于TELNET協議的遠程登錄客戶端程序。Telnet協議是TCP/IP協議族中的一員&a…

禪道、碼云、coding、redmine、jira、teambition幾大敏捷開發項目管理系統試用對比體驗

作為一個軟件公司的管理人員&#xff0c;在項目和人員多起來后&#xff0c;就需要通過系統來對項目和人員進行管理。 我們是典型的軟件外包公司&#xff0c;專為客戶定制軟件&#xff0c;所以我們的業務都是項目型的。因此&#xff0c;在管理模式上&#xff0c;我們就要用所謂…

Dubbo中的SPI機制

Dubbo中的SPI機制 概述 Service Provider Interface 即 SPI&#xff0c;是JDK內置的一種服務提供發現機制&#xff0c;可以用來啟用框架擴展和替換組件。可以讓不同的廠商針對統一接口編寫不同的實現 SPI實際上是“接口策略模式配置文件”實現的動態加載機制。在系統設計中&…

JWT:擁有我,即擁有權力

Hi&#xff0c;這里是桑小榆。上篇文章中&#xff0c;我們一起探討了 OAuth 協議的原理以及授權認證流程&#xff0c;本次我們一起探討 jwt 令牌作為授權協議的傳輸介質。OAuth協議規范了幾個參與角色的授權標準&#xff0c;安全可控的授予第三方應用&#xff0c;第三方應用獲取…

雙十一到來之前,阿里AI設計師“魯班”1天能做4000萬張海報

相比較去年&#xff0c;“魯班”的設計技藝有所提升。 人工智能很大程度上便利了我們的生活&#xff0c;現在他們甚至還能取代了一些設計師的工作&#xff0c;在雙十一正式到來之前&#xff0c;淘寶的宣傳已經鋪天蓋地&#xff0c;然而很多人都沒想到&#xff0c;我們打開淘寶…

Appium移動自動化測試之獲取appPackage和appActivity

方法一&#xff1a;直接打開Appium,點擊左上角機器人圖標 選擇apk所在位置&#xff0c;如圖所示&#xff0c;這里以ContactManager.apk為例 方法二&#xff1a;利用dex2jar和jd-gui這兩個工具反編譯apk文件 這里仍以ContactManager.apk為例 (1)重命名ContactManager.apk為Conta…

CAD轉WPF: 關于CAD圖紙文件轉換為WPF矢量代碼文件(xaml文件)的技巧

前言&#xff1a;下面的文章&#xff0c;我將會以幾個很簡單的步驟&#xff0c;來演示一下通過CAD圖紙轉換為XAML代碼文件的方法&#xff0c;供大佬們參考。一、為了演示一個簡單的操作&#xff0c;我此處先打開一個空白的CAD&#xff0c;等下用來進行繪制點內容使用。二、自定…

python之新式類與經典類

經典類與新式類經典類:P 或 P()--深度查找&#xff0c;向上查父節點新式類 :P(object)---廣度查找&#xff0c;繼承object&#xff0c;新式類的方法較多轉載于:https://www.cnblogs.com/zyy98877/p/8574983.html

Flowportal-BPM——環境配置

環境配置&#xff1a; 一、控制面板→程序和功能→打開或不關閉Window功能→選擇選項 二、控制面板→管理工具→Internet信息服務&#xff08;IIS&#xff09;管理器→左側第一個→ISAPI和CGI限制→全部選為【允許】 三、控制面板→管理工具→Internet信息服務&#xff08;IIS&…