MFC|三種繪圖模式、六種圖形對象(mfc繪圖的三種方式)
早期開發(fā)圖形程序都是直接針對具體設(shè)備進(jìn)行的,要開發(fā)一個圖形軟件必須先了解是什么型號的顯示卡或者打印機(jī),根據(jù)每個廠家提供的接口編寫不同的代碼來開發(fā)。進(jìn)入Windows等圖形界面的操作系統(tǒng)時代,操作系統(tǒng)通過對驅(qū)動程序的統(tǒng)一管理,將設(shè)備接口細(xì)節(jié)隱藏于操作系統(tǒng)內(nèi)部。程序員在編寫圖形程序時,只要調(diào)用一個公用的虛擬設(shè)備即可,這個虛擬設(shè)備也就是DC(Device Context)。
在Windows應(yīng)用程序中,設(shè)備環(huán)境(DC,繪圖模式)與圖形對象協(xié)同進(jìn)行繪圖顯示工作。就像畫家繪圖一樣,設(shè)備環(huán)境(繪圖模式)好比是畫家的畫布,圖形對象好比是畫家的畫具,畫家可以使用不同的畫布、不同的畫筆、畫刷、顏料等,畫出不同載體、不同色彩、不同線條的畫。
MFC繪圖類包括繪圖環(huán)境類和繪圖對象類。
1 繪圖環(huán)境類(繪圖模式)
繪圖環(huán)境類是MFC對GDI三類繪圖模式函數(shù)封裝成CDC及三種派生類。
CDC派生類封裝的GDI函數(shù)及功能說明:
a) CPaintDC類,封裝了BeginPaint和EndPaint函數(shù)。
用于標(biāo)準(zhǔn)客戶區(qū)繪圖,窗口刷新時不消失,在WM_PAINT消息下使用。
b) CWindowDC類,封裝了GetWindowDC和ReleaseDC函數(shù)。
用于非客戶區(qū)繪圖,在WM_NCPAINT消息下使用,窗口刷新時不消失。
c) CClientDC類,封裝了GetDC和ReleaseDC函數(shù)。
用于臨時客戶區(qū)繪圖,窗口刷新時消失,任何時候都可以使用。
d) CMemDC類,封裝CreateCompatibleDC和DeleteDC等函數(shù)。
VC6.0暫未封裝該類,VS 2010有封閉。在內(nèi)存中繪圖,常用于雙緩沖防止畫面閃爍。
CMetaFileDC類-父類是CDC類,作用保存繪制命令。
實例:
void CXdcDlg::OnPaint() { CPaintDC dc(this); // device context for painting dc.rectangle(0,0,40,40); dc.Rectangle(80,80,120,120); dc.MoveTo(20,20); dc.LineTo(100,100);}void CXdcDlg::OnNcPaint() {#if 0 CWindowDC dc(this); CRect rect; GetWindowRect(rect); dc.Rectangle(0,0,rect.Width(),rect.Height()); char str[222]; sprintf(str,”非客戶空間(%d,%d,%d,%d)”,rect.left,rect.top,rect.right,rect.bottom); dc.SetTextColor(RGB(255,0,0)); dc.TextOut(5,5,str,strlen(str));#endif}void CXdcDlg::OnLButtonDown(UINT nFlags, CPoint point) { CClientDC dc(this); dc.Ellipse(point.x-10,point.y-10,point.x 10,point.y 10); CDialog::OnLButtonDown(nFlags, point);}
2 繪圖對象類
使用GDI對象可以改變線條的顏色、大小,可以使用填充顏色,改變字體,顯示一張位圖等。不過,GDI對象是要通過DC才能發(fā)生作用的。要使用這些GDI對象,必須使用SelectObject函數(shù)將其選入DC中。
主要有六種,全部由CGdiObject類派生:
CPen-畫筆,用于修飾線條 的顏色、寬度和線型(實線、虛線或點劃線等);
CBrush-畫刷,用于修飾一個閉合圖形內(nèi)部的填充內(nèi)容(填充顏色、填充線條以及平鋪位圖;
CFont-字體,用于修飾輸出文字的樣式、高度、粗細(xì)以及字間距等;
CBitmap-位圖,用于顯示和處理點陣圖像;
CRgn-區(qū)域,用于修飾輸出圖像的不規(guī)則邊界,如橢圓或多邊形等;
CPalette-調(diào)色板,用于修飾輸出圖像的色調(diào),如16色或256色等;
顏色變量和處理函數(shù):
typedef DWORD COLORREF;
COLORREF c1 = RGB(255,255,255);
一般按如下步驟使用GDI對象:
a、創(chuàng)建或得到一個GDI對象;
b、使用dc.SelectObject函數(shù)把GDI對象選入DC;
c、使用DC進(jìn)行繪圖或文字輸出;
d、恢復(fù)DC原來的GDI對象并刪除剛新創(chuàng)建的GDI對象;
綜合DC和GDI對象的使用步驟,則繪圖的完整步驟為:
I 獲取或者創(chuàng)建一個DC,也就是創(chuàng)建一個繪圖模式或環(huán)境;
II 獲取或者創(chuàng)建一個GDI對象(Pen, Brush等);
III 使用dc.SelectObject函數(shù)把GDI對象選入DC;
IV 使用DC進(jìn)行繪圖或文字輸出;
V 恢復(fù)DC原來的GDI對象并刪除剛新創(chuàng)建的GDI對象,如pen.DeleteObject();
VI 釋放或刪除設(shè)備描述表DC;
其中,I和VI,II和IV是對應(yīng)的。
2.1 CPen類(畫筆)
畫筆決定了線條的顏色、寬度和線型(實線、點線或點劃線等)。Windows使用當(dāng)前在設(shè)備描述表中已選擇的畫筆來畫線。程序中可以選擇Windows的預(yù)定義畫筆,也可以選擇自定義的畫筆。
預(yù)定義畫筆有三種:BLACK_PEN(黑色筆) 、WHITE_PEN(白色筆)和NULL_PEN(空筆),這些都在windows.h中已經(jīng)定義好了,程序員可使用GetStockObject函數(shù)來選擇其中的一種,系統(tǒng)缺省的畫筆為黑色筆。Windows.h包含了HPEN的數(shù)據(jù)類型定義,使用該類型可以定義畫筆句柄的變量。
僅靠系統(tǒng)提供的預(yù)定義畫筆遠(yuǎn)遠(yuǎn)不能滿足需求,應(yīng)用程序可根據(jù)實際需要創(chuàng)建一種自定義的邏輯畫筆。其步驟一般為:首先用CreatePen或CreatePenIndirect函數(shù)建立一支畫筆,再調(diào)用SelectObject函數(shù)將其選入設(shè)備描述表,此后就可使用該畫筆在選定的設(shè)備描述表中進(jìn)行繪圖操作。任何時候某一設(shè)備描述表只能有一支畫筆被選入作為當(dāng)前畫筆,當(dāng)一支畫筆被選入時,原先已選入的畫筆便不再有效。完成繪圖操作后,可以通過調(diào)用DeleteObject來釋放已建立的畫筆。
函數(shù)CreatePen()
HPEN CreatePen(int fnPenStyle,int nWidth,COLORREF clrref);
該函數(shù)創(chuàng)建一個邏輯畫筆。其中fnPenStyle參數(shù)指定畫筆的線型,該參數(shù)可取由windows.h定義的七個標(biāo)識符之一,其含義為:
PS_SOLID 實線
PS_DASH 虛線
PS_DOT 點線
PS_DASHDOT 夾一點虛線
PS_DASHDOTDOT 夾二點虛線
PS_NULL 無
PS_INSIDEFRAME 線畫在所有構(gòu)件框架內(nèi)
nWidth參數(shù)是用邏輯單位表示的畫筆的寬度;
clrref參數(shù)是一個COLORREF類型的顏色值,指定畫筆的顏色,可用宏指令RGB構(gòu)造這個值,如:clrref=RGB(byRed,byGreen,byBlue);
實例
void CPenDlg::OnPaint() { CPaintDC dc(this); // 繪圖模式之一(標(biāo)準(zhǔn)客戶區(qū)繪圖),另外還有CWindowDC(非客戶區(qū))、CClientDC(臨時客戶區(qū)) dc.TextOut(20,20,”默認(rèn)畫筆:黑色,寬度為1″); dc.MoveTo(20,60); dc.LineTo(120,60); dc.TextOut(20,80,”通過構(gòu)造函數(shù)創(chuàng)建畫筆:CPen pn1(PS_SOLID,4,RGB(255,0,0));”); CPen pn1(PS_SOLID,4,RGB(255,0,0)); CPen *pOldPen = dc.SelectObject(&pn1); //選擇的是新建畫筆,返回的是之前的舊畫筆 dc.MoveTo(20,120); dc.LineTo(120,120); dc.TextOut(20,140,”通過CreatePen函數(shù)創(chuàng)建畫筆:pn2.CreatePen(PS_DASHDOT,1,RGB(0,0,255));”); CPen pn2; pn2.CreatePen(PS_DASHDOT,1,RGB(0,0,255)); dc.SelectObject(&pn2); dc.MoveTo(20,180); dc.LineTo(120,180); dc.TextOut(20,200,”畫一個矩形dc.Rectangle(20,240,140,300); 右上、右下角坐標(biāo) “); dc.SelectObject(pOldPen); // 選擇默認(rèn)畫筆 dc.Rectangle(20,240,140,300); dc.TextOut(20,320,”畫一個無邊框的矩形:CPen pn3(PS_NULL,1,RGB(0,0,0));”); CPen pn3(PS_NULL,1,RGB(0,0,0)); dc.SelectObject(&pn3); dc.Rectangle(20,360,140,420); dc.TextOut(20,440,”等價的無邊框矩形的畫法:dc.FillSolidRect(20,440,120,60,RGB(255,255,255));右上角坐標(biāo),長,寬”); dc.FillSolidRect(20,480,120,60,RGB(255,255,255)); //右上角坐標(biāo),長,寬 dc.SelectObject(pOldPen); // 恢復(fù)默認(rèn)畫筆}
運(yùn)行效果:
2.2 CBrush(刷子)
當(dāng)我們在繪制一些區(qū)域圖形時,其內(nèi)部往往需要以某種圖案進(jìn)行填充,這就需要選定”刷子”作為繪圖工具。Windows系統(tǒng)不僅為用戶提供了預(yù)定義刷子,而且還允許應(yīng)用程序自定義刷子。
Windows系統(tǒng)中預(yù)定義的刷子有如下七種:
BLACK_BRUSH 黑色刷子
DKGRAY_BRUSH 深灰色刷子
GRAY_BRUSH 灰色刷子
HOLLOW_BRUSH 中空刷子,畫邊界而不填充
LTGRAY_BRUSH 淺灰色刷子
NULL_BRUSH 空刷子
WHITE_BRUSH 白色刷子
應(yīng)用程序可以調(diào)用GetStockObject函數(shù)選用其中一個,系統(tǒng)缺省的刷子是白色刷子。Window.h包含了HBRUSH數(shù)據(jù)類型的定義,使用該類型就可定義刷子句柄的變量。
僅靠這七種刷子往往不能滿足要求,應(yīng)用程序通過調(diào)用如下幾種函數(shù)創(chuàng)建邏輯刷子,這些函數(shù)返回值均為刷子句柄。
CreateHatchBrush()
HBRUSH CreateHatchBrush(int fnStyle, COLORREF clrref);
該創(chuàng)建一個帶陰影的邏輯刷子。
FnStyle指定的陰影格式如下:
HS_BDLAGONAL 45度向上斜線組成的陰影圖案(自左到右)
HS_CROSS 水平和垂直交叉組成的陰影圖案
HS_DIAGCROSS 45度斜線交叉組成的陰影圖案
HS_FDIAGONAL 45度向下斜線組成的陰影圖案(自左到右)
HS_HORZONA 水平線組成的陰影圖案
HS_VERTICAL 垂直線組成的陰影圖案
Clrref是具有COLORREF類型定義的刷子顏色值,可用宏指令RGB構(gòu)造這個值。
函數(shù)CreateSolidBrush()
HBRUSH CreateSolidBrush(COLORREF clrre);
該函數(shù)創(chuàng)建的是一種實心顏色的邏輯刷子。clrre含義同上。
同樣,使用創(chuàng)建刷子的函數(shù)時,要檢查其返回,確保它是一個有效的句柄。
一旦創(chuàng)建了繪圖工具之后,可以SelectObject函數(shù)把它選擇到顯示緩沖區(qū)里。
在使用顯示緩沖區(qū)之前,并不一定非要創(chuàng)建和選擇繪圖工具,Windows為每個顯示緩沖區(qū)提供默認(rèn)的繪圖工具。例如:黑色筆,白色刷子和系統(tǒng)字體。
DeleteObject函數(shù)用來刪除不再需要的繪圖工具,但不能刪除一個已選進(jìn)顯示緩沖區(qū)的繪圖工具,而是應(yīng)該使用SelectObject函數(shù)恢復(fù)原有的繪圖工具,然后再刪除需要刪除的工具。
實例:
void CBrushDlg::OnPaint(){CPaintDC dc(this); // device context for paintingdc.Rectangle(20,20,120,100);CBrush br1(RGB(0,0,255));CBrush *pOldBrush = dc.SelectObject(&br1);dc.Ellipse(140,20,240,100);CBrush br2(HS_FDIAGONAL,RGB(255,0,0));dc.SelectObject(&br2);CPen pen(PS_SOLID,3,RGB(255,0,0));CPen *pOldPen = dc.SelectObject(&pen);dc.RoundRect(260,20,300,100,25,25);CBitmap bmp;bmp.LoadBitmap(IDB_BITMAP1);CBrush br3(&bmp);dc.SelectObject(&br3);CPen pen2(PS_SOLID,3,RGB(240,240,240));dc.SelectObject(&pen2);POINT pt[] = {{40,120},{160,120},{240,240},{20,240}};dc.Polygon(pt,4);CBrush br4;LOGBRUSH lb = {BS_NULL};br4.CreateBrushIndirect(&lb);dc.SelectObject(pOldPen);dc.SelectObject(&br4);dc.Chord(CRect(140,120,350,240),CPoint(260,240),CPoint(140,100));dc.SelectObject(pOldBrush);dc.SelectObject(pOldPen);}
運(yùn)行效果:
2.3 CFont(字體)
Windows是使用定義好的與設(shè)備無關(guān)的字符集,Windows的”文本”字符也是圖形,所以屏幕上所顯示的用打印機(jī)或繪圖儀等輸出品的文本完全一樣,做到”所見即所得”。
文本繪制函數(shù)有:
TextOut 以當(dāng)前的字體寫一字符串
DrawText 在一個特定矩形區(qū)中繪制某一格式的文本
ExtTextOut 在一個特定矩形區(qū)中,以當(dāng)前字體寫一字符串
GrayString 用灰色文本寫一字符串
TabbedTextOut 寫一帶擴(kuò)展字符的字符串
要輸出文本就離不開字體。獲取字體的相關(guān)信息可以使用函數(shù):
BOOL GetTextMetrics( LPTEXTMETRIC lpMetrics )
結(jié)構(gòu)TEXTMETRIC的定義如下所示:
typedef struct tagTEXTMETRIC { // tm LONG tmHeight; //字符高度 LONG tmAscent; //字符上部高度(基線以上) LONG tmDescent; //字符下部高度(基線以下) LONG tmInternalLeading; //由tmHeight定義的字符高度的頂部空間數(shù)目 LONG tmExternalLeading; //加在兩行之間的空間數(shù)目 LONG tmAveCharWidth; //平均字符寬度 LONG tmMaxCharWidth; //最寬字符的寬度 LONG tmWeight; //字體的粗細(xì)輕重程度 LONG tmOverhang; //加入某些拼接字體上的附加高度 LONG tmDigitizedAspectX; //字體設(shè)計所針對的設(shè)備水平方向 LONG tmDigitizedAspectY; //字體設(shè)計所針對的設(shè)備垂直方向 BCHAR tmFirstChar; //為字體定義的第一個字符 BCHAR tmLastChar; //為字體定義的最后一個字符 BCHAR tmDefaultChar; //字體中所沒有字符的替代字符 BCHAR tmbreakChar; //用于拆字的字符 BYTE tmItalic; //字體為斜體時非零 BYTE tmUnderlined; //字體為下劃線時非零 BYTE tmStruckOut; //字體被刪去時非零 BYTE tmPitchAndFamily; //字體間距(低4位)和族(高4位) BYTE tmCharSet; //字體的字符集 } TEXTMETRIC;
GDI字體族和字樣表如下表所示:
字體族 字體族常量 字樣說明
Dontcare FF_DONTCARE System 當(dāng)不能提供字體信息或字體并不
重要時使用
Decorative FF_DECORATIVE Symbol 新奇字體
Modern FF_MODERN Courer,ModernIerminal 筆畫大小固定的字體,但襯線可有可無
Roman FF_ROMAN Roman,TimeRoman 有襯線的、筆畫大小可變的羅馬字體
Script FF_SCRIPT Script 仿手寫體
Swiss FF_SWISS Helvetical,System 無襯線的、筆畫大小可變的字體
CreateFontIndirect函數(shù)
HFONT CreateFontIndirect(
CONST LOGFONT *lplf // pointer to logical font structure
);
參數(shù)lplf是LOGFONT結(jié)構(gòu)的指針。結(jié)構(gòu)中含有邏輯字體的特征信息。該函數(shù)用lplf所指的LOGFONT結(jié)構(gòu)中的信息創(chuàng)建一種邏輯字體。LOGFONT結(jié)構(gòu)的定義如下:
typedef struct tagLOGFONT { // lf LONG lfHeight; //字高度 LONG lfWidth; //字符平均寬度 LONG lfEscapement; //行與水平頁角度 LONG lfOrientation; //基線與水平角度 LONG lfWeight; //筆劃的粗細(xì) BYTE lfItalic; //非零為斜體 BYTE lfUnderline; //非零為下劃線 BYTE lfStrikeOut; //非零為中劃線 BYTE lfCharSet; //指定字符集 BYTE lfOutPrecision; //輸出精度 BYTE lfClipPrecision; //裁剪精度 BYTE lfQuality; //輸出質(zhì)量 BYTE lfPitchAndFamily; //字體的字距和族 TCHAR lfFaceName[LF_FACESIZE]; //含字體名的字符串 } LOGFONT;
函數(shù)SetTextAlign
大多數(shù)文本函數(shù)傳遞的參數(shù)表都要求有一個點坐標(biāo)參數(shù)以定義寫文本的參考點。當(dāng)前文本對齊屬性規(guī)定了字符串如何相對于所傳遞的坐標(biāo)進(jìn)行寫。SetTextAlign函數(shù)用以設(shè)置當(dāng)前文本對齊屬性。
UINT SetTextAlign( HDC hdc, // handle to device context UINT fMode // text-alignment flag );
該函數(shù)設(shè)置文本對齊方式。Hdc是參數(shù)描述表,fuAlign是文本對齊方式
實例:
void CFontDlg::OnPaint() { CPaintDC dc(this); // device context for painting dc.TextOut(10,10,”使用默認(rèn)字體輸出文字!”); CFont* pFont = GetFont(); CreateFont(&dc); CreateColor(&dc); Others(&dc, pFont); Width(&dc, pFont); Weight(&dc, pFont); Escape(&dc, pFont); Height(&dc, pFont); Normal(&dc, pFont); }void CFontDlg::Normal(CDC* pDC, CFont *pFont){ pFont = pDC->SelectObject(pFont); pDC->TextOut(10,30,”使用對話框字體輸出!”); pDC->SelectObject(pFont);}void CFontDlg::Height(CDC* pDC, CFont *pFont){ LOGFONT lf; pFont->GetLogFont(&lf); lf.lfHeight*=2; CFont font; font.CreateFontIndirect(&lf); pFont = pDC->SelectObject(&font); pDC->TextOut(10,50,”測試字符的高度加倍!”); pDC->SelectObject(pFont);}void CFontDlg::Weight(CDC* pDC, CFont *pFont){ LOGFONT lf; pFont->GetLogFont(&lf); lf.lfWeight=700; CFont font; font.CreateFontIndirect(&lf); pFont = pDC->SelectObject(&font); pDC->TextOut(10,80,”測試粗體字!”); pDC->SelectObject(pFont);}void CFontDlg::Width(CDC* pDC, CFont *pFont){ LOGFONT lf; pFont->GetLogFont(&lf); lf.lfWeight=lf.lfHeight; CFont font; font.CreateFontIndirect(&lf); pFont = pDC->SelectObject(&font); pDC->TextOut(10,100,”測試字體的寬度!”); pDC->SelectObject(pFont);}void CFontDlg::Others(CDC* pDC, CFont *pFont){ LOGFONT lf; pFont->GetLogFont(&lf); lf.lfItalic = TRUE; lf.lfUnderline = TRUE; lf.lfStrikeOut = TRUE; CFont font; font.CreateFontIndirect(&lf); pFont = pDC->SelectObject(&font); pDC->TextOut(10,120,”測試斜體、下劃線和刪除線!”); pDC->SelectObject(pFont);}void CFontDlg::Escape(CDC* pDC, CFont *pFont){ LOGFONT lf; pFont->GetLogFont(&lf); lf.lfEscapement = 200; CFont font; font.CreateFontIndirect(&lf); pFont = pDC->SelectObject(&font); pDC->TextOut(10,180,”測試字符串的傾斜度!”); pDC->SelectObject(pFont);}void CFontDlg::CreateColor(CDC* pDC){ COLORREF oldText = pDC->SetTextColor(RGB(255,0,0)); pDC->TextOut(10,200,”字體顏色”); COLORREF oldBack = pDC->SetBkColor(RGB(0,0,255)); pDC->TextOut(80,200,”背景顏色”); int nOldMode=pDC->SetBkMode(TRANSPARENT); pDC->TextOut(150,200,”背景透明”); pDC->SetTextColor(oldText); pDC->SetBkColor(oldBack); pDC->SetBkMode(nOldMode);}void CFontDlg::CreateFont(CDC* pDC){ CFont ft1; ft1.CreatePointFont(100,”幼圓”); CFont* pOldFont = pDC->SelectObject(&ft1); pDC->TextOut(10,220,”簡單創(chuàng)建字體的方法”); pDC->SelectObject(pOldFont); LOGFONT lf={20}; lf.lfCharSet=GB2312_CHARSET; lf.lfWeight=400; strcpy(lf.lfFaceName,”隸書”); CFont ft2; ft2.CreateFontIndirect(&lf); pDC->SelectObject(&ft2); pDC->TextOut(10,240,”完整創(chuàng)建字體的方法”);}
運(yùn)行效果:
2.4 CBitmap類(位圖)
void CBitmapDlg::OnPaint() { CPaintDC dc(this); // device context for painting CBitmap bmp; bmp.LoadBitmap(IDB_BITMAP1); BITMAP bm; bmp.GetBitmap(&bm); CDC mdc; mdc.CreateCompatibleDC(&dc); mdc.SelectObject(&bmp); dc.BitBlt(0,0,bm.bmWidth,bm.bmHeight,&mdc,0,0,SRCCOPY); //從1/3的位置開始輸出右下角2/3大小的圖片 dc.BitBlt(bm.bmHeight 10,10,bm.bmWidth*2/3,bm.bmHeight*2/3,&mdc,bm.bmWidth/3,bm.bmHeight/3,SRCCOPY); //使用默認(rèn)算法將圖像壓縮一半 dc.StretchBlt(10,bm.bmWidth 10,bm.bmWidth/2,bm.bmHeight/2,&mdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY); //更換壓縮算法提高壓縮后的圖像品質(zhì) dc.SetStretchBltMode(COLORONCOLOR); dc.StretchBlt(bm.bmWidth/2 20,bm.bmHeight 10,bm.bmWidth/2,bm.bmHeight/2,&mdc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY); //左右對稱壓縮 dc.StretchBlt(bm.bmWidth 30,bm.bmHeight 10,bm.bmWidth/2,bm.bmHeight/2,&mdc,bm.bmWidth,0,-bm.bmWidth,bm.bmHeight,SRCCOPY); }運(yùn)行效果:
2.5 CRgn類(區(qū)域)
void CRgnDlg::OnPaint() { CPaintDC dc(this); CBitmap bmp; bmp.LoadBitmap(IDB_BITMAP1); BITMAP bm; bmp.GetBitmap(&bm); int cx = bm.bmWidth; int cy = bm.bmHeight; CDC mdc; mdc.CreateCompatibleDC(&dc); mdc.SelectObject(&bmp); POINT pts[] = {{20,16},{110,56},{114,16},{166,52},{250,20},{240,100},{250,180},{150,160},{32,180},{52,100}}; CRgn rg1; rg1.CreatePolygonRgn(pts,sizeof(pts)/sizeof(POINT),WINDING); dc.SelectObject(&rg1); dc.BitBlt(0,0,cx,cy,&mdc,0,0,SRCCOPY); CRgn rg2; int nLeft = cx-50; int nTop = cy – 50; rg2.CreateRoundRectRgn(nLeft,nTop,nLeft cx,nTop cy,32,32); dc.SelectObject(&rg2); dc.BitBlt(nLeft,nTop,cx,cy,&mdc,0,0,SRCCOPY);}
運(yùn)行效果:
附:通過HDC句柄調(diào)用GDI函數(shù)的三種繪圖模式
// DC32.cpp : Defines the entry point for the application.#include “stdafx.h”#include “resource.h”#include <stdio.h>// GDI函數(shù)通過HDC句柄來調(diào)用#if 1//消息回調(diào)函數(shù) 窗口客戶區(qū)繪圖 BeginPaint(hwndDlg,&ps);窗口刷新時不消失,在WM_PAINT消息下使用,封裝成CPaintDC類BOOL CALLBACK dlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch(uMsg) { case WM_COMMAND: switch(wParam) { case IDCANCEL: EndDialog(hwndDlg,IDCANCEL); break; } case WM_PAINT: //窗口客戶區(qū)繪圖 { PAINTSTRUCT ps; //獲取與容器客戶區(qū)關(guān)聯(lián)的繪圖句柄 HDC hdc=BeginPaint(hwndDlg,&ps); //畫兩個矩形 Rectangle(hdc,0,0,40,40); Rectangle(hdc,80,80,120,120); //畫一條線 MoveToEx(hdc,20,20,NULL); LineTo(hdc,100,100); EndPaint(hwndDlg,&ps); } break; } return FALSE;}#endif#if 0//消息回調(diào)函數(shù) 非窗口客戶區(qū)繪圖 ;窗口刷新時不消失,在WM_NCPAINT消息下使用,封裝成CWindowDC類BOOL CALLBACK dlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch(uMsg) { case WM_COMMAND: switch(wParam) { case IDCANCEL: EndDialog(hwndDlg,IDCANCEL); break; } case WM_NCPAINT: { HDC hdc = GetWindowDC(hwndDlg); RECT rect; GetWindowRect(hwndDlg,&rect); //獲取整個窗口的空間區(qū)域 //畫兩個矩形 Rectangle(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top); char str[222]; sprintf(str,”非客戶空間(%d,%d,%d,%d)”,rect.left,rect.top,rect.right,rect.bottom); SetTextColor(hdc,RGB(255,0,0)); TextOut(hdc,5,5,str,strlen(str)); ReleaseDC(hwndDlg,hdc); return TRUE; } case WM_MOVE: SendMessage(hwndDlg,WM_NCPAINT,0,0); InvalidateRect(hwndDlg,NULL,TRUE); return TRUE; } return FALSE;}#endif#if 0//消息回調(diào)函數(shù) 臨時客戶區(qū)繪圖 ;窗口刷新時消失,任何時候都可以使用,封裝成GetDC類BOOL CALLBACK dlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch(uMsg) { case WM_COMMAND: switch(wParam) { case IDCANCEL: EndDialog(hwndDlg,IDCANCEL); break; } case WM_LBUTTONDOWN: HDC hdc = GetDC(hwndDlg); int x = LOWORD(lParam); int y = HIWORD(lParam); // 畫一個圓形 Ellipse(hdc,x-10,y-10,x 10,y 10); ReleaseDC(hwndDlg,hdc); return TRUE; } return FALSE;}#endif//測試坐標(biāo)系轉(zhuǎn)換void ScreenToClient(HWND hwndParent, RECT &rect){ POINT lt = {rect.left,rect.top}; POINT rb = {rect.right,rect.bottom}; ScreenToClient(hwndParent,<); ScreenToClient(hwndParent,&rb); rect.left = lt.x; rect.top = rb.x; rect.bottom = rb.y;}#if 0//消息回調(diào)函數(shù) 測試坐標(biāo)系轉(zhuǎn)換BOOL CALLBACK dlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch(uMsg) { case WM_COMMAND: switch(wParam) { case IDCANCEL: EndDialog(hwndDlg,IDCANCEL); break; } case WM_SETCURSOR: //當(dāng)鼠標(biāo)靠近或者切換到不同的控件時回調(diào) { HWND hwnd = (HWND)wParam; if(hwnd != GetDlgItem(hwndDlg,IDOK)) return TRUE; RECT rect; GetWindowRect(hwnd,&rect); //獲取按鈕的屏幕坐標(biāo) ScreenToClient(hwndDlg,rect); rect.left -=100; rect.right -= 100; MoveWindow(hwnd,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,TRUE); return TRUE; } break; } return FALSE;}#endifint APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ //MessageBox(NULL,”first program”,”note”,0); DialogBox(hInstance,(LPCTSTR)ws,NULL,dlgFunc); return 0;}
運(yùn)行效果:
-End-