版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第三講MFC繪圖基礎(chǔ)主講:呂駿
Windows是一個圖形操作系統(tǒng),大多數(shù)應(yīng)用程序都需要在客戶區(qū)繪制一些圖形,如繪制文本、幾何圖形、位圖和光標等。Windows提供了一個稱為圖形設(shè)備接口GDI(GraphicsDeviceInterface)的抽象接口。GDI作為Windows的重要組成部分,它負責管理用戶繪圖操作時功能的轉(zhuǎn)換。用戶通過調(diào)用GDI函數(shù)與設(shè)備打交道,GDI通過不同設(shè)備提供的驅(qū)動程序?qū)⒗L圖語句轉(zhuǎn)換為對應(yīng)的繪圖指令,避免了直接對硬件進行操作,從而實現(xiàn)所謂的設(shè)備無關(guān)性。所謂設(shè)備無關(guān)性,是指操作系統(tǒng)屏蔽了硬件設(shè)備的差異,使用戶編程時一般無需考慮設(shè)備的類型,如不同種類的顯示器或打印機。
Windows繪圖過程和設(shè)備無關(guān)性的實現(xiàn):
GDI處于設(shè)備驅(qū)動程序的上一層,當程序調(diào)用繪圖函數(shù)時,GDI將繪圖命令傳送給當前設(shè)備的驅(qū)動程序,以調(diào)用驅(qū)動程序提供的接口函數(shù)。驅(qū)動程序的接口函數(shù)將Windows繪圖命令轉(zhuǎn)化為設(shè)備能夠執(zhí)行的輸出命令,實現(xiàn)圖形的繪制。不同設(shè)備具有不同的驅(qū)動程序,設(shè)備驅(qū)動程序是設(shè)備相關(guān)的。設(shè)備環(huán)境DC(DeviceContext)為了實現(xiàn)設(shè)備無關(guān)性,應(yīng)用程序的輸出不直接面向顯示器等物理設(shè)備,而是面向一個稱之為設(shè)備環(huán)境DC(DeviceContext)的虛擬邏輯設(shè)備。設(shè)備環(huán)境也稱設(shè)備描述表或設(shè)備上下文,它是由Windows管理的一個數(shù)據(jù)結(jié)構(gòu),它保存了繪圖操作中一些共同需要設(shè)置的信息,如當前的畫筆、畫刷、字體和位圖等圖形對象及其屬性,以及顏色和背景等影響圖形輸出的繪圖模式。形象地說,一個設(shè)備環(huán)境提供了一張畫布和一些繪畫的工具,我們可以使用不同顏色的工具在上面繪制點、線、圓和文本。在Windows中不使用DC無法進行輸出,在使用任何GDI繪圖函數(shù)之前,必須建立一個設(shè)備環(huán)境。獲取設(shè)備環(huán)境DC的方法:
在程序中不能直接存取DC數(shù)據(jù)結(jié)構(gòu),只能通過系統(tǒng)提供的一系列函數(shù)或使用設(shè)備環(huán)境的句柄HDC來間接地獲取或設(shè)置設(shè)備環(huán)境結(jié)構(gòu)中的各項屬性,如顯示器高度和寬度、支持的顏色數(shù)及分辨率等。如果采用SDK方法編程,獲取DC的方法有兩種:在WM_PAINT消息處理函數(shù)中通過調(diào)用API函數(shù)BeginPaint()獲取設(shè)備環(huán)境,在消息處理函數(shù)返回前調(diào)用API函數(shù)EndPaint()釋放設(shè)備環(huán)境。在其他函數(shù)中通過調(diào)用API函數(shù)GetDC()獲取設(shè)備環(huán)境,調(diào)用API函數(shù)ReleaseDC()釋放設(shè)備環(huán)境。獲取設(shè)備描述表:方法一該方法適合于處理非WM_PAINT消息用GetDC獲取設(shè)備描述表句柄用ReleaseDC釋放設(shè)備描述表句柄這種獲取設(shè)備描述表的一般方式如下 hdc=GetDC(hwnd);
……
ReleaseDC(hwnd,hdc);9WM_PAINT消息什么時候向窗口過程發(fā)送WM_PAINT消息(窗口發(fā)生重繪)-“無效”的時候調(diào)用UpdateWindow函數(shù)刷新窗口窗口的全部或者部分失效的時候窗口從無到有手動刷新窗口調(diào)用InvalidateRect函數(shù)計算機科學與技術(shù)學院張淼10獲取設(shè)備描述表:方法二該方法只適合于處理WM_PAINT消息用BeginPaint“使無效窗口生效”并“返回設(shè)備描述表句柄”用EndPaint釋放設(shè)備描述表句柄一般處理WM_PAINT的形式如下:CaseWM_PAINT; hdc=BeginPaint(hwnd,&ps);
……
EndPaint(hwnd,&ps); return0;如果采用MFC方法編程,MFC提供了不同類型的DC類,每一個類都封裝了DC句柄,并且它們的構(gòu)造函數(shù)自動調(diào)用獲取DC的API函數(shù),析構(gòu)函數(shù)自動調(diào)用釋放DC的API函數(shù)。因此,在程序中通過聲明一個MFC設(shè)備環(huán)境類的對象就自動獲取了一個DC,而當該對象被銷毀時就自動釋放了獲取的DC。MFCAppWizard應(yīng)用程序向?qū)?chuàng)建的OnDraw()函數(shù)自動支持所獲取的DC。MFC的DC類包括CDC、CPaintDC、CClientDC、CWindowDC等,其中CDC類是MFC設(shè)備環(huán)境類的基類,其它的MFC設(shè)備環(huán)境類都是CDC的派生類。CDC類既作為其它MFC設(shè)備環(huán)境類的基類,又可以作為一個一般的設(shè)備環(huán)境類使用。利用它可以訪問設(shè)備屬性和設(shè)置繪圖屬性。CDC類對GDI的所有繪圖函數(shù)進行了封裝。CPaintDC類是OnPaint()函數(shù)使用的設(shè)備環(huán)境類,它代表一個窗口的繪圖畫面。如果添加WM_PAINT消息處理函數(shù)OnPaint(),就需要使用CPaintDC類來定義一個設(shè)備環(huán)境對象。CClientDC類代表了客戶區(qū)設(shè)備環(huán)境。當在客戶區(qū)實時繪圖時,需要利用CClientDC類定義一個客戶區(qū)設(shè)備環(huán)境。CWindowDC類代表了整個程序窗口設(shè)備環(huán)境,可以在整個窗口區(qū)域繪圖。CClientDC、CPaintDC和CWindowDC的區(qū)別當窗口的某個區(qū)域需要重繪時激發(fā)窗口重繪消息WM_PAINT,相應(yīng)消息處理函數(shù)CWnd::OnPaint將被調(diào)用。CPaintDC一般只用于OnPaint函數(shù)中,在處理完窗口重繪后,
CPaintDC對象的析構(gòu)函數(shù)把WM_PAINT消息從消息隊列中清除,避免不斷地重繪操作。坐標原點(0,0)是客戶區(qū)的左上角。CClientDC用于特定窗口客戶區(qū)(窗口中除邊框、標題欄、菜單欄、狀態(tài)欄外的中間部分)的輸出,其構(gòu)造函數(shù)中包含了GetDC,析構(gòu)函數(shù)中包含了ReleaseDC,不需要顯式釋放DC資源。一般用于響應(yīng)非重繪消息(如鍵盤和鼠標消息)的繪圖操作。坐標原點(0,0)是客戶區(qū)的左上角。CWindowDC在整個應(yīng)用程序窗口上畫圖,而CClientDC和CPaintDC只能在客戶區(qū)繪制圖形;除非要自己繪制窗口邊框和按鈕,否則一般不用它。坐標原點(0,0)是屏幕的左上角。13MFC中獲取DC的方法在如OnDraw等函數(shù)中傳遞一個指向CDC對象的指針如OnDraw(CDC*pDC);使用構(gòu)造函數(shù)構(gòu)建對象一般不構(gòu)造CDC對象在CWnd類的OnPaint函數(shù)中,定義CPaintDC對象CPaintDCdc(this);在CWnd類的其它函數(shù)中,定義CClientDC和CWindowDC的對象CClientDCdc(this);CWindowDCdc(this);OnDraw與OnPaint的區(qū)別OnDraw是CView類的成員函數(shù),不響應(yīng)消息;OnPaint是CWnd類的成員函數(shù),相應(yīng)WM_PAINT消息。CView默認調(diào)用的OnPaint函數(shù)如下
voidCView::OnPaint()
{
CPaintDCdc(this);
OnPrepareDC(&dc);
OnDraw(&dc);//調(diào)用了OnDraw
}可見OnPaint函數(shù)也調(diào)用了CView::OnDraw函數(shù)。因而一般在OnDraw函數(shù)內(nèi)添加繪圖代碼,完成繪圖任務(wù)15
GDI坐標系和映射模式Windows坐標系分為邏輯坐標系和設(shè)備坐標系兩種,GDI支持這兩種坐標系。一般而言,GDI的文本和圖形輸出函數(shù)使用邏輯坐標,而在客戶區(qū)移動或按下鼠標的鼠標位置是采用設(shè)備坐標。邏輯坐標系是面向DC的坐標系,這種坐標不考慮具體的設(shè)備類型,在繪圖時,Windows會根據(jù)當前設(shè)置的映射模式將邏輯坐標轉(zhuǎn)換為設(shè)備坐標。設(shè)備坐標系是面向物理設(shè)備的坐標系,這種坐標以像素或設(shè)備所能表示的最小長度單位為單位,X軸方向向右,Y軸方向向下。設(shè)備坐標系的原點位置(0,0)不限定在設(shè)備顯示區(qū)域的左上角。設(shè)備坐標系統(tǒng)設(shè)備坐標系統(tǒng)x軸自左至右,y軸從上到下,坐標原點在屏幕左上角[0,0]XYO17設(shè)備坐標系分為屏幕坐標系、窗口坐標系和客戶區(qū)坐標系三種相互獨立的坐標系。屏幕坐標系以屏幕左上角為原點,一些與整個屏幕有關(guān)的函數(shù)均采用屏幕坐標,如GetCursorPos()、SetCursorPos()、CreateWindow()、MoveWindow()。彈出式菜單使用的也是屏幕坐標。窗口坐標系以窗口左上角為坐標原點,它包括窗口標題欄、菜單欄和工具欄等范圍。客戶區(qū)坐標系以窗口客戶區(qū)左上角為原點,主要用于客戶區(qū)的繪圖輸出和窗口消息的處理。鼠標消息的坐標參數(shù)使用客戶區(qū)坐標,CDC類繪圖成員函數(shù)使用與客戶區(qū)坐標對應(yīng)的邏輯坐標。坐標之間的相互轉(zhuǎn)換編程時,有時需要根據(jù)當前的具體情況進行三種設(shè)備坐標之間或與邏輯坐標的相互轉(zhuǎn)換。MFC提供了兩個函數(shù)CWnd::ScreenToClient()和CWnd::ClientToScreen()用于屏幕坐標與客戶區(qū)坐標的相互轉(zhuǎn)換。MFC提供了兩個函數(shù)CDC::DPtoLP()和CDC::LPtoDP()用于設(shè)備坐標與邏輯坐標之間的相互轉(zhuǎn)換。生成設(shè)備環(huán)境,就可以開始繪制不同形狀的幾何圖形,GDI提供了繪制基本圖形的成員函數(shù),這些函數(shù)封裝在MFC的CDC類中。CDC類提供的繪圖函數(shù)包括點、直線、曲線、矩形、橢圓、弧、扇形、弦形和多邊形等供用戶使用。如果進行復(fù)雜繪圖的話,就需要通過算法來組織這些基本繪圖函數(shù)來完成繪圖。繪圖函數(shù)使用的坐標都是邏輯坐標。
繪制基本圖形
函
數(shù)功
能SetPixel用指定的顏色在指定的坐標畫一個點MoveTo移動當前位置到指定的坐標,函數(shù)返回以前位置的坐標。LineTo從當前位置到指定位置畫一條直線Polyline從當前位置開始,根據(jù)函數(shù)參數(shù)繪制多條折線。PolyBezier根據(jù)兩個端點和兩個控制點繪制貝濟埃(Bezier)曲線。Rectangle根據(jù)指定的左上角和右下角坐標繪制一個矩形RoundRect繪制一個圓角矩形。Ellipse根據(jù)指定的矩形繪制一個內(nèi)切橢圓Arc根據(jù)指定的矩形繪制內(nèi)切橢圓上的一段弧邊ArcTo該函數(shù)功能與Arc函數(shù)相同,不同之處在于畫弧成功后Pie繪制扇形Chord繪制弦形,弦形是一條橢圓弧和其對應(yīng)的弦所組成的封閉圖形。Polygon根據(jù)兩個或兩個以上頂點繪制一個多邊形DrawIcon在指定位置畫一個圖標,如果成功函數(shù)返回非0,否則返回0。畫線LineTo函數(shù)用于繪制一條從當前繪圖位置到指定坐標點的直線段,其函數(shù)聲明如下:BOOLLineTo(intx,inty);BOOLLineTo(POINTpoint);參數(shù)x和y,及參數(shù)point指定了坐標點,默認情況下從(0,0)開始畫
利用MFCAppWizard建立一個SDI應(yīng)用程序,在OnDraw()函數(shù)中添加如下程序代碼:
pDC->LineTo(10,10);POINTp1;p1.x=100;p1.y=100;//使用POINT結(jié)構(gòu)pDC->LineTo(p1);CPointp2;p2.x=200;p2.y=100;//使用CPoint類pDC->LineTo(p2);移動畫筆MoveTo函數(shù)用于將當前繪圖位置移到指定的坐標點處,函數(shù)聲明如下:CPointMoveTo(intx,inty);CPointMoveTo(POINTpoint);參數(shù)x和y,及參數(shù)point指定了新的當前繪圖位置坐標。返回值是CPoint對象實例,它包含了新的當前繪圖位置坐標。Rectangle函數(shù)用于繪制矩形,其函數(shù)聲明如下:BOOLRectangle(intx1,inty1,intx2,inty2);BOOLRectangle(LPCRECTlpRect);其中第一個函數(shù)參數(shù)給出了兩組點坐標,第一組為矩形的左上角點坐標,第二組為矩形的右下角點坐標。第二個函數(shù)使用了指向矩形區(qū)域結(jié)構(gòu)的指針作為參數(shù),也可以使用CRect類。如果繪圖成功,函數(shù)返回TRUE,否則返回FALSE。修改OnDraw函數(shù),輸入如下代碼: pDC->Rectangle(50,50,200,80); CRectr; r.left=100;r.right=200; r.top=100;r.bottom=200; pDC->Rectangle(r);(left,top是左上角坐標,right,bottom是右下角坐標)Ellipse函數(shù)用于繪制橢圓或者圓,其函數(shù)聲明如下:BOOLEllipse(intx1,inty1,intx2,inty2);BOOLEllipse(LPCRECTlpRect);其中,第一個函數(shù)的參數(shù)x1和y1指定了要繪制的橢圓或者圓的外接矩形的左上角點坐標,參數(shù)x2和y2指定了要繪制的橢圓或者圓的外接矩形的右下角點坐標。第二個函數(shù)的參數(shù)使用了矩形區(qū)域結(jié)構(gòu)來存放外接矩形的左上角和右下角坐標。如果繪圖成功,函數(shù)返回TRUE,否則返回FALSE。修改OnDraw函數(shù),輸入如下代碼:pDC->Ellipse(50,50,200,80);Arc函數(shù)用于繪制一個橢圓形的弧線,它是一個指定的矩形的內(nèi)切橢圓的一段。所繪制弧線的實際起點是該內(nèi)切橢圓與一條直線的交點,而該直線是從橢圓中心到指定點的連線?;【€的實際終點也是如此。如圖所示:函數(shù)聲明如下:BOOLArc(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);函數(shù)參數(shù)給出了四對坐標:第一對坐標是要繪制的圓弧所在橢圓的外接矩形的左上角坐標;第二對坐標是要繪制的圓弧所在橢圓的外接矩形的右下角坐標;第三對坐標指定了圓弧的起點;第四對坐標指定了圓弧的終點。在畫圓弧時,默認的圓弧方向是逆時針,即圓弧是按逆時針方向從起點到終點的。修改OnDraw函數(shù),輸入如下代碼: pDC->Arc(100,100,300,300,100,150,250,150);
Pie函數(shù)用于繪制扇形,它是由橢圓弧與其起始點和終止點所對應(yīng)的橢圓的半徑所圍成的圖形,其函數(shù)聲明如下:BOOLPie(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);其參數(shù)含義與Arc函數(shù)相同,差別在于Arc函數(shù)只繪制了橢圓弧,而Pie函數(shù)將橢圓弧所確定的扇形繪制出來。如果繪圖成功,函數(shù)返回TRUE,否則返回FALSE。修改OnDraw函數(shù),輸入如下代碼:pDC->Pie(100,100,300,300,100,150,250,150);Polygon函數(shù)用于繪制一個封閉的多邊形,其函數(shù)聲明如下:BOOLPolygon(LPPOINTlpPoints,intnCount);參數(shù)lpPoints存放的是多邊形的頂點坐標,nCount是多邊形的頂點數(shù)目,該參數(shù)必須大于2。如果繪圖成功,函數(shù)返回TRUE,否則返回FALSE。修改OnDraw函數(shù),輸入如下代碼:POINTp[5];p[0].x=10;p[0].y=10;p[1].x=100;p[1].y=100;p[2].x=200;p[2].y=100;p[3].x=200;p[3].y=200;p[4].x=100;p[4].y=50;pDC->Polygon(p,5);在默認狀態(tài)下,當用戶創(chuàng)建一個設(shè)備環(huán)境并在其中繪圖時,系統(tǒng)使用設(shè)備環(huán)境缺省的繪圖工具及其屬性。如果要使用不同風格和顏色的繪圖工具進行繪圖,用戶必須重新為設(shè)備環(huán)境設(shè)置自定義的畫筆和畫刷等繪圖工具。
畫筆和畫刷
繪圖工具類主要包括畫筆CPen、畫刷Cbrush、字體CFont、位圖Bitmap和調(diào)色板Cpalette等。類繼承關(guān)系如圖CObjectCPen類:GDI畫筆,用于畫線。默認的畫筆用于繪制與一個像素等寬的黑色實線。CBrush類:GDI畫刷,用來填充一個封閉圖形對象(如矩形、圓形)的內(nèi)部區(qū)域,默認的畫刷顏色是白色。CFont類:GDI字體,用來繪制文本,可設(shè)置文字的大小、是否加粗、是否斜體、是否加下劃線等。CBitmap類:GDI位圖,用于填充區(qū)域。CPalette類:GDI調(diào)色板,包含系統(tǒng)可用的色彩信息,是應(yīng)用程序和彩色輸出設(shè)備環(huán)境(如顯示器)的接口。CRgn類:GDI區(qū)域,用于設(shè)備環(huán)境(通常是窗口)內(nèi)的區(qū)域操作,通常和CDC類中與裁剪(clipping)有關(guān)的成員函數(shù)配合使用。39CDC類提供了成員函數(shù)SelectObject()選擇用戶自己創(chuàng)建的GDI對象,該函數(shù)有多種重載形式,可以選擇用戶已定制好的畫筆、畫刷、字體和位圖等不同類型的GDI對象。CPen*SelectObject(CPen*pPen);CBrush*SelectObject(CBrush*pBrush);virtualCFont*SelectObject(CFont*pFont);CBitmap*SelectObject(CBitmap*pBitmap);函數(shù)參數(shù)是一個指向用戶已定制好的GDI對象的指針,選擇操作成功函數(shù)將返回以前GDI對象的指針,否則返回NULL。選擇一個GDI對象:
顏色的設(shè)置Windows用COLORREF類型的數(shù)據(jù)存放顏色,它是一個32位整數(shù)。任何一種顏色都是由紅、綠、藍三種基本顏色組成,COLORREF類型數(shù)據(jù)的低位字節(jié)存放紅色強度值,第2個字節(jié)存放綠色強度值,第3個字節(jié)存放藍色強度值,高位字節(jié)為0,每一種顏色分量的取值范圍為0到255。直接設(shè)置COLORREF數(shù)據(jù)不太方便,Windows提供了RGB宏用于設(shè)置顏色,將其中的紅、綠、藍分量值轉(zhuǎn)換為COLORREF類型的顏色數(shù)據(jù):RGB(byRed,byGreen,byBlue)其中參數(shù)byRed、byGreen和byBlue分別表示紅、綠、藍分量值(范圍0到255)。RGB宏的使用:
很多涉及到顏色的GDI函數(shù)都需要使用COLORREF類型的參數(shù),如設(shè)置背景色的成員函數(shù)CDC::SetBkColor()、設(shè)置文本顏色的成員函數(shù)CDC::SetTextColor()。例如:COLORREFrgbBkClr=RGB(192,192,192); //定義灰色
pDC->SetBkCorlor(rgbBkClr)//背景色為灰色pDC->SetTextColor(RGB(0,0,255)); //文本顏色為蘭色標準彩色的RGB值
顏色RGB分量值顏色RGB分量值淺紅255,0,0深紅128,0,0淺綠0,255,0深綠0,128,0淺藍0,0,255深藍0,0,128淺黃255,255,0深黃128,128,0淺青0,255,255深青0,128,128紫色255,0,255灰色192,192,192白色255,255,255黑色0,0,0
使用畫筆當用戶創(chuàng)建一個用于繪圖的設(shè)備環(huán)境時,該設(shè)備環(huán)境自動提供了一個寬度為一個像素單位、風格為實黑線(BLACK_PEN)的缺省畫筆。如果要在設(shè)備環(huán)境使用自己的畫筆繪圖,首先需要創(chuàng)建一個指定風格的畫筆,然后將創(chuàng)建的畫筆選入設(shè)備環(huán)境,最后,在使用該畫筆繪圖結(jié)束后需要釋放該畫筆。
1.創(chuàng)建畫筆創(chuàng)建畫筆最簡單的方法是調(diào)用CPen類的一個帶參數(shù)的構(gòu)造函數(shù)來構(gòu)造一個CPen類畫筆對象,以下代碼創(chuàng)建了一個紅色虛線畫筆:CPenPenNew(PS_DASH,1,RGB(255,0,0));創(chuàng)建畫筆的第二種方法是首先構(gòu)造一個沒有初始化的CPen類畫筆對象,然后調(diào)用成員函數(shù)CPen::CreatePen()創(chuàng)建定制的畫筆工具:CPenPenNew;PenNew.CreatePen(PS_DASH,1,RGB(255,0,0));函數(shù)CreatePen()的參數(shù)類型與帶參數(shù)的CPen類構(gòu)造函數(shù)完全一樣。當畫筆對象的聲明與創(chuàng)建不在同一個地方時(如需要多次改變畫筆)只有采用這種方法。畫筆式樣(PenStyle)樣式說明樣式說明PS_SOLID實線PS_DASHDOTDOT雙點劃線PS_DOT點線PS_NULL空的邊框PS_DASH虛線PS_INSIDEFRAME邊框?qū)嵕€PS_DASHDOT點劃線
創(chuàng)建畫筆后必須調(diào)用成員函數(shù)CDC::SelectObject()將創(chuàng)建的畫筆選入當前設(shè)備環(huán)境。如果選擇成功,函數(shù)SelectObject()將返回以前畫筆對象的指針。選擇新的畫筆時應(yīng)該保存以前的畫筆對象,如下代碼所示:CPen*pPenOldpPenOld=pDC>SelectObject(&PenNew);2.選擇創(chuàng)建的畫筆
創(chuàng)建和選擇畫筆工具后,應(yīng)用程序就可以使用該畫筆繪圖。當繪圖完成后,應(yīng)該通過調(diào)用成員函數(shù)CDC::SelectObject()恢復(fù)設(shè)備環(huán)境以前的畫筆工具,并通過調(diào)用成員函數(shù)CGdiObject::DeleteObject()釋放GDI對象所占的內(nèi)存資源,如下代碼所示:pDC->SelectObject(pPenOld); //恢復(fù)設(shè)備環(huán)境DC中原來的畫筆PenNew.DeleteObject(); //刪除底層的GDI對象3.還原畫筆
例
編寫一個SDI應(yīng)用程序,繪制不同風格、寬度和顏色的直線。
在OnDraw()函數(shù)中添加如下所示的代碼:CPen*pPenOld,PenNew;intnPenStyle[]={ PS_SOLID,//實線
PS_DOT,//點線
PS_DASH,//虛線
PS_DASHDOT,//點劃線
PS_DASHDOTDOT,//雙點劃線
PS_NULL, //空的邊框
PS_INSIDEFRAME,//邊框?qū)嵕€};LPTSTRstrStyle[]={_T("Solid"),_T("Dot"),_T("Dash"),_T("DashDot"),_T("DashDotDot"),_T("Null"),_T("InsideFrame")};pDC->TextOut(60,10,_T("用不同樣式的畫筆繪圖"));
for(inti=0;i<7;i++)//用不同樣式畫筆繪圖{
if(PenNew.CreatePen(nPenStyle[i],1,RGB(0,0,0)))//創(chuàng)建畫筆{pPenOld=pDC->SelectObject(&PenNew); //選擇畫筆
pDC->TextOut(10,30+20*i,strStyle[i]); pDC->MoveTo(100,40+20*i); pDC->LineTo(200,40+20*i);pDC->SelectObject(pPenOld); //恢復(fù)原來的畫筆PenNew.DeleteObject();//刪除底層的GDI對象}else
{ MessageBox(_T("不能創(chuàng)建畫筆!"));}}當創(chuàng)建一個設(shè)備環(huán)境時,該設(shè)備環(huán)境自動提供了一個填充色為白色(WHITE_BRUSH)的缺省畫刷。與畫筆一樣,也可以利用MFC畫刷類CBrush創(chuàng)建自己的畫刷,用于填充圖形的繪制。畫刷有三種基本類型:純色畫刷、陰影畫刷和圖案畫刷,CBrush類提供了多個不同重載形式的構(gòu)造函數(shù)。以下創(chuàng)建三種不同類型的畫刷:CBrushbrush1(RGB(255,0,0));//創(chuàng)建純色畫刷CBrushbrush2(HS_DIAGCROSS,RGB(0,255,0)); //創(chuàng)建陰影畫刷CBrushbrush3(&bmp); //創(chuàng)建圖案畫刷使用畫刷創(chuàng)建畫刷也可先構(gòu)造一個沒有初始化的CBrush類畫刷對象,然后調(diào)用CBrush類的初始化成員函數(shù)創(chuàng)建定制的畫刷工具。CBrush類提供的常用創(chuàng)建函數(shù)有:CreateSolidBrush()用指定的顏色創(chuàng)建一個純色畫刷;CreateHatchBrush()用指定的陰影樣式和顏色創(chuàng)建一個陰影畫刷;CreatePatternBrush()用位圖創(chuàng)建一個圖案畫刷;CreateSysColorBrush()用系統(tǒng)默認顏色創(chuàng)建一個指定陰影樣式的畫刷。陰影畫刷使用預(yù)定義的六種陰影樣式進行繪圖。表2.3列出了六種陰影樣式。修改OnDraw函數(shù),輸入如下代碼:CBrushbrush(HS_CROSS,RGB(255,0,0));//構(gòu)造一個十字交叉線的陰影線畫刷,前景色為紅色CPenpen(PS_SOLID,2,RGB(0,0,255));//構(gòu)造一個寬度為2,顏色為藍色的實線畫筆pDC->SelectObject(&pen);pDC->SelectObject(&brush);//選擇畫筆和畫刷pDC->Rectangle(200,200,300,300);pen.DeleteObject();brush.DeleteObject();//刪除畫筆和畫刷對象很多Windows應(yīng)用程序都需要顯示文本,并且,文本還是一些應(yīng)用程序的主要處理對象,如MSWord字處理軟件。文本與字體密切相關(guān),輸出文本時選擇不同類型的字體在很大程度上影響程序的界面風格,合適的字體可以增強程序的感染力。因此,對軟件用戶來說,文本輸出也是很重要的。Windows為文本的顯示提供了多種物理字體支持,而在程序中我們可以創(chuàng)建不同風格的邏輯字體來輸出文本。
文本與字體
以圖形方式進行文本的輸出是Windows操作系統(tǒng)一個特性,文本輸出實際上是按照指定的字體樣式將文本中的每個字符繪制出來。編程時最常用的文本輸出函數(shù)是TextOut()函數(shù),該函數(shù)只能輸出單行文本。要繪制多行文本可以調(diào)用DrawText()函數(shù),另一個函數(shù)ExtTextOut()可以用一個矩形框?qū)敵鑫谋敬M行裁剪。繪制文本通過API函數(shù)TextOut執(zhí)行文本輸出操作。BOOLTextOut(__in
HDChdc,__in
intnXStart,__in
intnYStart,__in
LPCTSTRlpString,__in
intcbString);參數(shù)hdc為設(shè)備上下文的句柄;參數(shù)nXStart為起始點x坐標;參數(shù)nYStart為起始點y坐標;參數(shù)lpString為要輸出的文本字符串;參數(shù)cbString為字符串中要輸出的字符的數(shù)量。使用設(shè)備上下文類CDC的成員函數(shù)TextOut來輸出,CDC::TextOut函數(shù)的兩種重載形式virtualBOOLTextOut(intx,inty,LPCTSTRlpszString,intnCount);
BOOLTextOut(intx,inty,constCString&str);參數(shù)x指定文本起始點的x坐標;參數(shù)y指定文本起始點的y坐標;參數(shù)lpszString為要輸出的文本字符串;參數(shù)nCount指定字符串中的字節(jié)個數(shù);參數(shù)str為包含要輸出的字符的CString對象。(2)設(shè)置文本顏色在默認情況下,Windows繪制黑色文本。可以通過SetTextColor()函數(shù)改變文本的顏色。例如:pDC->SetTextColor(RGB(255,0,0));//設(shè)置文本顏色為紅色可以通過GetTextColor()函數(shù)檢索到當前文本的顏色,例如COLORREFcolor=pDC->GetTextColor();SetBkColor()和GetBkColor()函數(shù)用于設(shè)置背景顏色和獲取當前的背景顏色。(3)設(shè)置字符間距
SetTextCharacterExtra()函數(shù)用來設(shè)置文本字符的間距,GetTextCharacterExtra()用來獲得當前文本字符的間距,函數(shù)說明如下:
pDC->SetTextCharacterExtra(space);intspace=pDC->GetTextCharacterExtra();
其中,space表示在文本字符之間使用的額外空間的像素數(shù)。SetTextAlign()函數(shù)用于設(shè)置顯示文本的對齊方式,函數(shù)說明如下:
pDC->SetTextAlign(alignment);
其中,alignment參數(shù)取值:TA_LEFT、TA_CENTER和TA_RIGHT,分別表示左對齊、居中方法和右對齊。Alignment參數(shù)取值:TA_TOP、TA_BOTTOM和TA_BASELINE分別表示文本在垂直方向的對齊方式,上對齊、下對齊和字符的基線對齊。輸出文本時,默認情況下使用系統(tǒng)提供的缺省字體,如果需要可以改變顯示文本的字體。與畫筆和畫刷一樣,字體也是一種GDI對象,MFC類CFont對GDI字體對象進行了封裝,我們一般利用CFont類創(chuàng)建自己的字體(GDI對象),然后把創(chuàng)建的字體選入設(shè)備環(huán)境,以用于在設(shè)備環(huán)境中繪制文本。
Windows支持光柵字體、矢量字體和TrueType三種字體。光柵字體即點陣字體,這種字體需要為每一種大小的字體創(chuàng)建獨立的字體文件。矢量字體以一系列線段存儲字符。TrueType字體是與設(shè)備無關(guān)的字體,字符以輪廓的形式存儲,包括線段和曲線。
字體概述
TrueType字體正成為真正的主流,這種字體能夠以一種非常出色的字體技術(shù)繪制文本。TrueType字體能夠縮放為任何大小的字體,而不會降低圖形的質(zhì)量。Windows中提供的TrueType字體主要有Arial、Courier、Symbol、TimeNewRoman等,可以通過Windows“控制面板|字體”瀏覽系統(tǒng)已安裝的字體。CFont類成員函數(shù)CFont()構(gòu)造一個CFont對象。此對象在使用之前應(yīng)該先使用CreateFont、CreateFontIndirect、CreatePointFont或CreatePointFontIndirect初始化。BOOLCreateFont(intnHeight,intnWidth,intnEscapement,intnOrientation,intnWeight,BYTEbItalic,BYTEbUnderline,BYTEcStrikeOut,BYTEnCharSet,BYTEnOutPrecision,BYTEnClipPrecision,BYTEnQuality,
BYTEnPitchAndFamily,LPCTSTRlpszFacename)通過指定的一些特征初始化CFont對象。各參數(shù)的意義及取值參考MSDN。BOOLCreateFontIndirect(constLOGFONT*lpLogFont)通過一個LOGFONT結(jié)構(gòu)體變量給出的特征來初始化CFont對象。參數(shù)lpLogFont是指向LOGFONT結(jié)構(gòu)體變量的指針,此LOGFONT結(jié)構(gòu)體變定義了邏輯字體的特征。LOGFONT結(jié)構(gòu)體的定義參見字體對話框或CSDN。BOOLCreatePointFont(intnPointSize,LPCTSTRlpszFaceName,CDC*pDC=NULL)此函數(shù)提供了一種由指定字樣和點數(shù)創(chuàng)建字體的簡單方式。BOOLCreatePointFontIndirect(constLOGFONT*lpLogFont,CDC*pDC=NULL)此函數(shù)是通過指定的字樣和點數(shù)創(chuàng)建字體的間接方式。例:CClientDCdc(this);CFontfntZdy,*pfntOld;fntZdy.CreatePointFont(200,_T("Arial“),&dc);pfntOld=dc.SelectObject(&fntZdy);//選入設(shè)備環(huán)境dc.TextOut(100,100,_T("Hello!Thisis20PtArialFont."));dc.SelectObject(pfntOld); //恢復(fù)原來字體fntZdy.DeleteObject();//刪除自定義字體
例:CFontfont;LOGFONTLogFnt;memset(&LogFnt,0,sizeof(LOGFONT));//清零結(jié)構(gòu)LogFontLogFnt.lfHeight=22;//字體高度為22像素LogFnt.lfItalic=true;//斜體LogFnt.lfWeight=FW_BOLD;//粗黑wcscpy_s(LogFnt.lfFaceName,_T("Courier“));//匹配字體為Courierfont.CreateFontIndirect(&LogFnt);//創(chuàng)建字體CClientDCdc(this);CFont*def_font=dc.SelectObject(&font);//選入設(shè)備環(huán)境dc.TextOut(100,130, _T("Hello!Thisis22-pixel-heightCourierFont."));dc.SelectObject(def_font);font.DeleteObject();Windows預(yù)定義了一些簡單風格的GDI對象,用戶使用這些GDI對象時,無需自己創(chuàng)建它們,可以直接將它們選入當前的設(shè)備環(huán)境,這些GDI對象稱作為堆(Stock)對象。堆對象包括堆畫筆、堆畫刷和堆字體等。
使用GDI堆對象通過調(diào)用成員函數(shù)CDC::SelectStockObject()可以選擇一個堆對象繪圖工具,以下代碼將堆畫筆和堆畫刷作為當前的繪圖工具: pPenOld=(CPen*)pDC->SelectStockObject(NULL_PEN); //使用堆畫筆對象 pBrhOld=(CBrush*)pDC->SelectStockObject(LTGRAY _BRUSH); //使用堆畫刷對象堆畫筆、畫刷的樣式及說明
樣式說明樣式說明BLACK_PEN黑色畫筆WHITE_PEN白色畫筆NULL_PEN空畫筆BLACK_BRUSH黑色畫刷WHITE_BRUSH白色畫刷NULL_BRUSH空畫刷GRAY_BRUSH灰色畫刷DKGRAY_BRUSH深灰色畫刷LTGRAY_BRUSH淺灰色畫刷HOLLOW_BRUSH虛畫刷
利用MFCAppWizard向?qū)?chuàng)建一個SDI應(yīng)用程序UseStock,利用ClassWizard為類CUseStockView添加WM_PAINT消息處理函數(shù)OnPaint():CPen*pPenOld,PenNew;CBrush*pBrhOld,BrhNew;pPenOld=(CPen*)dc.SelectStockObject(BLACK_PEN); //使用堆畫筆對象pBrhOld=(CBrush*)dc.SelectStockObject(GRAY_BRUSH); //使用堆畫刷對象例
編寫一個SDI應(yīng)用程序,使用堆畫筆和堆畫刷繪制圖形。
dc.Rectangle(100,100,300,300);PenNew.CreateStockObject(NULL_PEN);//NULL_PEN用于繪制無邊界的填充圖形dc.SelectObject(&PenNew);BrhNew.CreateStockObject(LTGRAY_BRUSH);dc.SelectObject(&BrhNew);dc.Ellipse(400,100,600,200);dc.SelectObject(pPenOld);//恢復(fù)系統(tǒng)默認的GDI對象dc.SelectObject(pBrhOld);dc.Ellipse(400,210,600,310);
鼠標橡皮筋技術(shù)畫圓就是采用圓心和圓周上任一點畫圓技術(shù)(簡稱C+P方法),首先用鼠標左擊選擇圓心位置,然后移動鼠標,圓隨鼠標移動而擴大或縮小,當再次單擊鼠標左鍵時,確定圓周上的一點,從而畫出相應(yīng)的圓。直線、矩形等基本圖形都可以采用橡皮筋技術(shù)。
采用鼠標橡皮筋技術(shù)畫圓第一步:建立MouseSpring工程文件;第二步:向視圖類中添加自定義的成員變量proctected:CPointm_bO;//圓心
CPointm_bR;//圓上的點
intm_ist;//圓心與圓周上點的區(qū)別,m_ist=0,表示鼠標左擊點為圓心,m_ist=1,表示鼠標左擊點為圓周上的點第三步:向視圖類中添加自定義的成員函數(shù)原型:
public:voidDrawCircle(CDC*pDC,CPointcenp,CPointardp);intComputeRadius(CPointcenp,CPointardp);分別為兩個成員函數(shù)DrawCircle()和ComputeRadius()添加程序代碼,程序如下:voidCMouseSpringView::DrawCircle(CDC*pDC,CPointcenp,CPointardp){intradius=ComputeRadius(cenp,ardp);
//由圓心確定所畫圓的外切區(qū)域
CRectrc(cenp.x-radius,cenp.y-radius,cenp.x+radius,cenp.y+radius);pDC->Ellipse(rc);//畫出一個整圓}第四步:添加成員函數(shù)的程序代碼。intCMouseSpringView::ComputeRadius(CPointcenp,CPointardp){floatdx=cenp.x-ardp.x;floatdy=cenp.y-ardp.y;
//sqrt()函數(shù)的調(diào)用,在頭文件中加入#include<cmath>return(int)sqrt(dx*dx+dy*dy);}第五步:在視圖類CPP文件的構(gòu)造函數(shù)中初始化成員變量
視圖類的構(gòu)造函數(shù)名與該視圖類的名字相同。在視圖類中選擇構(gòu)造函數(shù),如:CMouseSpringView(),用鼠標左鍵雙擊,輸入下面程序代碼:CMouseSpringView::CMouseSpringView(){//TODO:addconstructioncodeherem_bO.x=0;m_bO.y=0;//圓心
m_bR.x=0;m_bR.y=0;//圓上的點
m_ist=0;//圓心與圓上的點區(qū)別}第六步:在視圖類的OnDraw()函數(shù)中加入下列代碼,實現(xiàn)視圖繪圖。
pDC->SelectStockObject(NULL_BRUSH); DrawCircle(pDC,m_bO,m_bR);//調(diào)用自定義的成員函數(shù)畫圓第七步:向視圖類中添加兩個鼠標消息響應(yīng)函數(shù),并輸入鼠標處理程序代碼。一個是OnLButtonDown()函數(shù)程序如下: CDC*pDC=GetDC();pDC->SelectStockObject(NULL_BRUSH); if(!m_ist)//繪制圓
{m_bO=m_bR=point;
//紀錄第一次單擊鼠標位置,定圓心
m_ist++; }
else {m_bR=point;//記錄第二次單擊鼠標的位置,定圓周上的點
m_ist--;//為新繪圖作準備
DrawCircle(pDC,m_bO,m_bR);//繪制新圓
} ReleaseDC(pDC);//釋放設(shè)備環(huán)境另一個是OnMouseMove()函數(shù),程序如下 CDC*pDC=GetDC(); intnDrawmode=pDC->SetROP2(R2_NOT);//設(shè)置異或繪圖模式,并保存原來繪圖模式pDC->SelectStockObject(NULL_BRUSH);if(m_ist==1){ CPointprePnt,curPnt; prePnt=m_bR;//獲得鼠標所在的前一位置
curPnt=point;//繪制橡皮筋線
DrawCircle(pDC,m_bO,prePnt);//用異或模式重復(fù)畫圓,擦出所畫的圓
DrawCircle(pDC,m_bO,curPnt);//用當前位置作為圓周上的點畫圓
m_bR=point;}pDC->SetROP2(nDrawmode);//恢復(fù)原繪圖模式
ReleaseDC(pDC);//釋放設(shè)備環(huán)境
第八步:編譯運行程序,驗證運行結(jié)果。〔例〕編寫一個程序Mydrawline,程序
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024冷庫租賃合同書范本(適用小型企業(yè))
- 2024年度互聯(lián)網(wǎng)廣告技術(shù)服務(wù)合同
- 2024年買賣合同標的為新能源汽車
- 2024年度影視制作與發(fā)行承包合同
- 2024年度房地產(chǎn)商業(yè)綜合體建設(shè)項目施工合同
- 公租房個人收入證明(12篇)
- 2024年度安置房社區(qū)文化活動合同
- 手機教學課件教學
- 2024年度品牌合作框架協(xié)議
- 2024年度特許經(jīng)營合同標的及許可使用范圍
- 海洋工程柔性立管發(fā)展概況
- 漢語教師志愿者培訓大綱
- 護理導(dǎo)論 評判性思維
- SPC培訓資料_2
- 學習適應(yīng)性測驗(AAT)
- ADS創(chuàng)建自己的元件庫
- MATLAB仿真三相橋式整流電路(詳細完美)
- 2019年重慶普通高中會考通用技術(shù)真題及答案
- 天秤座小奏鳴曲,Libra Sonatine;迪安斯,Roland Dyens(古典吉他譜)
- 鋼筋混凝土工程施工及驗收規(guī)范最新(完整版)
- 光纜施工規(guī)范及要求
評論
0/150
提交評論