一、 基礎
GDI的繪圖函數基本上都是有狀態的,所有的函數都要求一個HDC類型的句柄。這個HDC的獲得有幾個途徑BeginPaint,GetWindowDC, GetDC.他們的參數都只需要一個HWND就差不多了。記得調用了BeginPaint後要調用EndPaint進行清理,調用GetWindowDC和GetDC後要調ReleaseDC進行清理。在MFC代碼中常常遇到的CDC CPaintDC CWindowDC CClientDC。在這裡稍作解釋。
CDC :例如用GDI畫矩形要Rectangle(hDC,...),而使用CDC則是dc.Rectangle(...),由此可見CDC主要是把原本需要HDC作為參數的GDI函數封裝了一下,HDC成了它的一個成員變量。
CPaintDC CWindowDC CClientDC:他們都是從CDC繼承,分別是對上面所說的BeginPaint,GetWindowDC, GetDC調用對進行封裝(CPaintDC構造時調用BeginPaint,析構時調用EndPaint,其余同理)。
BeginPaint:一般用在對WM_PAINT的響應函數中使用
GetWindowDC:可獲得整個Window的HDC,而GetDC僅能獲得客戶區的HDC,區別就在於--
前者有效地繪制區域是整個窗口(邊框、標題欄、客戶區的總和)。
後者有效地繪制區域僅限於客戶區。
兩者的坐標系都是相對坐標而非屏幕坐標,原點是(0,0)。即以自己可繪制區域的左上角作為原點。
這裡可以順帶的講講RECT了,RECT是一個結構,依次有4個成員left,top,right,bottom用來代表一個矩形區域。CRect從RECT繼承,提供了一些常用的操作(例如說位移,縮小等等),其實就是改變4個成員的值。完全不用CRect也可以。許多GDI函數都要求一個RECT作為參數,或者類似的用(x,y,cx,cy)作參數,其實也就是一個RECT變種,用了寬度和高度罷了。
二、 實例教程
基礎知識介紹完畢,開始實例教程:
我們以如何繪制一個具有平面風格的狀態欄為例:
首先從CStatusBar繼承一個類:CStatusBarNew。(如果無法通過類向導做這件事,而你又對MFC的MESSAGEMAP等等東西不熟悉,可以從CStatusBarCtrl繼承一個,待生成代碼後,把所有的CStatusBarCtrl改為CStatusBar)
在此,只需要重寫WM_PAINT和WM_ERASEBKGND這兩個消息的響應函數。
BOOL CStatusBarNew::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CRect rect;
GetWindowRect(&rect);
ScreenToClient(&rect);
CBrush brush(0xf2f2f2);
pDC->FillRect(&rect, &brush);
return TRUE;
}
上面函數把狀態欄背景用0xf2f2f2這種顏色填充。
void CStatusBarNew::OnPaint()
{
CPaintDC cDC(this); // device context for painting
// TODO: Add your message handler code here
CRect rcItem;
cDC.SetBkMode(TRANSPARENT);
cDC.SelectObject (::GetStockObject (NULL_BRUSH));//選入畫刷