日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

VS2010/MFC编程入门之四(MFC应用程序框架分析)

發(fā)布時(shí)間:2023/12/18 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 VS2010/MFC编程入门之四(MFC应用程序框架分析) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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

?????? 一.SDK應(yīng)用程序與MFC應(yīng)用程序運(yùn)行過程的對比

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

?????? SDK應(yīng)用程序

?????? 首先,給出Windows SDK應(yīng)用程序“HelloWorld”的源碼:??

C++代碼

  • #include?<windows.h>? ??
  • ??
  • LRESULT?CALLBACK?myWndProc(HWND?hWindow,?UINT?msg,?WPARAM?wParam,?LPARAM?lParam); ??
  • ?? ??
  • int?WINAPI?WinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,?PSTR?szCmdLine,?int?iCmdShow)??? ??
  • {??? ??
  • ??const?static?TCHAR?appName[]?=?TEXT("Hello?world");??? ??
  • ??WNDCLASSEX?myWin;??? ??
  • ??myWin.cbSize?=?sizeof(myWin);??? ??
  • ??myWin.style?=?CS_HREDRAW?|?CS_VREDRAW;??? ??
  • ??myWin.lpfnWndProc?=?myWndProc;??? ??
  • ??myWin.cbClsExtra?=?0;??? ??
  • ??myWin.cbWndExtra?=?0;??? ??
  • ??myWin.hInstance?=?hInstance;??? ??
  • ??myWin.hIcon?=?0;??? ??
  • ??myWin.hIconSm??=?0;??? ??
  • ??myWin.hCursor?=?0;??? ??
  • ??myWin.hbrBackground?=?(HBRUSH)(COLOR_WINDOW?+?1);??? ??
  • ??myWin.lpszMenuName?=?0;??? ??
  • ??myWin.lpszClassName?=?appName;??? ??
  • ??//Register??? ??
  • ??if?(!RegisterClassEx(&myWin))?return?0;??? ??
  • ??const?HWND?hWindow?=?CreateWindow(??? ??
  • ????appName,??? ??
  • ????appName,??? ??
  • ????WS_OVERLAPPEDWINDOW,??? ??
  • ????CW_USEDEFAULT,??? ??
  • ????CW_USEDEFAULT,??? ??
  • ????CW_USEDEFAULT,??? ??
  • ????CW_USEDEFAULT,??? ??
  • ????0,??? ??
  • ????0,??? ??
  • ????hInstance,??? ??
  • ????0);??? ??
  • ??ShowWindow(hWindow,iCmdShow);??? ??
  • ??UpdateWindow(hWindow);??? ??
  • ??{??? ??
  • ????MSG?msg;??? ??
  • ????while(GetMessage(&msg,0,0,0))??? ??
  • ????{??? ??
  • ??????TranslateMessage(&msg);??? ??
  • ??????DispatchMessage(&msg);??? ??
  • ????}??? ??
  • ????return?(int)msg.wParam;??? ??
  • ??}??? ??
  • }??? ??
  • ?? ??
  • LRESULT?CALLBACK?myWndProc(HWND?hWindow,?UINT?msg,?WPARAM?wParam,?LPARAM?lParam)??? ??
  • {??? ??
  • ??if?(msg==WM_PAINT)??? ??
  • ??{??? ??
  • ????PAINTSTRUCT?ps;??? ??
  • ????const?HDC?hDC?=?BeginPaint(hWindow,&ps);??? ??
  • ????RECT?rect;??? ??
  • ????GetClientRect(hWindow,&rect);??? ??
  • ????DrawText(hDC,TEXT("HELLO?WORLD"),-1,&rect,?DT_SINGLELINE?|?DT_CENTER?|?DT_VCENTER);??? ??
  • ????EndPaint(hWindow,&ps);??? ??
  • ????return?0;??? ??
  • ??}??? ??
  • ??else?if?(msg==WM_DESTROY)??? ??
  • ??{??? ??
  • ????PostQuitMessage(0);??? ??
  • ????return?0;??? ??
  • ??}??? ??
  • ??return?DefWindowProc(hWindow,msg,wParam,lParam);??? ??
  • }??
  • ???????上面的程序運(yùn)行的流程是:進(jìn)入WinMain函數(shù)->初始化WNDCLASSEX,調(diào)用RegisterClassEx函數(shù)注冊窗口類->調(diào)用ShowWindow和UpdateWindow函數(shù)顯示并更新窗口->進(jìn)入消息循環(huán)。關(guān)于消息循環(huán)再簡單說下,Windows應(yīng)用程序是消息驅(qū)動的,系統(tǒng)或用戶讓應(yīng)用程序進(jìn)行某項(xiàng)操作或完成某個(gè)任務(wù)時(shí)會發(fā)送消息,進(jìn)入程序的消息隊(duì)列,然后消息循環(huán)會將消息隊(duì)列中的消息取出,交予相應(yīng)的窗口過程處理,此程序的窗口過程函數(shù)就是myWndProc函數(shù),窗口過程函數(shù)處理完消息就完成了某項(xiàng)操作或任務(wù)。本例是要顯示“HELLO WORLD”字符串,UpdateWindow函數(shù)會發(fā)送WM_PAINT消息,但是此消息不經(jīng)過消息隊(duì)列而是直接送到窗口過程處理,在窗口過程函數(shù)中最終繪制了“HELLO WORLD”字符串。

    ?????? MFC應(yīng)用程序

    ?????? 下面是MFC應(yīng)用程序的運(yùn)行流程,通過MFC庫中代碼進(jìn)行分析:

    ?????? 首先在HelloWorld.cpp中定義全局對象theApp:CHelloWorldApp theApp;。調(diào)用CWinApp和CHelloWorldApp的構(gòu)造函數(shù)后,進(jìn)入WinMain函數(shù)(位于appmodul.cpp中)。

    C++代碼

  • extern?"C"?int?WINAPI ??
  • _tWinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance, ??
  • ????_In_?LPTSTR?lpCmdLine,?int?nCmdShow) ??
  • #pragma?warning(suppress:?4985) ??
  • { ??
  • ????//?call?shared/exported?WinMain ??
  • ????return?AfxWinMain(hInstance,?hPrevInstance,?lpCmdLine,?nCmdShow); ??
  • }??
  • ???????在TCHAR.h中,有此定義:#define _tWinMain?? WinMain,所以這里的_tWinMain就是WinMain函數(shù)。它調(diào)用了AfxWinMain函數(shù)(位于WinMain.cpp中)。

    C++代碼

  • int?AFXAPI?AfxWinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,LPTSTR?lpCmdLine,?int?nCmdShow) ??
  • {? ??
  • ???????.............略 ??
  • ???????//?App?global?initializations?(rare) ??
  • ???????if?(pApp?!=?NULL?&&?!pApp->InitApplication()) ??
  • ??????????????goto?InitFailure; ??
  • ??
  • ???????if?(!pThread->InitInstance()) ??
  • ???????{ ??
  • ??????????????.........略 ??
  • ???????} ??
  • ??
  • ???????// Run函數(shù)位于THRDCORE.cpp中,由此函數(shù)進(jìn)入消息循環(huán) ??
  • ???????nReturnCode?=?pThread->Run(); ??
  • ??
  • ???????..............略 ??
  • ??
  • ???????return?nReturnCode; ??
  • } ??
  • ?????? 上面InitInstance函數(shù)的代碼如下:

    C++代碼

  • BOOL?CTestApp::InitInstance()????? ??
  • {???? ??
  • ???????.............略???? ??
  • ???????CSingleDocTemplate*?pDocTemplate;???? ??
  • ???????pDocTemplate?=?new?CSingleDocTemplate(???? ??
  • ??????????????IDR_MAINFRAME,???? ??
  • ??????????????RUNTIME_CLASS(CTestDoc),???? ??
  • ??????????????RUNTIME_CLASS(CMainFrame),??????//?main?SDI?frame?window???? ??
  • ??????????????RUNTIME_CLASS(CTestView));?? ??
  • ???????if?(!pDocTemplate) ??
  • ???????????? return?FALSE;?? ??
  • ???????AddDocTemplate(pDocTemplate);???? ??
  • ???????//?Parse?command?line?for?standard?shell?commands,?DDE,?file?open???? ??
  • ??? ??
  • ???????CCommandLineInfo?cmdInfo;???? ??
  • ???????ParseCommandLine(cmdInfo);???? ??
  • ??? ??
  • ???????//ProcessShellCommand位于AppUI2.cpp中,注冊并創(chuàng)建窗口???? ??
  • ???????if?(!ProcessShellCommand(cmdInfo))???? ??
  • ?????????????return?FALSE;???? ??
  • ??? ??
  • ???????m_pMainWnd->ShowWindow(SW_SHOW);???? ??
  • ???????m_pMainWnd->UpdateWindow();???? ??
  • ??? ??
  • ???????return?TRUE;???? ??
  • }??? ??
  • ???????InitInstance中的ProcessShellCommand函數(shù)又調(diào)用了CMainFrame的LoadFrame函數(shù)注冊并創(chuàng)建了窗口,執(zhí)行完P(guān)rocessShellCommand函數(shù)以后,調(diào)用了m_pMainWnd的ShowWindow和UpdateWindow函數(shù)顯示并更新框架窗口。這些是不是與上面的SDK程序十分類似?

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

    C++代碼

  • int?CWinThread::Run()???? ??
  • {???? ??
  • ????????.............略???? ??
  • ????????//?phase2:?pump?messages?while?available???? ??
  • ????????do??? ??
  • ????????{???? ??
  • ??????????????//?pump?message,?but?quit?on?WM_QUIT???? ??
  • ??????????????if?(!PumpMessage())???? ??
  • ?????????????????????return?ExitInstance();???? ??
  • ??? ??
  • ??????????????//?reset?"no?idle"?state?after?pumping?"normal"?message???? ??
  • ??????????????if?(IsIdleMessage(&m_msgCur))???? ??
  • ??????????????{???? ??
  • ?????????????????????bIdle?=?TRUE;???? ??
  • ??? ??
  • ?????????????????????lIdleCount?=?0;???? ??
  • ??? ??
  • ??????????????}???? ??
  • ???????}?while?(::PeekMessage(&m_msgCur,?NULL,?NULL,?NULL,?PM_NOREMOVE));???? ??
  • ???????..............略???? ??
  • }???? ??
  • ????? ??
  • BOOL?CWinThread::PumpMessage()???? ??
  • {?? ??
  • ???????return?AfxInternalPumpMessage();? ??
  • }? ??
  • ??
  • BOOL?AFXAPI?AfxInternalPumpMessage() ??
  • { ??
  • ???????_AFX_THREAD_STATE?*pState?=?AfxGetThreadState(); ??
  • ??? ??
  • ???????if?(!::GetMessage(&(pState->m_msgCur),?NULL,?NULL,?NULL))??????? ??
  • ???????{???? ??
  • ?????????????.............略???? ??
  • ???????}???? ??
  • ???????...............略???? ??
  • ???????if?(pState->m_msgCur.message?!=?WM_KICKIDLE?&&?!AfxPreTranslateMessage(&(pState->m_msgCur))) ??
  • ???????{ ??
  • ???????????? ::TranslateMessage(&(pState->m_msgCur)); ??
  • ???????????? ::DispatchMessage(&(pState->m_msgCur)); ??
  • ???????}?? ??
  • ??? ??
  • ???????return?TRUE;???? ??
  • }???? ??
  • ???????我們看到PumpMessage中通過調(diào)用GetMessage、TranslateMessage、DispatchMessage等建立了消息循環(huán)并投遞消息。

    ???????窗口過程函數(shù)AfxWinProc形式如下:

    C++代碼

  • LRESULT?CALLBACK?AfxWndProc(HWND?hWnd,UINT?nMsg,WPARAM?wParam,?LPARAM?lParam) ??
  • { ??
  • ??????…… ??
  • ??????CWnd*pWnd=CWnd::FromHandlePermanent(hWnd);??
  • ??????ReturnAfxCallWndProc(pWnd,hWnd,nMsg,wParam,lParam); ??
  • }??
  • ?????? 兩者運(yùn)行過程對比

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

    ?????? 二.MFC應(yīng)用程序框架主要類之間的關(guān)系

    ?????? 在第二講中,給大家演示了如何利用應(yīng)用程序向?qū)蓡挝臋n應(yīng)用程序框架,可以看到程序的基本框架和必要的代碼都自動生成了,上一講又講解了文件組成結(jié)構(gòu),實(shí)際上在前面自動生成的框架中比較重要的類包括以下幾個(gè):CHelloWorldApp、CMainFrame、CHelloWorldDoc和CHelloWorldView,至于其他的類比如CClassView、CFileView等都是在框架窗口(CMainFrame)上創(chuàng)建的面板等,不是必要的。

    ???????雞啄米就四個(gè)主要類的關(guān)系簡單講下,CHelloWorldApp類處理消息,將收到的消息分發(fā)給相應(yīng)的對象。CMainFrame是視圖CHelloWorldView的父窗口,視圖CHelloWorldView就顯示在CMainFrame的客戶區(qū)中。視圖類CHelloWorldView用來顯示文檔類CHelloWorldDoc中的數(shù)據(jù),并根據(jù)對視圖類的操作修改文檔類的數(shù)據(jù)。一個(gè)視圖類只能跟一個(gè)文檔類相聯(lián)系,而一個(gè)文檔類可以跟多個(gè)視圖類相聯(lián)系。關(guān)于視圖類和文檔類的關(guān)系后面會詳細(xì)講解。

    ?????? 本節(jié)VC++/MFC編程入門教程內(nèi)容比較多,主要是讓大家對MFC應(yīng)用程序的運(yùn)行原理有大概的了解。對于以后的MFC開發(fā)有很多好處。如果有問題請?jiān)陔u啄米博客留言交流。謝謝。

    總結(jié)

    以上是生活随笔為你收集整理的VS2010/MFC编程入门之四(MFC应用程序框架分析)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。