CView

CView是視圖程式設計中使用率最高的視窗對象,它是用戶的主要操作界面。因為它通常以某種形式表示文檔數據,所以稱之為視圖。一個視圖對象只關聯一個文檔對象;一個文檔對象可以關聯多個視圖,每個視圖對象以不同形式表示文檔數據。

基本介紹

  • 中文名:CView
  • 關聯對象WM_CREATE
  • 保存:文檔類將修改後保存到磁碟檔案
  • 接受:用戶對文檔中數據的編輯和修改
介紹,關聯對象,視圖繪製,虛函式,派生類,

介紹

從文檔類中將文檔中的數據取出後顯示給用戶;接受用戶對文檔中數據的編輯和修改;將修改的結果反饋給文檔類,由文檔類將修改後的內容保存到磁碟檔案中。
文檔負責了數據真正在永久介質中的存儲和讀取工作,視圖呈現只是將文檔中的數據以某種形式向用戶呈現,因此一個文檔可對應多個視圖。
Invalidate(TRUE)將整個視窗設定為需要重繪的無效區域,它會產生WM_PAINT訊息,這樣OnDraw將被調用。
假如文檔中的數據發生了變化,必須通知所有連結到該文檔的視圖,這時候文檔類的UpdateAllView函式需要被調用。
然而,除了列印和列印預覽外,視圖類顯示得很簡單。

關聯對象

