第三课——MFC编程
一、MFC概述
1. MFC簡述
MFC不僅僅是一套基礎類庫,更是一種編程方式。
2. MFC由來
1987年微軟公司推出了第一代Windows產品,并為應用程序設計者提供了Win16(16位Windows操作系統)API,在此基礎上推出了Windows GUI(圖形用戶界面),然后采用面向對象技術對API進行封裝。
1992年推出應用程序框架產品AFX(Application Frameworks),并在AFX的基礎上進一步發展為MFC產品。故在用MFC應用程序向導創建的程序中仍然保留stdafx.h頭文件包含,它是每個應用程序所必有的預編譯頭文件,程序所用到的Visual C++頭文件包含語句一般均添加到這個文件中。
3. MFC類的基本層次結構
圖示:
? ? ? ?
CObject類是MFC提供的絕大多數類的基類。該類完成動態空間的分配與回收,支持一般的診斷、出錯信息處理和文檔序列化等。
CCmdTarget類主要負責將系統事件(消息)和窗口事件(消息)發送給響應這些事件的對象,完成消息發送、等待和派遣(調度)等工作,實現應用程序的對象之間協調運行。
CWinApp類是應用程序的主線程類,它是從CWinThread類派生而來。CWinThread類用來完成對線程的控制,包括線程的創建、運行、終止和掛起等。
CDocument類是文檔類,包含了應用程序在運行期間所用到的數據。
CWnd類是一個通用的窗口類,用來提供Windows 中的所有通用特性、對話框和控件。
CFrameWnd 類是從 CWnd 繼承來的,并實現了標準的框架應用程序。
CDialog 類用來控制對話框窗口。
CView 是用于讓用戶通過窗口來訪問文檔以及負責文檔內容的顯示。
CMDIFrameWnd和CMDIChildWnd類分別用來多文檔應用程序的主框架窗口和文檔子窗口的顯示和管理。
CMiniFrameWnd類是一種簡化的框架窗口,它沒有最大化和最小化窗口按鈕,也沒有窗口系統菜單,一般很少用到它。
4. MFC的優勢
讀到本文最后,可得出如下結論:使用MFC
①可減少Windows應用程序的代碼量;
②通過消息映射機制使消息處理更為方便;
③能很好地體現面向對象編程的優點。
?
二、MFC程序框架
——寫在理解MFC機制之前
下面是一個MFC應用程序:
#include <afxwin.h> // MFC頭文件 class CHelloApp : public CWinApp // 聲明應用程序類 { public: virtual BOOL InitInstance(); }; CHelloApp theApp; // 建立應用程序類的實例 class CMainFrame: public CFrameWnd // 聲明主窗口類 { public:CMainFrame(){ // 創建主窗口Create(NULL, "我的窗口", WS_OVERLAPPEDWINDOW, CRect(0, 0, 480, 320));} protected:afx_msg void OnPaint();DECLARE_MESSAGE_MAP() }; // 消息映射入口 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)ON_WM_PAINT() // 繪制消息宏 END_MESSAGE_MAP()//定義消息映射函數 void CMainFrame::OnPaint() {CPaintDC dc(this);CRect rc;GetClientRect(&rc);dc.DrawText(_T("Hello MFC!"), -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER); } // 每當應用程序首次執行時都要調用的初始化函數 BOOL CHelloApp::InitInstance() {m_pMainWnd = new CMainFrame();m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();return TRUE; }?
三、程序運行機制
0. 上面程序中的關系梳理
- 應用程序類:CHelloApp(公有繼承自CWinApp)
- 應用程序類的實例:theApp
- 主窗口類:CMainFrame(公有繼承自CFrameWnd)
1. MFC使用afxwin.h來代替頭文件windows.h,在此程序中看不到Windows應用程序所必須的入口函數WinMain,這是因為MFC將它隱藏在應用程序框架內部了。
2. 當用戶運行應用程序時,Windows會自動調用應用程序框架內部的WinMain函數,并自動查找應用程序類CHelloApp(從CWinApp派生)的全局變量theApp,然后自動調用CHelloApp的虛函數InitInstance,該函數會進一步調用相應的函數來完成主窗口的構造和顯示工作。
- 重點:運行應用程序→WinMain+theApp→InitInstance(Create/ShowWindow/UpdateWindow)
3. 上面程序中InitInstance的執行過程(創建窗口+顯示窗口+更新窗口)如下:
① m_pMainWnd = new CMainFrame();
該語句的作用:創建從CFrameWnd類派生而來的用戶框架窗口CMainFrame類對象,繼而調用該類的構造函數,使得Create函數被調用,完成窗口創建工作。
②?m_pMainWnd->ShowWindow(m_nCmdShow);
? ??m_pMainWnd->UpdateWindow();
此兩條語句的作用:用作窗口的顯示和更新
③ 返回TRUE,表示窗口創建成功
4. InitInstance完成初始化工作之后,接下來就是調用CWinApp的成員函數Run,執行應用程序的消息循環,即重復執行接收消息并轉發消息的工作。
筆記:InitInstance之后是Run,Run是用來處理消息的。
當Run檢查到消息隊列為空時,將調用基類CWinApp的成員函數OnIdle進行空閑時的后臺處理工作。若消息隊列為空且又沒有后臺工作要處理時,則應用程序一直處于等待狀態,一直等到有消息為止。
5. 當程序結束后,調用基類CWinApp的成員函數ExitInstance,完成終止應用程序的收尾工作。
6. 尚待考究:既然MFC方式使用消息映射機制,那為何還要使用Run來處理消息?
?
四、消息映射
1. 區別于之前的消息處理機制
在MFC中,不再使用消息循環代碼以及在窗口過程函數中的switch結構來處理Win32的消息,而是使用獨特的消息映射機制。
2. 何為消息映射
所謂消息映射(Message Map)機制,就是將MFC類中的消息與消息處理函數一一對應起來的機制。
在MFC中,任何一個從CCmdTarget派生的類理論上均可處理消息,且都有相應的消息映射函數。(即每個類都有相應的消息映射函數)
3. 映射一個消息的過程
① 在處理消息的類中,使用消息宏DECLARE_MESSAGE_MAP()聲明對消息映射的支持,并在該宏之前聲明消息處理函數。
舉例:
protected:afx_msg void OnPaint();DECLARE_MESSAGE_MAP()② 使用BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏在類聲明之后的地方定義該類支持的消息映射入口點,所有消息映射宏都添加在這里,當然不同的消息MFC都會有不同的消息映射宏。
舉例:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)... END_MESSAGE_MAP()其中,BEGIN_MESSAGE_MAP帶有兩個參數。第一個參數:用來指定需要支持消息映射的用戶派生類;第二個參數:指定該類的基類。
③ 定義消息處理函數(此例中OnPaint為消息處理函數)
void CMainFrame::OnPaint() {CPaintDC dc(this);CRect rc;GetClientRect(&rc);dc.DrawText(_T("Hello MFC!"), -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER); }注意:為了使該消息能被其他對象接收并處理,在函數中常常需要調用基類中的相關消息處理函數。
?
補充:
應用程序類:繼承自CWinApp類
消息映射機制:將消息與消息處理函數相對應的機制
消息宏:DECLARE_MESSAGE_MAP(),使用它聲明對消息映射的支持
消息映射入口點:由BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏在類聲明之后定義入口點,而所有消息映射宏都添加在此
消息映射宏:不同的消息MFC都有不同的消息映射宏,如ON_WM_PAINT
消息處理函數:如OnPaint,該函數的聲明必須在消息宏之前
?
彩蛋:
在Visual C++ 6.0中不需要輸入上述程序代碼(其實不需要輸入任何代碼),就能創建所需要的應用程序!!
這就是MFC應用程序向導(MFC AppWizard)的功能。
上面只是拓寬你的視野!!!
具體MFC對應用程序項目的管理方式見下一課。
轉載于:https://www.cnblogs.com/xzxl/p/7929086.html
總結
以上是生活随笔為你收集整理的第三课——MFC编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 外观、体验升级 HUAWEI WATC
- 下一篇: Spring的两种属性注入方式