張丹丹

摘 要:Vc++是微軟推出的面向對象的可視化集成編程系統,隨Visual C++的發布還包括MFC-微軟基礎類,MFC提供的類很多用于界面開發,并設計了合理的消息映射機制和相應的消息處理函數,實現設備環境繪圖等。
中圖分類號:TP3 文獻標識碼:A 文章編號:1674-098X(2012)07(c)-0004-02
1 引言
,是經典的windows視窗和windows應用程序的開發平臺。為了減少程序設計人員工作開發量它提供有效的應用程序框架,對類進行了封裝,大部分是從Cobject里派生而來的,包含窗口類、圖形設備接口類、對象鏈接和嵌入類、文件和數據庫類、輸入/輸出類、異常類等等。
利用MFC提供的類我們可以方便做出一些不規則形狀的界面,同時利用雙緩沖原理有效解決界面抖動或界面顯示慢的問題。當窗口被改變大小,被最小最大化,或被關閉再打開,或者被另一個窗口覆蓋的時候,窗體都面臨著重繪,于是Window觸發WM_PAINT消息處理復雜圖形的繪制,由于過多的刷頻導致圖形顯示出抖動、緩慢等癥狀,利用內存設備環境,具體歸納為雙緩沖技術,可以有效解決這一問題。
2 MFC提供的設備環境類
MFC提供的類很多用于界面開發,其中一個重要的類—CDC,提供了處理設備環境,如顯示器、打印機等設備的成員函數。MFC將GDI(圖形設備接口)封裝在CDC類中,因此可以調用該類成員函數完成諸如各種顏色、尺寸,不同圖形的繪圖操作,同時GDI具有設備無關性,程序員也無需考慮設備的類型。CDC的這種設備無關性,使Windows下的繪圖等程序不直接面向物理設備,而通過虛擬的設備描述表進行。
設備描述表又稱設備上下文或設備環境,它是一種Windows下的數據結構,它存儲了設備繪圖屬性信息。應用程序不能直接訪問設備描述表,只能由各種相關API函數通過設備描述表的句柄間接訪問該結構。MFC提供的DC類包括CDC類和其派生類:CwindowDC、CclientDC 、CpaintDC等等,這些類都封裝了HDC句柄。CpaintDC是OnPaint()函數使用的設備環境類,該類對象只在響應WM_PAINT消息時調用,WM_PAINT是窗口每次重繪都會產生的一個消息, 而OnPaint()是對這個消息的響應函數,通常在使用OnPaint()函數處理WM_PAINT消息時,就可以創建一個CpaintDC類對象。CclientDC在處理非WM_PAINT消息時使用,用于繪制客戶區。另外還有很多DC類它們對于輸出的效果、圖形的顏色、剪裁、繪制等同樣發揮各自的作用。
另外一類重要的DC為內存DC, 它是虛擬的設備環境,可以有效的解決繪圖在顯示中所出現閃爍或緩慢的現象,也為雙緩沖技術的基本要點,實現步驟為:1)為當前的設備環境創建相匹配的內存DC,可以調用CreateCompatibleDC()函數實現;2)創建或導入位圖,可以調用Create Compatible Bitmap() 、LoadBitmap、LoadImage()等函數;3)將位圖載入內存設備環境,利用函數SelectObject()實現;4)將內存設備環境中繪制好的圖像拷貝至物理設備環境,利用BitBlt()完成。同時注意:當建立多個內存DC時,應將每個內存DC的繪圖一同復制到另一個內存DC中,再把這個復制好的內存DC拷貝至物理設備環境中。
3 MFC制作特殊界面和雙緩沖技術的實例
(1)窗口形狀的顯示在對話框初始函數中設置(代碼如下):
BOOL CEllipsefaceDlg :: OnInitDialog()
{
CDialog :: OnInitDialog() ;
......\此出代碼省略
CRgn a ;// 創建CRgn類對象a
a.CreateRoundRectRgn (0, 0, 400, 400, 700, 700 )[A1] ;
SetWindowRgn ( ( HRGN ) a,true )[A2] ; }(如圖1)
代碼詳解:
1.CRgn類封裝了一個Windows圖形設備接口(GDI)區域,調用CRgn類的成員函數可實現橢圓或者特殊矩形界面。
CRgn成員舉例說明:
CreateEllipticRgn():初始化一個橢圓區域的CRgn類對象
CreateRoundRectRgn(x1,y1,x2,y2,x3,y3):初始化一個圓角矩形區域的CRgn類對象
參數說明:
x1,y1:左上角x軸和y軸坐標
x2,y2:右下角x軸和y軸坐標
x3,y3:用于創建圓角的橢圓,它的寬度和高度
2.SetWindowRgn(HRGN hRgn,BOOL bRedraw):該函數用于設置窗口區域,該窗口區域決定了系統允許繪制窗口的范圍,超出該窗口區域的范圍系統一律不顯示。
參數說明:
HRGN hRgn:指向一個區域的句柄,把窗口設置在該區域。如果此參數設為NULL,函數不設置窗口區域。
BOOL bRedraw:參數為true,操作系統在設定區域后重新繪制窗口,反之不。
* 圖片顯示在OnPaint()函數中設置(代碼如下):
void CEllipsefaceDlg :: OnPaint()
{ …… // 此處代碼省略
else
{ ① CPaintDC dc ( this ) ;
② CRect area ;
GetWindowRect ( &area ) ;
③ CBitmap cBitmap ;
CBitmap * pOldMemBmp = NULL ;
cBitmap.LoadBitmap ( IDB_BITMAP ) ;
④ CDC mdc ;
mdc.CreateCompatibleDC(&dc);
⑤ pOldMemBmp = mdc.SelectObject ( &cBitmap ) ;
⑥ dc.BitBlt(0, 0, area.Width(), area.Height(), &mdc, 0, 0,SRCCOPY ) ;
⑦ if ( pOldMemBmp )mdc.SelectObject ( pOldMemBmp ) ;
CDialog :: OnPaint() ;
}
}
代碼詳解(如圖2):
①CPaintDC:派生于CDC的設備環境類。該類是OnPaint()函數使用的DC類,因此首先創建一個類對象dc。
②CRect類:RECT結構的數據成員(left,top,right,and bottom)也是CRect的可訪問的數據成員。在任何傳遞RECT結構,LPCRECT或LPRECT的函數中,都可以將一個CRect對象作為函數參數來代替。
void GetWindowRect(LPRECT lpRect) :屬于CWnd類的成員函數,返回窗口的邊框尺寸。
參數解釋:
const,lpRect,指向一個RECT結構的指針,該結構接收窗口的左上角和右下角的屏幕坐標。
總結:這兩行代碼利用GetWindowRect()獲取窗口區域,該函數參數為指向RECT結構的指針,因此首先創建一個Crect類對象area。
③CBitmap類封裝了窗口圖形設備接口位圖,提供操作位圖的成員函數。使用CBitmap對象之前要先構造CBitmap對象,調用其中的一個初始化成員函數設置位圖對象的句柄,本段程序調用了LoadBitmap(),此后就可以調用其它成員函數了。
LoadBitmap:從模塊的可執行文件中加載已命名的位圖資源,用來初始化對象,并且把位圖貼到對象中。本例中該函數參數為插入背景位圖的ID。
④創建CDC類的對象mdc(內存設備環境)。
CDC:定義了一類設備環境對象,所有的繪畫可以通過CDC的成員函數完成,該類提供了為設備環境操作的成員函數,比如繪畫工具的使用,使用顏色和調色板,窗體范圍的使用,轉換坐標,剪裁繪制線條,繪制簡單圖形等,該類還提供文本設置等的函數。在寫有關圖形界面的程序時,需使用CDC類及其子類。
CreateCompatibleDC:創建一個與物理設備兼容的內存設備環境,可以使用該內存設備環境在內存中存放圖片。此例調用該函數創建相應的內存設備環境mdc。
總結:利用雙緩沖技術的基本點是創建與設備壞境相對應的內存DC。
⑤CGdiObject* SelectObject( CGdiObject* pObject ):選擇一個圖形設備界面對象到指定的設備環境中,新的對象會替換掉之前的同類對象;
參數解釋:
hdc:設備上下文環境的句柄。
hgdiobj:被選擇的對象的句柄,該指定對象必須由如下的函數創建。
總結:為指向舊的內存位圖設置一個CBitmap類的指針,并預先設置該指針為空。然后將該指針指向載入位圖的內存設備壞境。
⑥BitBlt:把設備環境源的位圖復制到當前設備環境中。這里指把內存設備環境的位圖復制到當前的物理設備環境中,本例中即顯示器。
參數設置:
HDC hDestDC:指向目標設備環境的HDC句柄
xDest:目標矩形左上角的邏輯x軸坐標
yDest:目標矩形左上角的邏輯y軸坐標
pointDest:顯示目標矩形做上角的點結構
nDestWidth:目標矩形的邏輯寬度
nDestHeight:目標矩形的邏輯高度
HDC hSrcDC:指向源設備環境的HDC句柄
xSrc:源矩形左上角的邏輯x軸坐標
ySrc:源矩形左上角的邏輯y軸坐標
dwrop:執行柵格操作
rectDest:顯示目標區域的rect結構
pointSrc:顯示源矩形左上角的點結構
⑦ 如果指向內存位圖的指針不為空,則將其指向的位圖選入內存設備環境中。
(2)拖動窗體在WM_LBUTTONDOWN消息中實現(代碼如下):
void CEllipsefaceDlg::OnLButtonDown ( UINT nFlags,CPoint point )
{
::SendMessage ( this->GetSafeHwnd(), WM_SYSCOMMAND, SC_MOVE+2, 0 ) ;
CDialog :: OnLButtonDown ( nFlags,point ) ;
}
代碼詳解:
LRESULT SendMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam
):
為指定的窗口喚醒窗口程序,然后發送指定的消息給該窗口,當喚醒的窗口程序處理完消息后返回。
參數解釋:
HWND hWnd:指向喚醒窗口程序且將接受消息的窗口的句柄。
UINT Msg:被發送的指定消息。
WPARAM wParam、 LPARAM lParam :指定系統命令的類型。他們的類型可以是:SC_CLOSE(關閉窗口)、SC_HOTKEY(以應用程序指定的熱鍵激活窗口)、SC_MAXIMIZE(最大化窗口)、SC_MOVE(移動窗口)等。
CWnd::GetSafeHwnd:返回一個窗口的窗口句柄。
WM_SYSCOMMAND:當用戶從窗口菜單中選擇一個命令時,比如選擇最大化、最小化、還原、關閉等按鈕的時候,這些消息被發送至該窗口。
4 結語
本文通過窗口類、圖形設備接口類、設備上下文的成員函數及其類的創建和使用,闡述了如何使用MFC簡便的繪制不規則矩形界面,以及如何使用雙緩沖技術的原理和模式用于提高界面顯示效果等內容。對于MFC的消息及設備上下文的學習,可以探索出更多知識及應用。
參考文獻
[1] 劉銳寧,梁水,宋坤.Visual C++程序開發范例寶典[M].北京:人民郵電出版社,2009.
[2] 姚領田,高守傳.MFC窗口程序設計[M].北京:中國水利水電出版社,2007.
[3] G.(Shepherd,George),S.(Wingo.Scot).深入解析MFC.北京:中國電力出版社,2003.
[4] Microsoft.MSDN庫(中文) [DB/OL]. http://msdn.microsoft.com/library,2012/2012-05-03.
[5] 尹立民,王興東.Visual C++軟件項目開發實例[M].北京:電子工業出版社,2004.
[A1]對象a調用CRgn類成員函數CreateRoundRectRgn(),被初始化為一個圓角區域。
[A2]將初始化后的對象a作為對象句柄放入SetWindowRgn()中做參數,剛剛創建的圓角區域被設置為窗體區域,SetWindowRgn()為CWnd的成員函數。