第三篇:消息映射和視圖類
在寫了兩篇筆記後有很多朋友給我發信,和我交流一些在學習過程中的問題。但由於我也是一個初學者,對一些問題自己也沒有把握,所以實在不敢做答,但我會盡量盡我所能和大家一起研究,謝謝大家的鼓勵和信任。
在開始先補充一下上一篇的內容“內容窗口的創建”,兼答天歌網友的問題(如果天歌兄弟能看到的話 )。為了簡化我們看一個更簡單代碼,只有一個文件,創建一個空白的窗口,什麼也不做。注意哦:真寫程序時還是要分成.h和.cpp兩個文件比較清晰。
前幾步和『VC++技術內幕』學習筆記(2)中的一樣,下面是代碼:
//**********************************
// MyApp.cpp
#include "afxwin.h" //afxwin.h會調用windows.h是MFC編程的途徑,只要用到MFC就一定要包含它。
class CMyApp:public CWinApp //從CWinApp繼承一個類
{
public:
virtual BOOL InitInstance();//重載InitInstance虛函數
};
class CMyFrame:public CFrameWnd //從CFrameWnd繼承一個類
{};
CMyApp myApp; //最後又激活應用程序的構造函數
BOOL CMyApp::InitInstance ()
{
m_pMainWnd=new CMyFrame;
//new 激活了CMyFrame類構造函數CFrameWnd(),構造函數調又用CREATE()
//m_pMainWnd在MFC的定義CWnd* m_pMainWnd;// main window (usually same AfxGetApp()->m_pMainWnd)
//m_pMainWnd保存窗口的位置
((CMyFrame * )m_pMainWnd)->Create(NULL,"一個MFC應用程序:空白窗口"); //創建窗口
m_pMainWnd->ShowWindow(m_nCmdShow); //顯示在屏幕上
return TRUE;
}
如果還不明白建議查看MSDN或看看侯大師的深入淺出。關於這個問題就說到這,最後對天歌朋友的學習態度表示敬意。
下面進入正體,讓我們繼續來看看MFC的消息映射。
MFC是通過一些宏來將特定的消息影射到派生類相應的成員函數上,這種體制的好處是允許某些非窗口類(如文檔類)來控制命令消息。且不需要C++作任何擴展。
MFC的消息控制函數要求提供函數原形、函數體以及消息映射中的入口。真的很麻煩,還好用Class Wizard可以很容易的將上面說到的東西加到我們的類中。例如只要在Class Wizard中添加WM_LBUTTONDOWN消息,則相應的代碼便加在合適的地方。怎麼樣簡單多了吧。
應用程序除了包含應用程序框架類外,一般還要包含文檔和視圖類。這種文檔-視圖結構是應用框架的核心。我一直做MIS開發,當然不是用VC用的是VB,所以看到這我很不自覺的想到了後台數據庫和界面的關系,這個例子可能不是很恰當,但卻能很好的幫助我們理解文檔和視圖。文檔好比後台的數據庫,視圖就是界面上顯示的內容,同一個數據庫可以用不同的界面顯示,但由於所有的界面內容都是從數據庫中數據得來,所以當數據庫發生變化時所有的相關界面顯示都會跟著改變。越來越覺得不恰當,不過實在想不出別的例子了。我們的應用程序實際上就是通過視圖對文檔進行一系列操作,不單指輸出。下面我們看看視圖類。
視圖是一個從CView類派生的類的對象,在屏幕上顯示的窗口就是一種。對象的行為完全由類的成員函數和數據成員決定,其中及包括派生類中的特定函數,也包括基類的標准函數,所以了解MFC類庫的結構以及各類的標准成員函數是多麼重要啊,別怕麻煩找來MFC的源碼讀讀,看多少算多少,但肯定不白看,這是雷神的經驗。
記得上一篇的我的例子嗎
1、打開VC++6從菜單選擇NEW,給項目命名為”MyApp01“。
2、選擇MFC AppWizard[exe] 選項,除STEP 1選擇單文檔外其他STEP缺省。
此時MFC應用程序框架便幫我們完成了應用程序,你可以執行它,它會在屏幕上顯示一個典型的WINDOWS風格的空白窗口。
我們來看一下項目程序所在目錄下的文件:
myapp01.dsp //項目文件
myapp01.dsw //工作空間文件
myapp01.rc //資源描述文件
myapp01View.cpp //包含CMyAppView類成員函數的視圖類實現文件 重點
myapp01View.h //包含CMyAppView類成員函數的視圖類頭文件 重點
myapp01.opt //二進制文件,告訴Developer Studio本項目的哪些文件是打開的,又是如何排列的
readme.txt //用來解釋所產生的所有文件,未列出的myapp01Doc.cpp、myapp01Doc.h、StdAfx.cpp、StdAfx.h....在這裡都可以找到相應解釋。
resource.h //包含#define常量定義的頭文件
仔細研究一下myapp01View.cpp和myapp01View.h文件,程序核心CMyAppView類在這兩個文件中定義,就是我們今天要學的視圖類。要想看到CMyAppView類的全貌,應該用Source Browser查看,選擇CMyApp01View,按Alt+F12,選擇Base Class and Members 選項。我們會看到CMyAppView類的層次關系(從哪來得),以及所有成員函數,包括從基類繼承的(在Class View中不能顯示父類的成員函數)。我們發現實際上你什麼也不用做就擁有了一個有著強大功能的類。
下面我們看一下CMyAppView類的OnDraw成員函數,它是虛函數作用是每當窗口需重繪時應用程序框架會調用它。它的原型是這樣的(在myapp01View.h可以找到)
virtual void OnDraw(CDC* pDC); // overridden to draw this view
參數是CDC類的指針,WINDOWS是通過和窗口相關聯的設備環境(CDC類的對象就是設備環境)和顯示硬件進行通訊。有了這個指針我們便可以調用CDC類的成員函數來完成各種繪制工作,如上一篇用到的textout()還有一些Ellipse()、Polygon()、BitBlt()等等在MSDN中有好長的一篇,它是直接從CObject派生的,好了我們開始在OnDraw()裡添加一些繪圖工作。
3、在Class View選擇CMyApp01View類的OnDraw()成員函數雙擊會在C++編譯器看到以下內容
void CMyApp01View::OnDraw(CDC* pDC)
{
CMyApp01Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
在 // TODO: add draw code for native data here的位置增加一行代碼
void CMyApp01View::OnDraw(CDC* pDC)
{
CMyApp01Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDC->TextOut(10,10,"雷神願意和所有學VC的朋友共同進步!");
pDC->SelectStockObject (DKGRAY_BRUSH); //選擇刷子
pDC->Ellipse (CRect(20,40,120,140)); //畫圓,CRect是MFC庫提供的一個表示WINDOWS矩形類
pDC->Rectangle (CRect(220,240,120,140)); //畫矩形
// TODO: add draw code for native data here
}
編譯運行,成功了吧。先到這吧。另外以後的文章將同時貼在寫作區。