版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
蔡則aizesu@163.com第二章MFC繪圖基礎MFC上機操作步驟MFC繪圖方法CDC類的主要繪圖成員函數(shù)設備上下文的調(diào)用和釋放雙緩沖機制MFC繪制圖形的幾種方法
本章學習目標2.1MFC上機操作步驟2.2MFC繪圖方法2.3設備上下文的調(diào)用與釋放2.4雙緩沖機制2.5MFC繪圖的幾種方法2.6本章小結本章內(nèi)容
微軟基類庫MFC(microsoftfoundationclasslibrary,MFC)是以C++形式封裝的WindowsAPI(ApplicationProgramInterface),包含了200多個已經(jīng)定義好的常用基類。在程序設計過程中,一般是通過MFC調(diào)用基類的成員函數(shù)來完成設計任務的。
2.1MFC上機操作步驟
1.從Windows的開始菜單中啟動MicrosoftVisualC++6.0,如圖2-1所示。圖2-1VisualC++啟動菜單2.在VisualC++集成開發(fā)環(huán)境中,從File|New菜單命令,彈出New對話框,切換到Projects選項卡。如圖2-2所示。圖2-2New對話框3.在MFCAppWizard-Step1對話框中,選中SingleDocument單選按鈕,其余保持默認值,如圖2-3所示。單擊Finish按鈕。圖2-3MFCAppWizard-Step1對話框4.彈出NewProjectInformation對話框。如圖2-4所示。單擊OK按鈕。圖2-4NewProjectInformation對話框5.完成上述步驟后,Test工程的MFC應用程序框架已經(jīng)生成。如圖2-5所示。圖2-5應用程序框架6.在應用程序框架的ClassView標簽頁中顯示所創(chuàng)建的類和成員函數(shù);在ResourceView標簽頁板中顯示所創(chuàng)建的資源;在FileView標簽頁中顯示源程序文件。如圖2-6所示。圖2-6應用程序框架的三個標簽頁顯示標簽頁:從ClassView標簽頁可以看出,CTestApp是應用的主函數(shù)類,用來處理消息。MFC中的數(shù)據(jù)是存儲在CTestDoc類文檔中,而結果卻顯示在CTestView類中,即顯示在CMainFram類的客戶區(qū)中。MFC中的文檔/視圖結構用來將程序的數(shù)據(jù)本身和數(shù)據(jù)顯示相互隔離,文檔類負責管理和維護數(shù)據(jù)本身,視圖類負責處理用戶鼠標和鍵盤的操作。全部展開FileView標簽頁后,顯示如圖2-7所示的內(nèi)容。本書后續(xù)的編程過程中一般使用的是CTestView類的TestView.h頭文件和TestView.cpp源文件。
圖2-7FileView標簽頁的展開顯示在CTestView類的源文件TestView.cpp中可以找到OnDraw()函數(shù)。其內(nèi)容如下:voidCTestView::OnDraw(CDC*pDC){ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
//TODO:adddrawcodefornativedatahere}pDC定義為CDC類的指針。
pDoc通過GetDocument()函數(shù)得到指向文檔類CTestDoc的指針。ASSERT_VALID(pDoc)函數(shù)使pDoc指針有效。使用pDC指針,可以對CDC類的成員函數(shù)進行操作。OnDraw()函數(shù)由系統(tǒng)框架直接調(diào)用,程序一運行就會自動執(zhí)行。7.點擊工具條上的按鈕(如圖2-8所示),就可以直接編譯、運行程序。Test工程運行結果如圖2-9所示。
盡管未編寫一句代碼,但Test程序已經(jīng)形成一個可執(zhí)行程序框架。
圖2-8執(zhí)行按鈕圖2-9Test工程運行效果圖2.2MFC繪圖方法MFC運算功能強大,擁有完備的繪圖功能。
在Windows平臺上,應用程序的圖形設備接口(graphicsdeviceinterface,GDI)被抽象為設備上下文(DeviceContext,DC)。在微軟基類庫MFC中,CDC類是定義設備上下文對象的基類,所有繪圖函數(shù)都在CDC基類中定義。當需要輸出文字或圖形時,就需要調(diào)用CDC類的成員函數(shù),這些成員函數(shù)具備輸出文本、繪制圖形的功能。
本節(jié)講解的例程全部在TestView.cpp文件的voidCTestView::OnDraw(CDC*pDC)函數(shù)中實現(xiàn)。2.2.1CDC類結構和GDI對象
CDC類派生了CClientDC類、CMetaFileDC類、CPaintDC類和CWindowDC類。如圖2-10所示。圖2-10CDC類1.CDC類CClientDC類:顯示器客戶區(qū)設備上下文類。CClientDC只能在窗口的客戶區(qū)進行繪圖。(不包括邊框、標題欄、菜單欄及狀態(tài)欄的空白區(qū)域)點(0,0)是客戶區(qū)的左上角。構造函數(shù)自動調(diào)用GetDC()函數(shù),析構函數(shù)自動調(diào)用ReleaseDC()函數(shù)。CMetaFileDC類:Windows圖元文件設備上下文類。CMetaFileDC封裝了在Windows中繪制圖元文件的方法。圖元文件是微軟定義的一種Windows平臺下的與設備無關的的圖形文件格式(擴展名為wmf),其所占的磁盤空間比其它任何格式的圖形文件都要小得多。wmf格式文件通常用于存儲一系列由繪圖命令所描述的圖形(如繪制直線與文本等)。在建立圖元文件時,不能實現(xiàn)即繪即得,而是先將GDI調(diào)用記錄在圖元文件中,然后在GDI環(huán)境中重新執(zhí)行圖元文件,才可顯示圖像。CPaintDC類:CPaintDC對象只在響應WM_PAINT消息時使用。CPaintDC類的構造函數(shù)會自動調(diào)用BeginPaint()函數(shù)。CPaintDC類的析構函數(shù)則會自動調(diào)用EndPaint()函數(shù)。MFC程序中使用CPaintDC類在視圖窗口中繪圖時,需要先添加WM_PAINT消息的映射函數(shù)OnPaint(),然后在OnPaint()函數(shù)中編寫與CPaintDC類相關的代碼,而不是編寫在OnDraw()中。請注意,如果使用OnPaint()函數(shù)響應了WM_PAINT消息,則OnDraw()函數(shù)將會被自動屏蔽。CWindowDC類:整個屏幕區(qū)域的顯示器設備上下文類。包括客戶區(qū)和非客戶區(qū)。CWindowDC允許在整個屏幕區(qū)域內(nèi)進行繪圖,其構造函數(shù)自動調(diào)用GetWindowDC(),析構函數(shù)自動調(diào)用ReleaseDC()函數(shù)。CWindowDC中的點(0,0)在屏幕的左上角,而CClientDC和CPaintDC中的點(0,0)是屏幕客戶區(qū)的左上角。如果在CTestView類中使用CWindowDC類對象進行繪圖,只有在使用GetParent()函數(shù)獲得CWnd指針后,才能在整個屏幕區(qū)域內(nèi)繪圖。圖2-11繪圖對象類2.常用繪圖類包括CPoint、CRect、CSize等,如圖2-11所示。由于CPoint、CRect和CSize是對Windows的POINT、RECT和SIZE結構體的封裝,因此可以直接使用其成員變量。CPoint類:存放點坐標(x,y)。相應的POINT結構體定義為typedefstructtagPOINT{
LONGx;
//點的x坐標
LONGy;
//點的y坐標}POINT,*PPOINT;CRect類:存放矩形左上角點和右下角點的坐標(left,top,right,bottom),相應的RECT結構體定義為typedefstruct_RECT{LONGleft;
//左上角點的x坐標
LONGtop;
//左上角點的y坐標
LONGright;
//右下角點的x坐標
LONGbottom;
//右下角點的y坐標}RECT,*PRECT;存放矩形x方向的長度和y方向的長度(cx,cy),相應的SIZE結構體定義為CSize類:typedefstructtagSIZE{LONGcx;//矩形的寬度
LONGcy;//矩形的高度}SIZE,*PSIZE;3.繪圖工具類圖2-12繪圖工具類
包括CGdiObject、CBitmap、CBrush、CFont、CPalette、CPen、CRgn等,如圖2-12所示。CGdiObject類:GDI繪圖工具的基類,一般不能直接使用。CBitmap:封裝了一個GDI位圖,提供位圖操作的接口。CBrush類:封裝了GDI畫刷,可以選作設備上下文的當前畫刷。畫刷用于填充圖形內(nèi)部。CFont:封裝了GDI字體,可以選作設備上下文中的當前字體。CPallette:封裝了GDI調(diào)色板,提供應用程序和顯示器之間的顏色接口。CPen:封裝了GDI畫筆,可以選作設備上下文的當前畫筆。畫筆用于繪制圖形邊界線。CRgn類:CRgn類封裝了一個Windows的GDI區(qū)域。這一區(qū)域是某一窗口中的一個橢圓或多邊形區(qū)域。在選擇GDI對象進行繪圖時,需要遵循以下步驟:繪圖開始前,創(chuàng)建一個GDI對象,并選入當前設備上下文,同時保存原GDI對象指針。使用新GDI對象繪圖。繪圖結束后,使用已保存的原GDI對象指針將設備上下文恢復原狀。把圖形顯示在屏幕坐標系中的過程稱為映射根據(jù)映射模式的不同可以分為邏輯坐標,設備坐標。邏輯坐標的單位是米制尺度或其它與字體相關的尺度。設備坐標的單位是像素MFC提供了幾種不同的映射模式,見表2-1。一般使用設備坐標模式MM_TEXT,坐標原點位于客戶區(qū)的左上角,x軸水平向右,y軸垂直向下,坐標基本單位為一個像素。2.2.2映射模式映射模式宏定義值坐標系特征MM_TEXT1每個邏輯坐標被轉(zhuǎn)換為1個設備坐標。正x向右,正y向下。MM_LOMETRIC2每個邏輯坐標被轉(zhuǎn)換為0.1mm。正x向右,正y向上。MM_HIMETRIC3每個邏輯坐標被轉(zhuǎn)換為0.01mm。正x向右,正y向上。MM_LOENGLISH4每個邏輯坐標被轉(zhuǎn)換為0.01inch。正x向右,正y向上。MM_HIENGLISH5每個邏輯坐標被轉(zhuǎn)換為0.001inch。正x向右,正y向上。MM_TWIPS6每個邏輯坐標被轉(zhuǎn)換為1/20點或1緹(因為1個點是1/72inch,所以1緹是1/1440inch)。正x向右,正y向上。MM_ISOTROPIC7在保持相等x和y軸相等比例的情況下,邏輯坐標單位和方向可以獨立設置。MM_ANISOTROPIC8邏輯坐標的單位、方向和比例獨立設置。表2-1映射模式1.設置映射模式函數(shù)類屬:CDC::SetMapMode原型:virtualintSetMapMode(intnMapMode);返回值:原映射模式。參數(shù):nMapMode是表2-1的模式代碼。2.設置窗口范圍函數(shù)類屬:CDC::SetWindowExt原型:virtualCSizeSetWindowExt(intcx,intcy);返回值:原窗口范圍的CSize對象。 4.設置視區(qū)坐標原點函數(shù)類屬:CDC::SetViewportOrg原型:virtualCPointSetViewportOrg(intx,inty);返回值:原視區(qū)原點的CPoint對象。3.設置視區(qū)范圍函數(shù)類屬:CDC::SetViewportExt原型:virtualCSizeSetViewportExt(intcx,intcy);返回值:原視區(qū)范圍的CSize對象。說明:(1)當使用各向同性的映射模式MM_ISOTROPIC
和各向異性的映射模式MM_ANISOTROPIC時,需要調(diào)用SetWindowExt()和SetViewportExt()函數(shù)來改變窗口和視區(qū)的設置,其它模式則不需要調(diào)用。(2)MM_LOMETRIC,MM_HIMETRIC,MM_LOENGLISH,MM_HIENGLISH和MM_TWIPS模式主要應用于使用物理單位(英寸或毫米)繪圖的情況下,y軸始終向上。(3)“窗口”與“視區(qū)”的概念往往不容易理解。(4)本書為了簡化操作,以后假定窗口和視區(qū)的大小相同,即x方向的比例因子和y方向的比例因子都為1。
例2-1使用用戶自定義映射模式,設置窗口大小和視區(qū)大小相等的二維屏幕坐標系。坐標系原點位于客戶區(qū)中心,視區(qū)中x軸水平向右為正,y軸垂直向上為正。voidCTestView::OnDraw(CDC*pDC){CTestDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedatahere
CRectrect;//聲明客戶區(qū)矩形GetClientRect(&rect);//獲得客戶區(qū)坐標pDC->SetMapMode(MM_ANISOTROPIC);//設置映射模式pDC->SetWindowExt(rect.Width(),rect.Height());//設置窗口pDC->SetViewportExt(rect.Width(),-rect.Height());
//x軸水平向右,y軸垂直向上pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);
//客戶區(qū)中心為坐標系原點}}2.2.3使用GDI對象創(chuàng)建畫筆函數(shù)類屬:CPen::CreatePen原型:BOOLCreatePen(intnPenStyle,intnWidth,COLORREFcrColor);返回值:如調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):nPenStyle是畫筆樣式,見表2-2;nWidth是畫筆的寬度;crColor是畫筆的顏色。畫筆樣式線型寬度畫筆樣式線型寬度PS_SOLID實線任意指定PS_DASHDOTDOT雙點劃線1或者更小PS_DASH虛線1或者更小PS_NULL不可見線任意指定PS_DOT點線1或者更小PS_INSIDEFRAME內(nèi)框架線任意指定PS_DASHDOT點劃線1或者更小
表2-2畫筆的樣式說明:(1)當畫筆的寬度大于1個像素時,畫筆樣式只能取PS_SOLID、PS_NULL和PS_INSIDEFRAME。 (2)畫筆也可以使用構造函數(shù)直接定義。原型為CPen(intnPenStyle,intnWidth,COLORREFcrColor);
(3)COLORREF是32位顏色數(shù)據(jù)類型,用雙字表示。原型為
typedefDWORDCOLORREF;(4)COLORREF可以表示為十六進制形式:0xbbggrr。例如0x0000ff代表紅色,0x00ff00代表綠色,0xff0000代表藍色。(5)可以使用RGB宏來創(chuàng)建COLORREF顏色。原型為COLORREFRGB(BYTEbyRed,BYTEbyGreen,BYTEbyBlue);其中,byRed是紅色分量,byGreen是綠色分量,byBlue是藍色分量,全部用字節(jié)表示。顏色分量可以表示為十六進制數(shù),范圍為0x00~0xff,也可以表示為十進制數(shù),范圍為(0~255),0代表無色,255代表全色。 (6)可以使用GetRValue(),GetGValue()和GetBValue()宏從COLORREF顏色中獲得紅、綠、藍分量。2.創(chuàng)建畫刷函數(shù)(1)創(chuàng)建實體畫刷函數(shù)類屬:CBrush::CreateSolidBrush原型:BOOLCreateSolidBrush(COLORREFcrColor);返回值:如果調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):crColor是畫刷的顏色。(2)創(chuàng)建陰影畫刷函數(shù)類屬:CBrush::CreateHatchBrush原型:BOOLCreateHatchBrush(intnIndex,COLORREFcrColor);返回值:如果調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):nIndex是陰影樣式,見表2-3;crColor是陰影線的顏色。3.選入GDI對象類屬:CDC::SelectObject原型:CPen*SelectObject(CPen*pPen);CBrush*SelectObject(CBrush*pBrush);CBitmap*SelectObject(CBitmap*pBitmap);返回值:如果成功,返回被替換對象的指針;否則,返回NULL。參數(shù):pPen是將要選擇的畫筆對象指針;pBrush是將要選擇的畫刷對象指針;pBitmap是將要選擇的位圖對象指針。說明:本函數(shù)將設備上下文的原GDI對象更換為新對象,同時返回指向原對象的指針。4.刪除GDI對象類屬:CGdiObject::DeleteObject原型:BOOLDeleteObject();返回值:如成功刪除GDI對象,返回“非0”;否則,返回“0”。參數(shù):無。5.選入庫對象類屬:CDC::SelectStockObject原型:virtualCGdiObject*SelectStockObject(intnIndex);返回值:如果調(diào)用成功,返回被替代的CGdiObject類對象的指針;否則返回NULL。參數(shù):參數(shù)nIndex可以是表2-4給出的庫畫筆代碼或表2-5給出的庫畫刷代碼。陰影樣式含義陰影樣式含義HS_BDIAGONAL
45°上升陰影線(從左到右)HS_FDIAGONAL
45°下降陰影線(從左到右)HS_CROSS
水平與垂直交叉陰影線HS_HORIZONTAL
水平陰影線HS_DIAGCROSS45°十字交叉陰影線HS_VERTICAL垂直陰影線表2-3常用的陰影線樣式庫畫筆代碼含義BLACK_PEN寬度為1個像素的黑色實線畫筆NULL_PEN
透明畫筆WHITE_PEN寬度為1個像素的白色實線畫筆表2-43種常用庫筆庫畫刷代碼含義對應的RGBBLACK_BRUSH
黑色的實心畫刷RGB(0,0,0)DKGRAY_BRUSH暗灰色的實心畫刷RGB(64,64,64)GRAY_BRUSH灰色的實心畫刷RGB(128,128,128)HOLLOW_BRUSH
空心畫刷LTGRAY_BRUSH淡灰色的實心畫刷RGB(192,192,192)NULL_BRUSH透明畫刷WHITE_BRUSH白色的實心畫刷RGB(255,255,255)表2-57種常用庫畫刷
說明:SetPixelV()函數(shù)不需要返回所繪制像素點的RGB值,執(zhí)行速度比SetPixel()快得多。推薦使用SetPixelV()函數(shù)繪制像素點。2.2.4CDC類繪圖成員函數(shù)繪制像素點函數(shù)類屬:CDC::SetPixel和CDC::SetPixelV原型:COLORREFSetPixel(intx,inty,COLORREFcrColor);BOOLSetPixelV(intx,inty,COLORREFcrColor);返回值:SetPixel()函數(shù)如果調(diào)用成功,返回所繪制像素點的RGB值;否則,返回-1。SetPixelV()函數(shù)如果調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):x是像素點位置的x邏輯坐標;y是像素點位置的y邏輯坐標;crColor是像素點顏色。返回值:指定像素的RGB值。參數(shù)說明:得到指定像素的RGB顏色值。本函數(shù)是常成員函數(shù)。2.獲取像素點顏色函數(shù)
例2-6在屏幕的P0(20,20)坐標位置處繪制一個綠色像素點,然后讀出該像素點的顏色,水平平移100個像素繪制P1點。效果如圖2-13所示。類屬:CDC::GetPixel原型:COLORREFGetPixel(intx,inty)const;{ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);voidCTestView::OnDraw(CDC*pDC)
COLORREFclr;
intx=20,y=20;
pDC->SetPixelV(x,y,RGB(0,255,0));
clr=pDC->GetPixel(x,y);
pDC->SetPixelV(x+100,y,clr);
//TODO:adddrawcodefornativedatahere}圖2-13例2-2效果圖P0P13.繪制直線段函數(shù)
(1)設置當前位置函數(shù)類屬:CDC::MoveTo原型:CPointMoveTo(intx,inty);返回值:先前位置的CPoint對象。參數(shù):新位置的點坐標x和y。說明:本函數(shù)只將畫筆的當前位置移動到坐標x和y處,不繪制直線段。(2)繪制直線段函數(shù)類屬:CDC::MoveTo原型:BOOLLineTo(intx,inty);返回值:如果畫線成功,返回“非0”;否則,返回“0”。參數(shù):直線段終點坐標x和y。
說明:①本函數(shù)從當前位置繪制直線段,但不包括(x,y)點。不包括終點坐標是為了實現(xiàn)多線段連接時公共點的處理,即采用起點閉區(qū)間,終點開區(qū)間的處理方法。②繪制直線段函數(shù)的參數(shù)不包含顏色,直線段的顏色通過畫筆來指定。例2-3
從起點P0(20,30)到終點P1(200,300)畫一條1像素寬的綠色直線,效果如圖2-14所示。voidCTestView::OnDraw(CDC*pDC){ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
//TODO:adddrawcodefornativedatahere CPenNewPen,*pOldPen; NewPen.CreatePen(PS_SOLID,1,RGB(0,255,0)); pOldPen=pDC->SelectObject(&NewPen);
pDC->MoveTo(20,30);
pDC->LineTo(200,300);
pDC->SelectObject(pOldPen);NewPen.DeleteObject();}圖2-14例2-3效果圖4.繪制矩形函數(shù)
類屬:CDC::Rectangle原型:BOOLRectangle(intx1,inty1,intx2,inty2);返回值:如果調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):x1、y1是矩形的左上角點坐標,x2、y2是矩形的右下角點坐標。說明:(1)該函數(shù)使用當前畫刷填充矩形內(nèi)部,并使用當前畫筆繪制矩形邊界線。(2)矩形不包括右邊界坐標和下邊界坐標,即矩形寬度為x2-x1,高度為y2-y1。例2-4
繪制左上角點為P0(100,100),右下角點為P1(600,300)的矩形。矩形邊界線為1像素寬的藍線,矩形內(nèi)部填充為綠色,效果如圖2-15所示。voidCTestView::OnDraw(CDC*pDC){ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
//TODO:adddrawcodefornativedatahereCPenNewPen,*pOldPen;
NewPen.CreatePen(PS_SOLID,1,RGB(0,0,255));
pOldPen=pDC->SelectObject(&NewPen);
CBrushNewBrush,*pOldBrush;
NewBrush.CreateSolidBrush(RGB(0,255,0));
pOldBrush=pDC->SelectObject(&NewBrush);pDC->Rectangle(100,100,600,300);
pDC->SelectObject(pOldBrush);
NewBrush.DeleteObject();pDC->SelectObject(pOldPen);
NewPen.DeleteObject();
}圖2-15例2-4效果圖5.繪制橢圓函數(shù)類屬:CDC::Ellipse原型:BOOLEllipse(intx1,inty1,intx2,inty2);返回值:如調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):(x1,y1)和(x2,y2)分別是限定橢圓范圍的
外切矩形左上角點的坐標和右下角點坐標。說明:(1)該函數(shù)使用當前畫刷填充橢圓內(nèi)部,并用當前畫筆繪制橢圓邊界線。(2)MFC中沒有專門的畫圓函數(shù),只是把圓繪制為外切矩形為正方形的橢圓。
例2-5
在屏幕客戶區(qū)內(nèi)繪制內(nèi)切橢圓,橢圓的形狀依據(jù)客戶區(qū)形狀而改變。橢圓邊界為1像素寬的藍線,內(nèi)部填充為綠色,效果如圖2-16所示。圖2-16例2-5效果圖{ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
//TODO:adddrawcodefornativedatahere
CRectrect; GetClientRect(&rect); CPenNewPen,*pOldPen; NewPen.CreatePen(PS_SOLID,1,RGB(0,0,255)); pOldPen=pDC->SelectObject(&NewPen); CBrushNewBrush,*pOldBrush; NewBrush.CreateSolidBrush(RGB(0,255,0)); pOldBrush=pDC->SelectObject(&NewBrush); pDC->Ellipse(rect.left,rect.top,rect.right,rect.bottom);//繪制橢圓
pDC->SelectObject(pOldBrush); NewBrush.DeleteObject();pDC->SelectObject(pOldPen); NewPen.DeleteObject();}6.繪制多邊形函數(shù)類屬:CDC::Polygon原型:BOOLPolygon(LPPOINTlpPoints,intnCount);返回值:如調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):lpPoints指定多邊形頂點數(shù)組指針,數(shù)組中的每個頂點是一個POINT結構或CPoint對象;nCount指定多邊形頂點數(shù)組中的頂點個數(shù)。
說明:(1)該函數(shù)使用當前畫刷填充多邊形內(nèi)部,并使用當前畫筆繪制多邊形邊界線。(2)多邊形自動閉合。例2-6繪制4個頂點分別位于屏幕客戶區(qū)左部中點、上部中點、右部中點和下部中點的多邊形。多邊形邊界線為3像素寬的藍線,內(nèi)部填充為綠色,效果如圖2-17所示。圖2-17例2-6效果圖voidCTestView::OnDraw(CDC*pDC){ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
//TODO:adddrawcodefornativedatahereCRectrect; GetClientRect(&rect); CPenNewPen,*pOldPen; NewPen.CreatePen(PS_SOLID,3,RGB(0,0,255)); pOldPen=pDC->SelectObject(&NewPen); CBrushNewBrush,*pOldBrush; NewBrush.CreateSolidBrush(RGB(0,255,0)); pOldBrush=pDC->SelectObject(&NewBrush);CPointP[4];//定義多邊形頂點數(shù)組
P[0].x=rect.left;P[0].y=rect.top+rect.Height()/2;//計算左部中點
P[1].x=rect.left+rect.Width()/2;P[1].y=rect.top;
//計算頂部中點
P[2].x=rect.right;P[2].y=rect.top+rect.Height()/2;
//計算右部中點
P[3].x=rect.left+rect.Width()/2;P[3].y=rect.bottom;
//計算下部中點
pDC->Polygon(P,4);
//繪制多邊形
pDC->SelectObject(pOldBrush); NewBrush.DeleteObject();
pDC->SelectObject(pOldPen); NewPen.DeleteObject();}7.填充矩形函數(shù)類屬:CDC::FillSolidRect原型:voidFillSolidRect(LPCRECTlpRect,COLORREFclr);voidFillSolidRect(intx,inty,intcx,intcy,COLORREFclr);返回值:無。參數(shù):lpRect是指向矩形的指針,或是一個Rect結構或CRect對象;x,y指定矩形的左上角點坐標,cx、cy指定矩形的寬度和高度;clr指定填充顏色。說明:(1)該函數(shù)使用當前畫刷填充整個矩形,包括左邊界和上邊界,但不包括右邊界和下邊界。(2)當前畫筆對該函數(shù)不起作用。例2-7使用FillRect函數(shù)將屏幕客戶區(qū)填充為黑色,效果如圖2-18所示。圖2-17例2-8效果圖voidCTestView::OnDraw(CDC*pDC){ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
//TODO:adddrawcodefornativedatahere
CRectrect; GetClientRect(&rect); pDC->FillSolidRect(rect,RGB(0,0,0));}
說明:在繪制真實感圖形時,為了更好地表示光照及紋理的效果,常將屏幕背景色填充為黑色,本例提供了一個改變屏幕背景色的方法,第3行語句使用黑色填充屏幕客戶區(qū)。改變RGB宏表示的顏色,可以更換屏幕的背景色。8.路徑層函數(shù)⑴打開路徑層類屬:CDC::BeginPath原型:BOOLBeginPath();返回值:如調(diào)用成功,返回“非0”;否則,返回“0”。 參數(shù):無。說明:打開一個路徑層。⑵關閉路徑層類屬:CDC::EndPath原型:BOOLEndPath();返回值:如調(diào)用成功,返回“非0”;否則,返回“0”。 參數(shù):無。說明:關閉當前路徑層,并將該路徑層選入設備上下文。(3)填充路徑層類屬:CDC::FillPath原型:BOOLFillPath();返回值:如調(diào)用成功,返回“非0”;否則,返回“0”。 參數(shù):無。說明:①用當前畫刷和填充模式填充路徑層內(nèi)部,同時關閉已經(jīng)打開的路徑層。路徑層填充完畢后,將被設備上下文廢棄。 ②該函數(shù)不繪制路徑層輪廓。(4)繪制并填充路徑層類屬:CDC::StrokeAndFillPath原型:BOOLStrokeAndFillPath();返回值:如調(diào)用成功,返回“非0”;否則,返回“0”。 參數(shù):無。
說明:使用當前畫筆繪制路徑層的輪廓,并使用當前畫刷填充路徑層內(nèi)部,同時關閉已經(jīng)打開的路徑層。例2-8繪制3個相同的多邊形。第一個和第二個多邊形使用MoveTo()函數(shù)和LineTo()函數(shù)繪制,分別使用FillPath()函數(shù)和StrokeAndFillPath()函數(shù)填充;第三個多邊形使用Polygon()函數(shù)繪制。多邊形邊界線為1像素寬的藍線,內(nèi)部填充為綠色,試觀察3種填充效果的異同,如圖2-19所示。圖2-19例2-8效果圖voidCTestView::OnDraw(CDC*pDC){ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
//TODO:adddrawcodefornativedatahere
//繪制第一個多邊形,用FillPath()函數(shù)填充
CPointP[7];
//聲明多邊形頂點數(shù)組
P[0]=CPoint(220,140);P[1]=CPoint(140,60); P[2]=CPoint(100,160);P[3]=CPoint(140,270); P[4]=CPoint(200,200);P[5]=CPoint(240,270);P[6]=CPoint(320,120); CPenNewPen,*pOldPen; NewPen.CreatePen(PS_SOLID,1,RGB(0,0,255)); pOldPen=pDC->SelectObject(&NewPen); CBrushNewBrush,*pOldBrush; NewBrush.CreateSolidBrush(RGB(0,255,0)); pOldBrush=pDC->SelectObject(&NewBrush);
pDC->BeginPath(); pDC->MoveTo(P[0]); for(inti=1;i<7;i++)pDC->LineTo(P[i]); pDC->LineTo(P[0]); pDC->EndPath(); pDC->FillPath();//繪制第二個多邊形,用StrokeAndFillPath()函數(shù)填充
P[0]=CPoint(520,140);P[1]=CPoint(440,60); P[2]=CPoint(400,160);P[3]=CPoint(440,270); P[4]=CPoint(500,200);P[5]=CPoint(540,270);P[6]=CPoint(620,120); pDC->BeginPath(); pDC->MoveTo(P[0]); for(i=1;i<7;i++) pDC->LineTo(P[i]); pDC->LineTo(P[0]); pDC->EndPath(); pDC->StrokeAndFillPath();
//繪制第三個多邊形,用畫刷填充
P[0]=CPoint(820,140);P[1]=CPoint(740,60); P[2]=CPoint(700,160);P[3]=CPoint(740,270); P[4]=CPoint(800,200);P[5]=CPoint(840,270);P[6]=CPoint(920,120); pDC->Polygon(P,7); pDC->SelectObject(pOldBrush); NewBrush.DeleteObject(); pDC->SelectObject(pOldPen); NewPen.DeleteObject();}9.繪制Bezier曲線函數(shù)
類屬:CDC::PolyBezier原型:BOOLPolyBezier(constPOINT*lpPoints,intnCount);返回值:如調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):lpPoints是樣條的終止點和控制點組成的POINT結構數(shù)組指針;nCount表示lpPoints數(shù)組中的數(shù)組元素個數(shù)。說明:(1)每段Bezier樣條要求2個中間控制點和1個終止控制點。第一段Bezier樣條還要求1個起始控制點。(2)PolyBezier()函數(shù)可以繪制一段或多段Bezier樣條。繪制多段Bezier樣條時,除第一段樣條使用4個控制點外,其余各段樣條僅使用3個控制點,因為后面一段樣條總把前一段樣條的終止控制點作為自己的起始控制點。只繪制一段Bezier樣條時,參數(shù)lpPoints應為4。繪制n段Bezier樣條時,參數(shù)lpPoints應為n×3+1。(3)PolyBezier函數(shù)使用當前畫筆繪制,并且一般不閉合,因此不填充內(nèi)部。(4)PolyBezier()函數(shù)不更新當前點位置。(5)繪制兩段Bezier樣條時,存在第二段Bezier樣條與第一段Bezier樣條的連接問題,稱為Bezier樣條的拼接。拼接兩段Bezier樣條時,需要滿足一定的連續(xù)條件。如果第二段Bezier樣條任意給定,那么兩段Bezier樣條之間只能在拼接點處滿足端點連續(xù),兩段Bezier樣條不能光滑過渡;如果需要滿足光滑過渡,則要求第一段Beizer樣條的最后兩個控制點和第二段Bezier樣條的第1個控制點共線。
例2-9
給定圖2-20所示7個控制點P0(200,400)、P1(300,200)、P2(600,100)、P3(650,300)、P5(1100,400)、P6(900,120)。使用黑色畫筆繪制控制多邊形,使用綠色畫筆繪制兩段Bezier樣條。要求兩段Bezier樣條光滑連接,也就是說P4控制點與P2、P3控制點共線。設P4點的x坐標為600,請根據(jù)直線方程計算P4點的y坐標并繪制光滑拼接的兩段Bezier樣條。圖2-20例2-9效果圖#defineROUND(d)int(d+0.5)voidCTestView::OnDraw(CDC*pDC){ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
//TODO:adddrawcodefornativedatahere
CRectrect; CPointp[7];p[0]=CPoint(100,400);p[1]=CPoint(200,200);p[2]=CPoint(500,100);p[3]=CPoint(550,300);doublek=(p[3].y-p[2].y)/(p[3].x-p[2].x);doublex=600,y=k*(x-p[3].x)+p[3].y;
p[4]=CPoint(ROUND(x),ROUND(y));p[5]=CPoint(900,400);p[6]=CPoint(800,120);for(inti=0;i<7;i++) { if(0==i) pDC->MoveTo(p[i]); else pDC->LineTo(p[i]); pDC->Ellipse(p[i].x-5,p[i].y-5,p[i].x+5,p[i].y+5); CPenNewPen,*pOldPen; NewPen.CreatePen(PS_SOLID,1,RGB(0,255,0));
pOldPen=pDC->SelectObject(&NewPen); pDC->PolyBezier(p,7);
pDC->SelectObject(pOldPen);}(1)創(chuàng)建位圖函數(shù)10.位圖操作函數(shù)
類屬:CBitmap::CreateCompatibleBitmap原型:BOOLCreateCompatibleBitmap(CDC*pDC,intnWidth,intnHeight);返回值:如調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):pDC是顯示設備上下文指針,nWidth是位圖寬度,nHeight是位圖高度。說明:①CreateCompatibleBitmap()函數(shù)為指定的顯示設備上下文創(chuàng)建一個指定寬度與高度的兼容位圖,該位圖可以選為與指定的顯示設備上下文兼容的內(nèi)存設備上下文的當前位圖。②本函數(shù)創(chuàng)建的是黑色單色位圖,可以使用FillSolidRect()函數(shù)將其填充為白色。(2)導入位圖函數(shù)類屬:CBitmap::LoadBitmap原型:BOOLLoadBitmap(UINTnIDResource);返回值:如果調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):nIDResource是位圖資源的ID編號。
說明:該函數(shù)將資源中以nIDResource標識的位圖加載給CBitmap對象。(3)創(chuàng)建與指定設備兼容的內(nèi)存設備上下文函數(shù)類屬:CDC::CreateCompatibleDC原型:virtualBOOLCreateCompatibleDC(CDC*pDC);返回值:如果調(diào)用成功,返回“非0”;否則,返回“0”。 參數(shù):pDC是顯示設備上下文的指針。(4)檢索位圖信息函數(shù)類屬:CBitmap::GetBitmap原型:intGetBitmap(BITMAP*pBitMap);返回值:如果調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):pBitMap是指向BITMAP結構體的指針。BITMAP結構體定義了邏輯位圖的高度、寬度、顏色格式和位圖的字節(jié)數(shù)據(jù)。typedefstructtagBITMAP{
int
bmType;
//位圖類型
int
bmWidth;//位圖寬度
int
bmHeight;//位圖高度
int
bmWidthBytes;//每行掃描線上的字節(jié)數(shù)
BYTE
bmPlanes;//顏色位面數(shù)
BYTE
bmBitsPixel;//每個位面上定義一個像素的顏色數(shù)
LPVOID
bmBits;//位圖數(shù)據(jù)指針}BITMAP;(5)傳送位圖函數(shù)類屬:CDC::BitBlt原型:BOOLBitBlt(intx,inty,intnWidth,intnHeight,CDC*pSrcDC,intxSrc,intySrc,DWORDdwRop);返回值:如調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):x,y是目標矩形區(qū)域的左上角點坐標,nWidth和nHeight是目標區(qū)域和源圖像的寬度和高度,pSrcDC是源設備上下文的指針,xSrc和ySrc是源位圖的左上角點坐標,dwRop是光柵操作碼,光柵操作碼有多種,最常用的是SRCCOPY,表示將源位圖直接復制到目標設備上下文中。例2-10在屏幕客戶區(qū)內(nèi)顯示一幅位圖,如圖2-21所示的“博創(chuàng)研究所”位圖(1024×768)。請使用BitBlt()或StretchBlt()函數(shù)繪制。圖2-21“博創(chuàng)研究所”位圖voidCTestView::OnDraw(CDC*pDC){ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc); //TODO:adddrawcodefornativedatahere CRectrect
GetClientRect(&rect);
CDCmemDC;
CBitmapNewBitmap,*pOldBitmap;
NewBitmap.LoadBitmap(IDB_BITMAP1);
memDC.CreateCompatibleDC(pDC);
pOldBitmap=memDC.SelectObject(&NewBitmap);
BITMAPbmp;
NewBitmap.GetBitmap(&bmp);
pDC>StretchBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
memDC.SelectObject(pOldBitmap);}圖2-22ResourceView標簽頁中選擇位圖圖2-23導入位圖對話框圖2-24例2-10效果圖11.文本函數(shù)(1)設置文本顏色函數(shù)類屬:CDC::SetTextColor原型:virtualCOLORREFSetTextColor(COLORREFcrColor);返回值:原文本顏色的RGB值。參數(shù):crColor是新的文本顏色的RGB值。(2)設置文本背景顏色函數(shù)類屬:CDC::SetBkColor原型:virtualCOLORREFSetBkColor(COLORREFcrColor);返回值:原文本背景色的RGB值。參數(shù):crColor是新的文本背景顏色的RGB值。(3)設置文本背景模式函數(shù)類屬:CDC::SetBkMode原型:intSetBkMode(intnBkMode);返回值:原文本背景模式。參數(shù):nBkMode可以取OPAQUE或TRANSPARENT。說明:OPAQUE模式用當前背景顏色填充文本背景,這是默認的文本背景模式;TRANSPARENT模式保持文本背景透明。(4)輸出文本函數(shù)類屬:CDC::TextOut原型:BOOLTextOut(intx,inty,constCString&str);返回值:如果調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):x,y是文本的起點邏輯坐標,str是CString對象。(5)設置文本格式函數(shù)類屬:CString::Format原型:voidFormat(LPCTSTRlpszFormat,...);返回值:無。參數(shù):lpszFormat是格式控制字符串,如%d、%f、%c等。說明:CString類的Forma()成員函數(shù)可將任意數(shù)據(jù)類型轉(zhuǎn)換為CString字符串,該函數(shù)常用于輸出數(shù)值型數(shù)據(jù)。(6)文本的屬性文本的屬性主要有字樣、風格和字體。字樣是指宋體、楷體、隸書等特定模式。風格表現(xiàn)為字體的粗細、是否傾斜等特點。字體是指邏輯字體的定義,包括高度、寬度等。在使用邏輯字體輸出文本時,系統(tǒng)會采將邏輯字體映射為最匹配的物理字體。邏輯字體的屬性可以使用LOGFONT結構來描述。(7)創(chuàng)建字體類屬:CDC::CreateFontIndirect原型:BOOLCreateFontIndirect(constLOGFONT*lpLogFont);返回值:如果調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):lpLogFontLOGFONT結構體的指針。說明:該函數(shù)使用指向LOGFONT的指針初始化字體對象。例2-11
設置屏幕客戶區(qū)背景色為黑色。在點(20,20)處以“幼圓”字體輸出白色文本“基于MFC研究計算機圖形學”。改變文字顏色為紅色,文本背景色為黃色,在(100,80)處整數(shù)(5,8)。設置文本背景模式為TRANSPARENT,改變文本顏色為綠色,在(100,120)處輸出浮點數(shù)(5.2,8.3),效果如圖2-25所示。圖2-25例2-11效果圖voidCTestView::OnDraw(CDC*pDC){ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
//TODO:adddrawcodefornativedatahere
CRectrect; GetClientRect(&rect); pDC->FillSolidRect(rect,RGB(0,0,0)); pDC->SetTextColor(RGB(255,255,255)); CStringdata,str="基于MFC研究計算機圖形學"; CFontNewFont,*pOldFont;LOGFONTlf; memset(&lf,0,sizeof(LOGFONT)); lf.lfHeight=30; lf.lfCharSet=GB2312_CHARSET; strcpy((lf.lfFaceName),"幼圓");NewFont.CreateFontIndirect(&lf); pOldFont=pDC->SelectObject(&NewFont); pDC->TextOut(20,20,str);
pDC->SelectObject(pOldFont); NewFont.DeleteObject(); pDC->SetTextColor(RGB(255,0,0)); pDC->SetBkColor(RGB(255,255,0)); inta1=5,b1=8; doublea2=5.2,b2=8.3; data.Format("%d,%d",a1,b1); pDC->TextOut(100,80,data);
pDC->SetTextColor(RGB(0,255,0)); pDC->SetBkMode(TRANSPARENT);
data.Format("%f,%f",a2,b2); pDC->TextOut(100,120,data);}2.3設備上下文的調(diào)用與釋放1.獲得設備上下文類屬:CWnd::GetDC()原型:CDC*GetDC();返回值:如果調(diào)用成功,返回當前屏幕客戶區(qū)的設備上下文指針;否則,返回NULL。參數(shù):無。2.釋放設備上下文類屬:CWnd::ReleaseDC原型:intReleaseDC(CDC*pDC);返回值:如果調(diào)用成功,返回“非0”;否則,返回“0”。參數(shù):pDC是被釋的設備上下文指針。2.4雙緩沖機制雙緩沖是一種基本的動畫技術。創(chuàng)建一個與屏幕顯示設備上下文兼容的內(nèi)存設備上下文,先將圖形繪制到內(nèi)存設備上下文中,然后調(diào)用BitBlt()函數(shù)將內(nèi)存位圖復制到屏幕上,同時禁止背景刷新,可實現(xiàn)平滑動畫,消除了屏幕閃爍現(xiàn)象。例2-12
將圖2-26所示的一幅火焰動畫位圖flame.bmp加載到MFC的資源中。flame.bmp位圖的大小為1560×140,由26幅小位圖組成,每幅小位圖的大小為60×140。請使用雙緩沖機制逐幅讀入小位圖,間隔20毫秒依次顯示在客戶區(qū)中心,后一幅小位圖取代前一幅小位圖產(chǎn)生火焰動畫。效果如圖2-27所示。圖2-26火焰動畫位圖
圖2-27例2-12效果圖1.設計思路將flame.bmp位圖加載到資源中,取ID為IDB_FLAME。在OnDraw()函數(shù)中創(chuàng)建雙緩沖,一個緩沖器為內(nèi)存設備上下文,另一個緩沖器為顯示設備上下文。將flame.bmp位圖沿寬度方向按60×140大小依次讀出小位圖,在定時器的作用下繪制到屏幕中心(位圖中心取為屏幕客戶區(qū)中心),后一幅小位圖取代前一幅小位圖形成火焰動畫。2.建立雙緩沖voidCTestView::OnDraw(CDC*pDC){ CTestDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
//TODO:adddrawcodefornativedatahere CRectrect; GetClientRect(&rect); pDC->FillSolidRect(rect,RGB(0,0,0));
CDCmemDC; memDC.CreateCompatibleDC(pDC); CBitmapNewBitmap,*pOldBitmap;NewBitmap.LoadBitmap(IDB_FLAME);
pOldBitmap=memDC.SelectObject(&NewBitmap); BITMAPbmp; NewBitmap.GetBitmap(&bmp);
intnBmpWidth=bmp.bmWidth/(m_TotalBmps);
pDC->BitBlt((rect.Width()-nBmpWidth)/2,(rect.Height()-bmp.bmHeight)/2,nBmpWidth,rect.Height(),&memDC,m_Num*bmp.bmWidth/m_TotalBmps,0,SRCCOPY);
memDC.SelectObject(pOldBitmap);}3.設置定時器在重載函數(shù)OnInitialUpda
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年臺州學院單招職業(yè)適應性測試題庫及參考答案詳解一套
- 2026年湖南軟件職業(yè)技術大學單招職業(yè)適應性測試題庫含答案詳解
- 2026年呂梁職業(yè)技術學院單招職業(yè)適應性考試題庫及答案詳解一套
- 2026年河南機電職業(yè)學院單招職業(yè)傾向性測試題庫附答案詳解
- 羅莊社工面試題及答案
- 關于銀行面試題目及答案
- 國家開放大學《健康教育與健康促進》形考任務1-4答案
- 2025年哈爾濱工業(yè)大學未來工學院招聘5人備考題庫及完整答案詳解一套
- 重慶市開州區(qū)事業(yè)單位2025年面向應屆高校畢業(yè)生考核招聘工作人員備考題庫及完整答案詳解1套
- 企業(yè)規(guī)章管理制度范本(3篇)
- 四川省成都市郫都區(qū)2024-2025學年八年級上學期期末檢測物理試題(含答案)
- 15分鐘應急救援圈
- 2026年華北電力大學輔導員及其他崗位招聘31人歷年題庫附答案解析
- 河北省唐山市2024-2025學年高二上學期期末考試數(shù)學試卷(含答案)
- 押運證的考試題及答案
- 2026年遼寧農(nóng)業(yè)職業(yè)技術學院單招職業(yè)技能測試題庫帶答案詳解
- 2025年消防心理測試測試題及答案
- 2025年及未來5年市場數(shù)據(jù)中國溶聚丁苯橡膠市場前景預測及投資規(guī)劃研究報告
- 2025年食品安全衛(wèi)生監(jiān)督員考試題庫及答案指導
- 2025年掌上華醫(yī)(醫(yī)院版)自測三基三嚴考試題庫及答案(含各題型)
- 2025年廣東省常用非金屬材料檢測技術培訓考核核心考點速記速練300題(附答案)
評論
0/150
提交評論