前面已經提到,視圖需要表示文檔數據,所以文檔對象與視圖對象必須建立關聯。這樣,當文檔數據發生變化時,它可以及時通知視圖;當視圖需要顯示不同的文檔數據時,它可以從文檔對象中提取。
在文檔/視圖框架程式中,文檔對象總是在視圖之前建立,而在視圖的WM_CREATE訊息處理函式中,建立了它與文檔對象的關聯。代碼如下:
IntCView::OnCreate(LPCREATESTRUCTlpcs){if(CWnd::OnCreate(lpcs)==-1)return-1;//m_pDocuemnt視圖成員,用於存儲相應文檔對象的指針,此時為空ASSERT(m_pDocument==NULL);CCreateContext*pContext=(CCreateContext*)lpcs->lpCreateParams;//pContext->m_pCurrentDoc是已經建立的文檔對象的指針if(pContext!=NULL&&pContext->m_pCurrentDoc!=NULL){//將當前視圖加入文檔對象的視圖列表中,因為一個文檔可關聯多個視圖pContext->m_pCurrentDoc->AddView(this);/*在文檔的AddView()函式中,已經將當前文檔對象指針賦給m_pDocument視圖成員。這樣,在視圖建立之初,二者就建立了關聯。*/ASSERT(m_pDocument!=NULL);}else{TRACE(“Warning:CreatingapanewithnoCDocument.\n”);}return0;//ok}
同時,視圖類定義了成員函式GetDocument(),返回文檔對象的指針。代碼如下:
CDocument*CView::GetDocument()const{ASSERT(this!=NULL);returnm_pDocument;}
視圖總是在文檔對象之前銷毀,在視圖的析構函式中,與文檔對象解除關聯。代碼如下:
CView::~CView(){if(m_pDocument!=NULL)m_pDocument->RemoveView(this);}

視圖繪製

視窗的繪製工作總是在WM_PAINT訊息處理中進行的,當視窗需要繪製時,它會收到系統發來的WM_PAINT訊息。在繪製過程中,首先要準備顯示設備句柄,最後要釋放句柄。眾所周知,在視圖視窗中繪製,無需重載WM_PAINT訊息處理函式OnPaint(),因為有一個更加友好的繪製新口:OnDraw()。該函式的實參是一個已經準備好的顯示設備,最後無需釋放。其實,這一切還是WM_PAINT訊息處理函式OnPaint()為我們準備的,代碼如下:
voidCView::OnPaint(){//CPaintDC類維護顯示設備CPaintDCdc(this);OnPrepareDC(&dc);OnDraw(&dc);}
OnPrepareDC()是一個虛擬函式,它總是在OnDraw()之前執行,可以重載它,設定繪圖模式。因為OnDraw()每次執行,都使用不同的CPaintDC對象,所以本次繪圖模式的狀態不能保留到下一次。
OnDraw()在視圖基類CView中定義為純虛函式。例如:
virtualvoidOnDraw(CDC*pDC)=0;
所以CView是抽象基類,不能實例化,而派生類必須重載OnDraw()。

虛函式

OnUpdate
當文檔數據發生變化時,文檔對象調用CDocument::UpdateAllView()通知所有視圖,作為回響,視圖的OnUpdate()成員被調用。所以,重載的OnUpdate()應該能夠根據需要,將文檔數據的變化反映在視圖中。CView::OnUpdate()只是簡單地使客戶區無效,導致客戶區重畫。例如:
voidCView::OnUpdate(CView*pSender,LPARAM,CObject*){ASSERT(pSender!=this);UNUSED(pSender);//unusedinreleasebuildsInvalidate(TRUE);}
OnInitialUpdate()
在初始創建、調用OnCreate()之後,或者在File/New、File/Open命令後被框架調用。基類CView::OnInitialUpdate()只是簡單地調用OnUpdate(),可以重載它完成初始化工作。但注意,它可能被多次調用。
voidCView::OnInitialUpdate(){OnUpdate(NULL,0,NULL);}CalcWindowRect
每當主框架視窗的客戶區尺寸發生變化或控制條的位置發生變化,需要重新排列客戶區時,調用該函式,根據視圖客戶區尺寸計算視圖視窗的尺寸。
我們知道,排列主視窗客戶區是由CFrameWnd::RecalcLayout()完成的。顯然,視圖的CalcWindowRect()函式也是由它觸發調用的。主視窗的客戶區尺寸減掉所有控制占用的部分,剩下的區域分給視圖,這部分區域作為實參傳入CalcWindowRect()。在CalcWindowRect()函式內,需要計算視圖視窗的尺寸。代碼如下:
voidCView::CalcWindowRect(LPRECTlpClientRect,UNITnAdjustType){//lpClientRect此時是整個視圖客戶區的尺寸//需要為滾動條增加尺寸嗎if(nAdjustType!=0){//調用API,根據視窗風格計算視窗尺寸::AdjustWindowRectEx(lpClientRect,0,FALSE,GetExStyle());DWORDdwStyle=GetStyle();if(dwStyle&WS_VSCROLL){//為垂直滾動條增加尺寸//afxData在.NET下需要#include<../../src/mfc/afximpl.h>//afxData在VC6.0下需要#include<../src/mfc/afximpl.h>intnAdjust=afxData.cxVScroll;if(dwStyle&WS_BORDER)nAdjust-=CX_BORDER;lpClientRect->right+=nAdjust;}if(dwStyle&WS_HSCROLL){//為水平滾動條增加尺寸intnAdjust=afxData.cyHScroll;if(dwStyle&WS_BORDER)nAdjust-=CY_BORDER;lpClientRect->bottom+=nAdjust;}return;}//無需為滾動條增加尺寸,調用基類成員完成計算CWnd::CalcWindowRect(lpClientRect,nAdjustType);}
PostNcDestroy
在視圖視窗關閉時最後調用的成員函式,它與CFrameWnd::PostNcDestroy完成相同的功能,即刪除視圖對象。代碼如下:
voidCView::PostNcDestroy(){deletethis;}
這樣,可以不必關心視圖的釋放工作,即使它在堆中構造。
OnCmdMsg
在討論CFrameWnd::OnCmdMsg()時已經了解過該函式,下面只給出它的代碼:
BOOLCView::OnCmdMsg(UINTnID,intnCode,void*pExtra,AFX_CMDHANDLERINFO*pHandlerInfo){//首先查找自身的命令訊息映射if(CWnd::OnCmdMsg(nID,nCode,pExtra,pHandlerInfo))returnTRUE;//如果視圖本身沒有處理該命令,將機會留給與其關聯的文檔對象if(m_pDocument!=NULL){CPushRoutingViewpush(this);returnm_pDocument->OnCmdMsg(nID,nCode,pExtra,pHandlerInfo);}returnFALSE;}
OnActivateView
當視圖被激活為活動視圖,或由活動轉為非活動時,調用該函式通知視圖。基類的實現只是設定該視圖為焦點。代碼如下:
voidCView::OnActivateView(BOOLbActivate,CView*pActivateView,CView*){UNUSED(pActivateView);//unusedinreleasebuildsif(bActivate)//當前狀態為活動嗎{ASSERT(pActivateView==this);//如果其父視窗也是活動的,則設定焦點。(在MDI中,其父框架可能是非活動的)if(IsTopParentActive())SetFocus();}}

派生類

MFC提供了豐富的CView派生類,各種不同的派生類實現了對不同種類控制項的支持,以為用戶提供多元化的顯示界面。
CScrollView:提供滾動支持;CCtrlView:支持tree、list和richedit控制項;CDaoRecordView:在dialog-box控制項中顯示資料庫記錄;CEditView:提供了一個簡單的多行文本編輯器視圖;CFormView:包含dialog-box控制項,可滾動,基於對話框模板資源;CListView:支持列表控制項視圖;CRecordView:在dialog-box控制項中顯示資料庫記錄;CRichEditView:支持富文本編輯的控制項視圖;CTreeView:支持重點在樹控制項的文檔/視圖結構的視圖。

相關詞條

熱門詞條

聯絡我們