Visual C++基礎教程課件:圖形輸出_第1頁
Visual C++基礎教程課件:圖形輸出_第2頁
Visual C++基礎教程課件:圖形輸出_第3頁
Visual C++基礎教程課件:圖形輸出_第4頁
Visual C++基礎教程課件:圖形輸出_第5頁
已閱讀5頁,還剩127頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

圖形輸出10.1圖形設備接口

10.2畫筆和畫刷

10.3繪圖

10.4文本和字體

習題

10.1.1設備環(huán)境當Windows應用程序在屏幕、打印機或其它輸出設備上畫圖時,它并不是將像素直接輸出到設備上,而是將圖形繪制到由設備環(huán)境(DeviceContext,DC)表示的邏輯顯示平面上。設備環(huán)境是Windows定義和管理的一個數(shù)據(jù)結(jié)構(gòu),它包含了GDI需要的、與邏輯顯示平面相關(guān)的所有繪圖屬性,如當前的畫筆、畫刷、字體和位圖等圖形對象及其屬性,以及顏色、背景和繪圖模式,這些屬性決定了最后輸出的效果??梢詫⒃O備環(huán)境看做是一個繪圖工具箱,它包括畫布及各種各樣的繪圖工具。在繪圖之前,可以改變設備環(huán)境的屬性,例如可以選擇不同顏色、大小的字體,設置畫筆的粗細和顏色。10.1圖形設備接口在繪圖之前,應用程序必須從GDI獲取設備環(huán)境的句柄,并將其傳遞給GDI繪圖函數(shù)。若無有效的設備環(huán)境句柄,則GDI不會輸出任何內(nèi)容。采用傳統(tǒng)的調(diào)用API編程方式,在響應消息WM_PAINT的處理函數(shù)中調(diào)用API函數(shù)BeginPaint,以獲取設備環(huán)境句柄,使用結(jié)束后調(diào)用EndPaint釋放設備環(huán)境。在其它函數(shù)中繪圖,需要調(diào)用GetDC獲取設備環(huán)境,調(diào)用ReleaseDC釋放設備環(huán)境。

MFC的CDC類將Windows設備環(huán)境和獲取設備環(huán)境句柄的GDI函數(shù)封裝在一起,因此,在使用MFC編寫Windows應用程序時,不必直接獲取設備環(huán)境句柄,而是通過創(chuàng)建一個設備環(huán)境對象并調(diào)用它的成員函數(shù)來畫圖。CDC的派生類如CPaintDC、CClientDC和CWindowDC則代表Windows應用程序使用的不同類型的設備環(huán)境。MFC提供的CDC派生類如表10-1所示。表10-1CDC的派生類類名描述CPaintDC用于在窗口客戶區(qū)域繪圖(僅限于OnPaint處理函數(shù))CClientDC用于在窗口客戶區(qū)域繪圖(除OnPaint外的任何處理程序)CWindowDC用于在窗口類任意地方繪圖,包括非客戶區(qū)域CMetaFileDC用于向GDI元文件繪圖除了CMetaFileDC外,這些類的構(gòu)造函數(shù)和析構(gòu)函數(shù)均調(diào)用相應的函數(shù)獲取和釋放設備環(huán)境,從而使得設備環(huán)境的使用非常方便。若在棧上定義設備環(huán)境對象,當對象的作用域結(jié)束時,則其析構(gòu)函數(shù)會被自動調(diào)用,釋放設備環(huán)境。如:CClientDCdc(this);//利用dc繪圖若使用new動態(tài)創(chuàng)建設備環(huán)境對象,如:

CClientDC*pDC=newCClientDC(this);則在設備環(huán)境使用結(jié)束時必須使用delete刪除對象:

deletepDC;以便調(diào)用析構(gòu)函數(shù)釋放設備環(huán)境。由于設備環(huán)境是Windows操作系統(tǒng)中的資源,因此要確保應用程序使用完設備環(huán)境后及時釋放。否則,會由于系統(tǒng)中資源數(shù)目的限制而影響其它應用程序的運行。

CPaintDC類代表了一個窗口的繪圖畫面,允許在窗口的客戶區(qū)域畫圖。但CPaintDC只能在消息WM_PAINT的處理函數(shù)OnPaint中使用,而不能在其它地方使用。

CClientDC類代表一個窗口客戶區(qū)設備環(huán)境,窗口的客戶區(qū)是指窗口中不包括邊框、標題欄、菜單欄、工具欄和狀態(tài)欄的區(qū)域。坐標點(0,0)通常指客戶區(qū)的左上角。如果需要在整個窗口區(qū)域繪圖,則應使用CWindowDC類,它代表了整個窗口設備環(huán)境,包括窗口邊框、標題欄、菜單欄、工具欄和狀態(tài)欄等非客戶區(qū)和客戶區(qū)。坐標點(0,0)通常指窗口的左上角。在MFC應用程序中,視圖窗口沒有非客戶區(qū),因此,CWindowDC更適用于框架窗口。有時可以使用CWindowDC創(chuàng)建特殊效果,例如用戶自己繪制標題欄和帶圓角的窗口?!纠?0.1】CPaintDC、CClientDC和CWindowDC的使用示例。程序的創(chuàng)建過程如下:

(1)利用AppWizard創(chuàng)建一個單文檔界面應用程序,項目名設置為EX10_1。

(2)利用ClassWizard在視圖類CEX10_1View中添加消息WM_PAINT的處理函數(shù)OnPaint,并添加如下黑體所示的代碼:

voidCEX10_1View::OnPaint()

{ CPaintDCdc(this);//devicecontextforpainting CRectrect; GetClientRect(&rect); dc.Ellipse(rect);

}

(3)利用ClassWizard在視圖類CEX10_1View中添加消息WM_LBUTTONDOWN的處理函數(shù)OnLButtonDown,并添加如下黑體所示的代碼:

voidCEX10_1View::OnLButtonDown(UINTnFlags,CPointpoint)

{ CClientDCdc(this); dc.LineTo(100,100); dc.TextOut(100,100,"在視圖窗口客戶區(qū)繪圖");

}

(4)利用菜單編輯器添加菜單命令“在框架窗口繪圖”(菜單編輯器的使用見第11章),取消其Pop-up屬性,設置其ID為IDM_DRAW。利用ClassWizard在框架窗口類CMainFrame中添加此菜單的COMMAND消息處理函數(shù)OnDraw,并添加如下黑體所示的代碼:

voidCMainFrame::OnDraw()

{ CWindowDCdc(this); CPenpen(PS_SOLID,4,RGB(255,0,0)); dc.SelectObject(&pen); dc.LineTo(100,100); dc.TextOut(100,100,"在框架窗口內(nèi)繪圖");

}

(5)編譯、鏈接和運行程序。當在視圖窗口中單擊鼠標左鍵和執(zhí)行菜單命令“在框架窗口繪圖”后,結(jié)果如圖10-1所示。圖10-1例10-1程序運行結(jié)果10.1.2設備環(huán)境的屬性獲取圖形設備接口的設備環(huán)境后,就可以在設備環(huán)境上繪圖,但當使用CDC的輸出函數(shù)繪圖時,在屏幕上(或打印機等其它設備)上所看到的某些輸出特性依賴于設備環(huán)境當前的屬性。例如,當使用TextOut輸出文字時,可以在函數(shù)中指定輸出的坐標位置和要輸出的字符串,但沒有規(guī)定文本顏色和字體及字體的大小,這些由設備環(huán)境當前的屬性來決定。因此,當獲取GDI設備環(huán)境后,還需要設置設備環(huán)境的屬性。設備環(huán)境的屬性包括以下內(nèi)容:

·相關(guān)的GDI對象,如畫筆(Pen)、畫刷(Brush)、字體(Font)、位圖(Bitmap)、調(diào)色板(Palette)和區(qū)域(Region)。

·決定繪圖時縮放尺寸的映射模式和繪圖模式。

·其它各種細節(jié),例如文本顏色、背景顏色等。當創(chuàng)建一個設備環(huán)境對象時,它有一些默認的屬性,例如,輸出文本時有默認的字體及大小、顏色等。當需要輸出其它特性時,在繪圖之前需要通過CDC類的成員函數(shù)進行相應的屬性設置。表10-2列出了設備環(huán)境中常用的一些屬性和訪問與設置這些屬性的CDC類成員函數(shù)。表10-2常用的設備環(huán)境屬性及其相關(guān)函數(shù)屬性默認值設置獲取文本顏色BLACKSetTextColorGetTextColor背景顏色WHITESetBkColorGetBkColor背景模式OPAQUESetBkModeGetBkMode映射模式MM_TEXTSetMapModeGetMapMode繪圖模式R2_COPYPENSetROP2GetROP2當前位置(0,0)MoveToGetCurrentPosition當前畫筆BLACK_PENSelectObjectSelectObject當前畫刷WHITE_BRUSHSelectObjectSelectObject當前字體SYSTEM_FONTSelectObjectSelectObject不同的CDC輸出函數(shù)以不同的方式使用設備環(huán)境的屬性。例如,在使用Rectangle函數(shù)畫矩形時,GDI用當前的畫筆畫矩形區(qū)域的邊界,并用當前的畫刷填充該矩形區(qū)域。所有的文本輸出函數(shù)都采用當前的字體,文本顏色和背景顏色決定了在文本輸出時所有用到的顏色。文本顏色決定了字符的顏色,而背景顏色決定字符后面的填充色。在使用LineTo函數(shù)畫虛線或點劃線時,背景顏色還用于填充線段間的空隙,或用來填充陰影畫筆所畫標記間的空白處。如果想忽略背景顏色,可將背景模式設置為透明(TRANSPARENT),例如:

dc.SetBkMode(TRANSPARENT);

MFC提供6個GDI對象類用于改變設備環(huán)境的相應屬性,它們是CBitmap、CBrush、CFont、CPalette、CPen和CRgn,它們分別代表位圖、畫刷、字體、調(diào)色板、畫筆和區(qū)域。這些類的繼承關(guān)系如圖10-2所示。在應用程序中可以創(chuàng)建這些GDI對象,然后通過調(diào)用CDC::SelectObject成員函數(shù)將創(chuàng)建的GDI對象選入設備環(huán)境,從而改變設備環(huán)境的屬性。除非調(diào)用SelectObject或SelectStockObject改變當前畫筆、畫刷或字體,否則,GDI將使用設備環(huán)境的默認值。例如,要繪制一個紅色的圓,并使其具有10個像素寬的黑色邊框,則要創(chuàng)建一個10個像素點寬的黑色畫筆和一個紅色的畫刷,并在調(diào)用CDC::Ellipse畫圓之前用SelectObject將它們選入設備環(huán)境。圖10-2GDI對象類的繼承關(guān)系例如將例10.1視圖類中響應消息WM_LBUTTONDOWN的處理函數(shù)OnLButtonDown修改為如下形式,則在窗口客戶區(qū)單擊鼠標時可繪制一個10像素寬的黑色邊框的紅色圓:

voidCEX10_1View::OnLButtonDown(UINTnFlags,CPointpoint)

{ //TODO:Addyourmessagehandlercodehereand/orcalldefault CClientDCdc(this); CPenpen(PS_SOLID,10,RGB(0,0,0)); //創(chuàng)建10像素寬的黑色畫筆

dc.SelectObject(&pen);

//將畫筆選入設備環(huán)境

CBrushbrush(RGB(255,0,0));//創(chuàng)建紅色的畫刷

dc.SelectObject(&brush); dc.Ellipse(0,0,100,100);

}除了可以自定義GDI對象并選入設備環(huán)境來改變設備環(huán)境的屬性外,Windows預先定義了一些畫筆、畫刷、字體以及其它一些GDI對象,這些對象是Windows的一部分,可以直接使用。通過調(diào)用CDC::SelectStockObject成員函數(shù)將庫存GDI對象選入設備環(huán)境,其函數(shù)原型為:

virtualCGdiObject*SelectStockObject(intnIndex);

函數(shù)返回指向設備環(huán)境以前的GDI對象的指針。參數(shù)“nIndex”指定要選入設備環(huán)境的庫存對象。表10-3列出了可以選入設備環(huán)境的畫筆和畫刷庫存對象。表10-3Windows庫存的畫筆和畫刷nIndex參數(shù)描述BLACK_BRUSH黑色畫刷DKGRAY_BRUSH深灰色畫刷GRAY_BRUSH灰色畫刷HOLLOW_BRUSH與NULL_BRUSH相同LTGRAY_BRUSH淺灰色畫刷NULL_BRUSH空畫刷(內(nèi)部不填充)WHITE_BRUSH白色畫刷BLACK_PEN黑色畫筆NULL_PEN空畫筆(不畫)WHITE_PEN白色畫筆10.1.3繪圖模式當向GDI設備環(huán)境的邏輯顯示面輸出圖形時,GDI并不是簡單地輸出圖形像素點的顏色,而是將輸出圖形畫筆顏色和圖形內(nèi)部的填充色與顯示平面目標位置上的顏色進行某種邏輯運算,然后將運算的結(jié)果顏色輸出。設備環(huán)境的繪圖模式屬性決定了當前設備環(huán)境的邏輯運算。繪圖模式使用CDC::SetROP2成員函數(shù)進行設置,其函數(shù)原型為:

intSetROP2(intnDrawMode);其中:參數(shù)“nDrawMode”用來指定新的繪圖模式。表10-4列出了一些常用的繪圖模式。函數(shù)返回設備環(huán)境先前的繪圖模式。設備環(huán)境默認的繪圖模式是R2_COPYPEN。表10-4設備環(huán)境的繪圖模式繪圖模式(nDrawMode)執(zhí)行的運算R2_BLACK最后像素總是黑色R2_WHITE最后像素總是白色R2_NOP屏幕像素顏色保持不變(最后像素=屏幕像素)R2_NOT屏幕顏色的反色(最后像素=NOT屏幕像素)R2_COPYPEN畫筆的顏色(最后像素=畫筆)R2_NOTCOPYPEN畫筆顏色的反色(最后像素=NOT畫筆)R2_MERGEPENNOT最后像素=(NOT屏幕像素)OR畫筆R2_MASKPENNOT最后像素=(NOT屏幕像素)AND畫筆R2_MERGENOTPEN最后像素=(NOT畫筆)OR屏幕像素R2_MASKNOTPEN最后像素=(NOT畫筆)AND屏幕像素R2_MERGEPEN最后像素=畫筆OR屏幕像素R2_MASKPEN最后像素=畫筆AND屏幕像素R2_XORPEN最后像素=畫筆XOR屏幕像素R2_NOTXORPEN最后像素=NOT(畫筆XOR屏幕像素)表中的“畫筆”指輸出圖形畫筆顏色和圖形內(nèi)部的填充色。繪圖模式有時非常有用,例如在游戲設計中,如果想恢復游戲背景,只需要將繪圖模式設置為R2_XORPEN,然后再次輸出前景圖像即可?!纠?0.2】繪圖模式使用示例。設計一個單文檔界面應用程序,項目名為EX10_2。利用ClassWizard在視圖類CEX10_2View中添加消息WM_LBUTTONDOWN的處理函數(shù)OnLButtonDown,并添加如下黑體所示的代碼:

voidCEX10_2View::OnLButtonDown(UINTnFlags,CPointpoint)

{ //TODO:Addyourmessagehandlercodehereand/orcalldefault CClientDCdc(this); CRectrect(10,10,60,160); dc.SelectStockObject(BLACK_BRUSH); dc.Rectangle(rect); rect.OffsetRect(50,0); dc.SelectStockObject(WHITE_BRUSH); dc.Rectangle(rect); rect.OffsetRect(50,0); dc.SelectStockObject(BLACK_BRUSH); dc.Rectangle(rect); dc.SelectStockObject(NULL_BRUSH); dc.SetROP2(R2_NOT); dc.Ellipse(10,10,160,160);}運行程序時,在視圖窗口單擊鼠標左鍵,則結(jié)果如圖10-3所示。圖10-3繪圖模式的使用示例10.1.4映射模式與坐標轉(zhuǎn)換

1.坐標系統(tǒng)當在應用程序中輸出圖形或文本時,需要指定圖形或文本繪制的位置,這時指定的坐標位置是參照某個坐標系統(tǒng)的。在Windows中,坐標系統(tǒng)大致可以分為兩大類:設備坐標系統(tǒng)和邏輯坐標系統(tǒng)。設備坐標系統(tǒng)是指顯示器或打印機等物理設備的坐標系統(tǒng)。不同的物理設備具有不同的坐標單位、坐標原點和坐標方向,對于顯示設備,坐標單位為像素,設備上的(0,0)始終在顯示平面的左上角,X軸正向向右,Y軸正向向下。在設備坐標系統(tǒng)中又有三種相互獨立的坐標系統(tǒng):屏幕坐標系統(tǒng)、窗口坐標系統(tǒng)和用戶區(qū)坐標系統(tǒng)。這些坐標系統(tǒng)均以像素點來表示度量的單位,X軸向右為正,Y軸向下為正。屏幕坐標系統(tǒng)使用整個屏幕坐標區(qū)作為坐標系統(tǒng)。窗口坐標系統(tǒng)使用包括邊框在內(nèi)的應用程序的窗口作為坐標區(qū)域,窗口的左上角為坐標原點。用戶區(qū)坐標系統(tǒng)是最經(jīng)常使用的坐標系統(tǒng),以窗口的客戶區(qū)域作為坐標區(qū)域。調(diào)用CWnd::ClientToScreen和CWnd::ScreenToClient函數(shù)可實現(xiàn)用戶區(qū)坐標值與屏幕坐標值之間的轉(zhuǎn)換。當調(diào)用一個返回屏幕坐標值的Windows函數(shù),并需要將返回的屏幕坐標值再傳遞給需要用戶區(qū)坐標值的函數(shù)(或者反過來)時,就需要使用上面兩個函數(shù)。邏輯坐標系統(tǒng)是與GDI設備環(huán)境相關(guān)的坐標系統(tǒng),這種坐標不考慮具體的物理設備。例如,當應用程序繪制一條從A點到B點的直線時,傳遞給MoveTo()?和LineTo()?函數(shù)的坐標不是指定屏幕上的物理位置,而是其在設備環(huán)境中定義的邏輯坐標系統(tǒng)中的坐標。當使用CDC成員函數(shù)在某個設備環(huán)境中繪圖時,圖形輸出到一個邏輯窗口,GDI需要將在邏輯窗口中的邏輯坐標轉(zhuǎn)換為設備坐標才能將圖形在顯示器或打印機上輸出。從邏輯坐標值到設備坐標值的轉(zhuǎn)換方式,由設備環(huán)境的映射模式屬性決定。

2.映射模式映射模式是設備環(huán)境的屬性,用于確定從邏輯坐標到設備坐標的轉(zhuǎn)換方式。在繪圖時,Windows根據(jù)當前設備環(huán)境的映射模式將邏輯坐標轉(zhuǎn)換為設備坐標。映射模式定義了邏輯單位的實際大小、坐標增長方向,所有映射模式的坐標原點一般在圖形輸出區(qū)域的左上角。Windows支持8種不同的映射模式,如表10-5所示。表10-5Windows映射模式映射模式邏輯單位坐標軸方向MM_TEXT一個像素X軸正向向右,Y軸正向向下MM_LOMETRIC0.1毫米X軸正向向右,Y軸正向向上MM_HIMETRIC0.01毫米X軸正向向右,Y軸正向向上MM_LOENGLISH0.01英寸X軸正向向右,Y軸正向向上MM_HIENGLISH0.001英寸X軸正向向右,Y軸正向向上MM_TWIPS1/1440英寸X軸正向向右,Y軸正向向上MM_ISOTROPIC用戶自定義,X軸與Y軸的單位比例為1:1用戶自定義MM_ANISOTROPIC用戶自定義,X軸與Y軸的單位比例可以任意用戶自定義映射模式的坐標原點一般在圖形輸出區(qū)域的左上角,在使用MM_LOMETRIC、MM_HIMETRIC、MM_LOENGLISH、MM_HIENGLISH和MM_TWIPS時,由于它們的Y軸都為正向向上,為了使輸出可見,Y坐標必須使用負值。例如:

dc.Rectangle(0,0,200,-100);

因此,在使用非MM_TEXT映射模式時,如果應用程序的輸出不可見,應檢查Y坐標值的正負號。設備環(huán)境默認的映射模式為MM_TEXT。如果需要使用其它的映射模式,可以調(diào)用CDC::SetMapMode成員函數(shù)來設置新的映射模式。使用CDC::GetMapMode成員函數(shù)可以獲取當前的映射模式。例如,以下語句將映射模式設置為MM_LOMETRIC,并畫一個半徑為2.5厘米的圓:

dc.SetMapMode(MM_LOMETRIC);

dc.Ellipse(0,0,500,-500);除了6種固定比例的映射模式外,Windows還提供了兩種可變比例的映射模式:MM_ISOTROPIC和MM_ANISOTROPIC,允許用戶改變比例因子和原點,即用戶自己決定從邏輯坐標轉(zhuǎn)換為設備坐標的方式。

MM_ISOTROPIC和MM_ANISOTROPIC映射模式常用于根據(jù)窗口尺寸按比例自動調(diào)整圖形輸出的大小,在用戶改變窗口的大小時,輸出的內(nèi)容也會改變大小。例如,下面是一個單文檔應用程序的OnDraw函數(shù),它首先使用MM_

ANISOTROPIC映射模式將窗口客戶區(qū)大小(無論其為多大)映射為邏輯坐標的500單位寬和500單位長,坐標原點位于窗口左上角,X軸正向向右,Y軸正向向下;然后畫一個與窗口邊框相接的橢圓。當用戶改變窗口大小時,橢圓始終占據(jù)整個窗口。

voidCEX10_2View::OnDraw(CDC*pDC)

{ CRectclientRect; GetClientRect(clientRect); pDC->SetMapMode(MM_ANISOTROPIC); pDC->SetWindowExt(500,500); pDC->SetViewportExt(clientRect.Width(),clientRect.Height()); pDC->Ellipse(0,0,500,500);

}

如果希望Y軸正向向上,則只需要將傳遞給SetWindowExt或SetViewportExt的Y坐標值取反即可。

CDC::SetWindowExt函數(shù)以邏輯尺寸設置“窗口范圍”,其函數(shù)原型為:

virtualCSizeSetWindowExt(intcx,intcy);

virtualCSizeSetWindowExt(SIZEsize);其中,參數(shù)“cx”和“cy”或“size”以邏輯單位指定窗口大小。

CDC::SetViewportExt函數(shù)以設備單位或像素點設置“視口范圍”,其函數(shù)原型為:

virtualCSizeSetViewportExt(intcx,intcy);

virtualCSizeSetViewportExt(SIZEsize);

Windows對邏輯坐標值和設備坐標值的相互轉(zhuǎn)換,是根據(jù)用戶指定的窗口邏輯尺寸(窗口范圍)、實際尺寸(視口范圍)以及坐標原點位置進行的。設定窗口范圍和視口范圍時,實際上是在自己確定縮放比例。一般說來,視口范圍是畫圖所在窗口的大小(以像素點數(shù)目計算),而窗口范圍是指以邏輯單位表示的窗口尺寸。

MM_ISOTROPIC和MM_ANISOTROPIC映射模式的區(qū)別在于前者始終保持1:1的縱橫比,后者X和Y比例因子可以分別改變。使用SetWindowExt和SetViewportExt時要注意:在MM_ISOTROPIC映射模式下,應該首先調(diào)用SetWindowExt。而在MM_ANISOTROPIC映射模式下,窗口范圍和視口范圍中先設置哪個都無關(guān)緊要。

3.坐標原點在各種映射模式下,設備環(huán)境的原點默認位于顯示平面的左上角。用戶可以改變坐標原點的位置。MFC的CDC類提供了兩個函數(shù)用于移動坐標原點。CDC::SetWindowOrg用于移動窗口原點,CDC::SetViewportOrg用于移動視口原點,一般情況下,只能使用其中之一。SetViewportOrg的參數(shù)為設備坐標值,SetViewportOrg(x,y)將視口原點移至(x,y),即通知Windows將邏輯原點(0,0)映射成設備點(x,y)。SetWindowOrg的參數(shù)為邏輯坐標值,SetWindowOrg(x,y)將窗口原點移至(x,y),即通知Windows將邏輯點(x,y)映射成設備原點(0,0),即顯示平面左上角?!纠?0.3】移動原點示例。創(chuàng)建一單文檔界面應用程序,項目名為EX10_3。在視圖類CEX10_3View的OnDraw函數(shù)中添加如下代碼:

voidCEX10_3View::OnDraw(CDC*pDC)

{ CRectclientRect; GetClientRect(clientRect); pDC->SetMapMode(MM_LOMETRIC); pDC->SetViewportOrg(clientRect.Width()/2,clientRect.Height()/2); pDC->Ellipse(-250,250,250,-250);

}

程序首先設置映射模式為MM_LOMETRIC,然后將邏輯原點移至窗口客戶區(qū)中心,再在窗口客戶區(qū)中繪制一半徑為2.5厘米的圓,如圖10-4所示。圖10-4例10.3運行結(jié)果

4.坐標轉(zhuǎn)換當設置好設備環(huán)境的映射模式及邏輯平面原點后,便可以調(diào)用CDC成員函數(shù)繪圖,大多數(shù)CDC成員函數(shù)使用邏輯坐標作為參數(shù)。但Windows應用程序不能只在邏輯坐標下工作,經(jīng)常還涉及到設備坐標,例如鼠標單擊消息處理函數(shù)OnLButtonDown中的point參數(shù)表示單擊時鼠標的坐標,是設備坐標。許多MFC成員函數(shù)使用設備坐標作為參數(shù),例如CWnd成員函數(shù)、CRect的成員函數(shù)等都是用設備坐標作為參數(shù)。因此,應用程序經(jīng)常需要在設備坐標和邏輯坐標之間進行切換。調(diào)用CDC::LPtoDP函數(shù)可將邏輯坐標值轉(zhuǎn)換為設備坐標值,函數(shù)原型為:

voidLPtoDP(LPPOINTlpPoints,intnCount=1)const;

voidLPtoDP(LPRECTlpRect)const;

voidLPtoDP(LPSIZElpSize)const;其中,參數(shù)“l(fā)pPoints”為指向由點構(gòu)成的數(shù)組,數(shù)組中的每一個點是一個POINT結(jié)構(gòu)變量或CPoint對象;“nCount”為數(shù)組中點的數(shù)目;“l(fā)pRect”為指向RECT結(jié)構(gòu)變量或CRect對象的指針,常用于將一個矩形從邏輯坐標轉(zhuǎn)換為設備坐標;“l(fā)pSize”為指向SIZE結(jié)構(gòu)變量或CSize對象的指針。調(diào)用CDC::DPtoLP函數(shù)可將設備坐標值轉(zhuǎn)換為邏輯坐標值,函數(shù)原型為:

voidDPtoLP(LPPOINTlpPoints,intnCount=1)const;

voidDPtoLP(LPRECTlpRect)const;

voidDPtoLP(LPSIZElpSize)const;

在響應鼠標單擊的命中測試調(diào)用CRect::PtInRect或CRgn::PtInRegion時,設備坐標和邏輯坐標之間的轉(zhuǎn)換是必不可少的。鼠標單擊后得到的鼠標指針位置坐標是設備坐標值,如果在某個設備環(huán)境中畫了一個圓并且想知道鼠標單擊是否發(fā)生在這個圓內(nèi),則需要將圓的邏輯坐標值轉(zhuǎn)換為設備坐標值,或?qū)⑹髽藛螕臬@得的設備坐標值轉(zhuǎn)換為邏輯坐標值。否則就是在比較兩個不同種類的坐標,不能保證測試結(jié)果的正確性?!纠?0.4】編寫一個單文檔界面應用程序,通過用鼠標單擊客戶區(qū)域的圓來改變圓的顏色。程序的創(chuàng)建過程如下:

(1)利用AppWizard創(chuàng)建一單文檔界面應用程序,項目名為EX10_4。

(2)在視圖類CEX10_4View類的頭文件EX10_4View.h中添加數(shù)據(jù)成員:private: intm_nColor; //畫圓時畫刷的顏色

CRectm_rectEllipse; //圓的外接矩形在視圖類的構(gòu)造函數(shù)中對添加的數(shù)據(jù)成員進行初始化:

CEX10_4View::CEX10_4View():m_rectEllipse(0,0,200,-200)

{ m_nColor=GRAY_BRUSH;

}

(3)在視圖類的OnDraw成員函數(shù)中設置畫刷顏色及映射模式,并用外接矩形畫圓:

voidCEX10_4View::OnDraw(CDC*pDC)

{ pDC->SelectStockObject(m_nColor); pDC->SetMapMode(MM_LOMETRIC); pDC->Ellipse(m_rectEllipse);

}

(4)利用ClassWizard在視圖類CEX10_4View中添加消息WM_LBUTTONDOWN的處理函數(shù)OnLButtonDown,并添加如下黑體代碼:

voidCEX10_4View::OnLButtonDown(UINTnFlags,CPointpoint)

{ CClientDCdc(this); dc.SetMapMode(MM_LOMETRIC); CRectrectDevice=m_rectEllipse; dc.LPtoDP(&rectDevice);

//將外接矩形轉(zhuǎn)換為設備坐標值

if(rectDevice.PtInRect(point)) //測試鼠標單擊是否在圓的外接矩形內(nèi)

{ if(m_nColor==GRAY_BRUSH) m_nColor=WHITE_BRUSH; else m_nColor=GRAY_BRUSH; InvalidateRect(rectDevice);

//使矩形無效,更新視圖

}

}

(5)編譯、鏈接和運行程序,程序運行結(jié)果如圖10-5所示。圖10-5例10.4運行結(jié)果10.1.5顏色設置對于繪圖來說,顏色是一個重要的屬性。WindowsGDI提供了一個獨立于硬件的顏色接口。程序中提供的是一個邏輯顏色,GDI將程序代碼中的邏輯顏色映射為計算機或其它輸出設備上的適當顏色(近似色)或顏色組合(通過抖動實現(xiàn))。

Windows使用一個32位無符號長整數(shù)來表示一種顏色,其數(shù)據(jù)類型為COLORREF。使用顏色的GDI函數(shù)都接受COLORREF參數(shù)。COLORREF的3個低位字節(jié)分別指定顏色的紅、綠和藍分量,高位字節(jié)為0,每一個分量的取值范圍為0~255,如圖10-6所示。圖10-6COLORREF類型的顏色值除了可以直接使用COLORREF類型的32位長整數(shù)指定顏色值外,Windows還提供了RGB宏用于設置顏色,將紅、綠、藍分量轉(zhuǎn)換為COLORREF類型的顏色值,其使用格式為:

COLORREFRGB(BYTEbRed,BYTEbGreen,BYTEbBlue);其中,參數(shù)“bRed”、“bGreen”和“bBlue”分別用于指定顏色的紅、綠、藍分量,它們的取值范圍為0~255。例如,RGB(0,0,0)表示黑色,RGB(255,255,255)表示白色,即長整數(shù)0x00FFFFFF??梢允褂肎etRValue、GetGValue和GetBValue宏從COLORREF值中提取出8位紅、綠、藍分量。

GDI對COLORREF值的處理依賴于輸出硬件設備的顏色分辨率和使用顏色的設備環(huán)境。如果輸出硬件設備支持24位顏色,例如視頻適配器,則COLORREF值可以直接轉(zhuǎn)換成屏幕上的顏色。但若視頻適配器只支持每像素4位或6位顏色,則會根據(jù)當前調(diào)色板的設置決定一次能同時顯示的顏色。例如,標準的VGA可以顯示262144種不同的顏色(紅、綠、藍各6位),但是運行在分辨率為640×480模式下時只能同時顯示16種不同的顏色值。更普遍的情況是視頻適配器可以顯示超過1670萬種顏色,但只能同時顯示256種顏色??梢酝瑫r顯示的256種顏色根據(jù)RGB值確定并編入適配器的硬件調(diào)色板中。其中有16種顏色是所有調(diào)色板都支持的“純”色,如表10-6所示。表10-6標準“純”色RGB值顏色RGB分量值顏色RGB分量值黑色0,0,0中灰色128,128,128深紅色128,0,0紅色255,0,0深綠色0,128,0綠色0,255,0深黃色128,128,0黃色255,255,0深藍色0,0,128藍色0,0,255深紫色128,0,128紫色255,0,255深青色0,128,128青色0,255,255淺灰色192,192,192白色255,255,255當視頻適配器不支持繪圖函數(shù)中指定的COLORREF值時,GDI使用簡單的顏色匹配算法將每個COLORREF值都映射給最接近的純色。如果給生成畫筆的函數(shù)傳遞一個COLORREF值,Windows就會給畫筆分配一個最接近的純色;如果將COLORREF值傳遞給生成畫刷的函數(shù)而又找不到匹配的純色時,Windows就會使用純色來抖動,以實現(xiàn)畫刷顏色。許多使用顏色的GDI函數(shù)都使用COLORREF類型值作為參數(shù)。例如影響文本顯示顏色的兩個設備環(huán)境屬性文本顏色(前景色)和背景顏色可以分別使用CDC::SetTextColor和CDC::SetBkColor函數(shù)進行設置,其函數(shù)原型為:

virtualCOLORREFSetTextColor(COLORREFcrColor);

virtualCOLORREFSetBkColor(COLORREFcrColor);這兩個函數(shù)將參數(shù)crColor設置為當前文本顏色(背景顏色)并返回先前的文本顏色(背景顏色)。例如:

COLORREFoldTextColor;

oldTextColor=pDC->SetTextColor(RGB(255,0,0));

//設置文本顏色為紅色

pDC->SetBkColor(RGB(0,0,0)); //設置背景顏色為黑色

pDC->TextOut(0,0,“黑色背景紅色文字”);

//輸出文字

pDC->SetTextColor(oldTextColor);

//恢復原來的文本顏色10.2畫

刷當在設備環(huán)境中繪制直線和曲線以及矩形、橢圓等封閉圖形時,Windows用設備環(huán)境當前的畫筆繪制直線和曲線以及封閉圖形的邊框,使用設備環(huán)境當前的畫刷填充圖形內(nèi)部。設備環(huán)境的默認畫筆畫出的是一個像素點寬的黑色實線,默認的畫刷為白色畫刷WHITE_BRUSH。如果需要使用不同風格的畫筆和畫刷,則必須重新為設備環(huán)境定義畫筆和畫刷,并在繪圖之前將其選入設備環(huán)境。在MFC應用程序中使用畫筆和畫刷的步驟大致相同:

(1)創(chuàng)建畫筆(畫刷)。

(2)將創(chuàng)建的畫筆(畫刷)選入設備環(huán)境。

(3)輸出圖形。

(4)還原設備環(huán)境先前的畫筆(畫刷)。10.2.1畫筆

MFC的CPen類封裝了GDI畫筆。

1.創(chuàng)建畫筆創(chuàng)建畫筆最簡單的方法是構(gòu)造一個CPen對象,并給它傳遞定義畫筆的參數(shù),包括畫筆的樣式、寬度和顏色。CPen類的構(gòu)造函數(shù)原型如下:

CPen(intnPenStyle,intnWidth,COLORREFcrColor);其中,參數(shù)“nPenStyle”用于指定畫筆的樣式,其取值如表10-7所示;“nWidth”用于指定畫筆寬度;參數(shù)“crColor”用于指定畫筆的顏色。例如:

CPenpen(PS_DASH,1,RGB(255,0,0));

創(chuàng)建畫筆的第二種方法是調(diào)用CPen的缺省構(gòu)造函數(shù)構(gòu)造一個沒有初始化的CPen對象,并調(diào)用CPen::CreatePen函數(shù)創(chuàng)建畫筆。CreatePen函數(shù)原型為:BOOLCreatePen(intnPenStyle,intnWidth,COLORREFcrColor);例如:

CPenpen;

pen.CreatePen(PS_DASH,1,RGB(255,0,0));

創(chuàng)建畫筆的第三種方法是構(gòu)造一個沒有初始化的CPen對象,填寫描述畫筆特性的LOGPEN結(jié)構(gòu),然后調(diào)用CPen::CreatePenIndirect函數(shù)創(chuàng)建畫筆。例如:

CPenpen;

LOGPENlogPen;

logPen.lopnStyle=PS_DASH;

logPenlopnWidth=1;

logPen.lopnColor=RGB(255,0,0);

pen.CreatePenIndirect(&logPen);

創(chuàng)建畫筆需要三個特性參數(shù):樣式、寬度和顏色。上述三個例子創(chuàng)建的都是寬度為1的紅色虛線畫筆。傳遞給CPen構(gòu)造函數(shù)和CreatePen的第一個參數(shù)用于指定畫筆的樣式,即線的類型。表10-7列出了畫筆樣式。表10-7畫筆的基本樣式樣式說明樣式說明PS_SOLID實線PS_DASHDOTDOT雙點劃線PS_DASH虛線PS_NULL空筆PS_DOT點線PS_INSIDEFRAME邊框內(nèi)實線PS_DASHDOT點劃線傳遞給CPen構(gòu)造函數(shù)和CreatePen函數(shù)的第二個參數(shù)用于指定畫筆的寬度。畫筆寬度以邏輯值指定,其單位取決于當前設備環(huán)境的映射模式??梢詣?chuàng)建任意寬度的PS_SOLID、PS_NULL和PS_INSIDEFRAME樣式畫筆,但PS_DASH、PS_DOT、PS_DASHDOT和PS_DASHDOTDOT樣式畫筆則必須是一個邏輯單位寬。無論是何種映射模式,若將畫筆寬度指定為0,則任一樣式的畫筆寬度都為一個像素點寬。

2.選入畫筆創(chuàng)建好畫筆后必須將其選入設備環(huán)境才能使用。函數(shù)CDC::SelectObject用于將GDI對象選入設備環(huán)境。SelectObject在CDC類中是一個重載函數(shù),用于選擇畫筆的函數(shù)原型為:

CPen*SelectObject(CPen*pPen);其中,參數(shù)“pPen”指向?qū)⒁贿x入設備環(huán)境的畫筆對象。函數(shù)返回指向設備環(huán)境先前的畫筆對象的指針。一般情況下,在使用SelectObject選擇新的畫筆時應保存先前的畫筆對象,以便可以通過其返回值恢復設備環(huán)境先前的屬性。例如:

CPen*pOldPen,NewPen;

NewPen.CreatePen(PS_DASH,1,RGB(255,0,0));

//創(chuàng)建寬度為1的紅色點劃線

pOldPen=pDC->SelectObject(&NewPen);

pDC->Ellipse(0,0,255,255);

3.還原畫筆將畫筆選入設備環(huán)境后,就可以使用該畫筆繪圖。當繪圖結(jié)束后,應該恢復設備環(huán)境先前的屬性,此時只需要再次調(diào)用SelectObject,將上次調(diào)用此函數(shù)時保存的畫筆選入設備環(huán)境即可。例如:

pDC->SelectObject(pOldPen); //還原畫筆由CGdiObject派生類創(chuàng)建的畫筆、畫刷和其它對象都要占用內(nèi)存空間,因此在使用完畢之后一定要刪除它們。如果在棧上創(chuàng)建CPen、CBrush、CFont或其它GDI對象,那么在對象超出其作用域范圍時,相關(guān)的GDI對象就會自動被刪除。如果用new在堆上創(chuàng)建了一個CGdiObject派生類對象,則在特定時刻一定要用delete刪除它,以便調(diào)用它的析構(gòu)函數(shù)。在應用程序中可以通過調(diào)用CGdiObject::DeleteObject顯式地刪除GDI對象,以便釋放其所占用的內(nèi)存資源。如果是庫存對象,即便是由CreateStockObject創(chuàng)建的庫存對象,也沒必要專門去刪除它。例如:

pDC->SelectObject(pOldPen); //還原畫筆

NewPen.DeleteObject(); //刪除創(chuàng)建的畫筆NewPen【例10.5】編寫一個單文檔界面應用程序,用不同樣式、寬度的畫筆繪制圓。利用AppWizard創(chuàng)建一個單文檔界面應用程序,項目名為EX10_5。在類CEX10_5View的成員函數(shù)OnDraw中添加如下黑體代碼,根據(jù)創(chuàng)建的不同樣式和寬度的畫筆繪制圓。

voidCEX10_5View::OnDraw(CDC*pDC)

{ CPen*pOldPen,NewPen; intnPenStyle[]={PS_SOLID,PS_DASH,

PS_DOT,PS_DASHDOT,PS_DASHDOTDOT,

PS_NULL,PS_INSIDEFRAME}; pDC->TextOut(80,10,"用不同樣式的畫筆畫圓"); CRectrect1(50,50,320,320); for(inti=0;i<7;i++) { if(NewPen.CreatePen(nPenStyle[i],1,

RGB(0,0,0)))

//用不同樣式創(chuàng)建畫筆 { pOldPen=pDC->SelectObject(&NewPen);

//將畫筆選入設備環(huán)境

pDC->Ellipse(&rect1); rect1.DeflateRect(20,20,20,20);

//縮小橢圓外接矩形

pDC->SelectObject(pOldPen);

//恢復原來的畫筆

NewPen.DeleteObject();

//刪除GDI對象

} else { MessageBox("創(chuàng)建畫筆失敗!"); } } pDC->TextOut(400,10,"用不同寬度的畫筆畫圓"); CRectrect2(350,50,620,320); for(i=0;i<7;i++) { if(NewPen.CreatePen(PS_SOLID,1+i,RGB(0,0,0))) { pOldPen=pDC->SelectObject(&NewPen); pDC->Ellipse(&rect2); rect2.DeflateRect(20,20,20,20); pDC->SelectObject(pOldPen); NewPen.DeleteObject(); } else MessageBox("創(chuàng)建畫筆失?。?); }

}編譯、鏈接和運行程序,運行結(jié)果如圖10-7所示。圖10-7例10.5運行結(jié)果10.2.2畫刷當在設備環(huán)境中繪制矩形、橢圓等封閉圖形時,Windows使用設備環(huán)境當前的畫刷填充圖形內(nèi)部,設備環(huán)境缺省的畫刷為白色畫刷WHITE_BRUSH。通過創(chuàng)建GDI畫刷并在繪圖之前將其選入設備環(huán)境可以改變圖形的填充顏色和樣式。

MFC的CBrush類封裝了GDI畫刷。畫刷有三種基本類型:純色畫刷、陰影畫刷和圖案畫刷。純色畫刷填充的是單一顏色,如果顯示硬件不支持直接顯示純色畫刷的顏色,則Windows通過抖動處理來模仿該顏色。陰影畫刷采用預先定義的線條圖案填充圖形,預定義的線條圖案共有六種。圖案畫刷使用指定的位圖來填充圖形。創(chuàng)建畫刷的第一種方法是使用類CBrush的構(gòu)造函數(shù)直接創(chuàng)建畫刷。與畫刷的三種類型對應,類CBrush提供了三個不同的構(gòu)造函數(shù)分別用于創(chuàng)建不同類型的畫刷,其原型為:

CBrush(COLORREFcrColor);

CBrush(intnIndex,COLORREFcrColor);

CBrush(CBitmap*pBitmap);

第一個構(gòu)造函數(shù)用于創(chuàng)建純色畫刷,其中的參數(shù)用于指定畫刷的顏色;第二個構(gòu)造函數(shù)用于創(chuàng)建陰影畫刷,兩個參數(shù)分別指定畫刷陰影的樣式和顏色,畫刷陰影樣式共六種,如表10-8所示;第三個構(gòu)造函數(shù)用于創(chuàng)建圖案畫刷,其中的參數(shù)用于指定畫刷所使用的位圖。例如:

CBrushbrush(RGB(255,0,0));創(chuàng)建了一個紅色的純色畫刷。表10-8陰影畫刷的樣式樣式說明HS_BDIAGONAL從左向右45°角向下的陰影HS_CROSS水平和垂直交叉的陰影HS_DIAGCROSS45°角的交叉陰影HS_FDIAGONAL從左向右45°角向上的陰影HS_HORIZONTAL水平陰影HS_VERTICAL垂直陰影在使用陰影畫刷時,Windows使用設備環(huán)境當前的背景色填充陰影線的空白處,默認背景色為白色??梢允褂肅DC::SetBkColor改變設備環(huán)境的背景色,或用SetBkMode將背景模式由OPAQUE改為TRANSPARENT,禁止背景填充。創(chuàng)建畫刷的第二種方法是使用類CBrush的缺省構(gòu)造函數(shù)定義CBrush對象,然后調(diào)用CBrush類中的成員函數(shù)創(chuàng)建畫刷。函數(shù)CreateSolidBrush用于創(chuàng)建純色畫刷,其原型為:

BOOLCreateSolidBrush(COLORREFcrColor);

函數(shù)CreateHatchBrush用于創(chuàng)建陰影畫刷,其原型為:

BOOLCreateHatchBrush(intnIndex,COLORREFcrColor);函數(shù)CreatePatternBrush用于創(chuàng)建圖案畫刷,其原型為:

BOOLCreatePatternBrush(CBitmap*pBitmap);

創(chuàng)建畫刷的第三種方法是構(gòu)造一個沒有初始化的CBrush對象,填寫描述畫刷特性的LOGBRUSH結(jié)構(gòu),然后調(diào)用CPen::CreateBrushIndirect函數(shù)創(chuàng)建畫刷。此函數(shù)可以創(chuàng)建三種類型的畫刷。例如,如下代碼創(chuàng)建一個水平和垂直交叉的紅色陰影線的陰影畫刷:

CBrushbrush;

LOGBRUSHlogBrush;

logBrush.lbStyle=BS_HATCHED;

logBrush.lbColor=RGB(255,0,0);

logBrush.lbHatch=HS_CROSS;

brush.CreateBrushIndirect(&logBrush);為了在繪圖中使用創(chuàng)建的畫刷,在繪圖之前應將其通過CDC::SelectObject函數(shù)選入設備環(huán)境。與畫筆一樣,畫刷使用結(jié)束后應該還原設備環(huán)境先前的畫刷,也可以調(diào)用CGdiObject::DeleteObject顯式刪除畫刷?!纠?0.6】編寫一個單文檔界面應用程序,利用不同的陰影畫刷繪制矩形。利用AppWizard創(chuàng)建一個單文檔應用程序,項目名為EX10_6。在類CEX10_6View的成員函數(shù)OnDraw中添加如下黑體代碼,根據(jù)創(chuàng)建的不同畫刷繪制矩形。

voidCEX10_6View::OnDraw(CDC*pDC)

{ intnIndex[]={HS_BDIAGONAL,HS_CROSS,

HS_DIAGCROSS, HS_FDIAGONAL,HS_HORIZONTAL,

HS_VERTICAL}; char*strIndex[]={“HS_BDIAGONAL”,“HS_CROSS”,

"HS_DIAGCROSS", “HS_FDIAGONAL”,“HS_HORIZONTAL”,

"HS_VERTICAL"}; COLORREFcrColor[]={RGB(255,0,0),RGB(0,255,0),

RGB(0,0,255),

RGB(255,255,0),RGB(255,0,255),RGB(0,255,255)}; CRectrect(10,30,50,60); CBrush*pOldBrush,NewBrush; for(inti=0;i<6;i++) { if(NewBrush.CreateHatchBrush

(nIndex[i],crColor[i])) { pOldBrush=pDC->SelectObject

(&NewBrush); pDC->TextOut(10+120*i,10,strIndex[i]); pDC->Rectangle(&rect); rect.OffsetRect(120,0); pDC->SelectObject(pOldBrush); NewBrush.DeleteObject(); } else MessageBox("創(chuàng)建畫刷失敗"); }

}編譯、鏈接和運行程序,運行結(jié)果如圖10-8所示。圖10-8例10.6運行結(jié)果10.3繪圖在成功設置設備環(huán)境、設備環(huán)境的屬性和選擇繪圖工具后,就可以利用GDI繪圖函數(shù)繪制各種不同的圖形。WindowsGDI繪圖函數(shù)比較多,這些函數(shù)封裝在MFC的CDC類中。CDC中的繪圖函數(shù)使用的坐標都是邏輯坐標。10.3.1繪制點、直線和曲線

MFC的CDC類中包含了許多用來繪制直線和曲線的成員函數(shù)。表10-9列出了一些常用的繪制直線和曲線的成員函數(shù)。表10-9繪制直線和曲線的常用CDC函數(shù)函數(shù)說明MoveTo將當前位置移動到指定坐標。在畫線前設置SetPixel用指定的顏色在指定的坐標畫一個像素點LineTo從當前位置畫一條直線到指定位置,并將當前位置移至直線的終點Arc畫一個弧,畫弧方向為從起點到終點逆時針方向ArcTo畫一個弧并將當前位置移至弧的終點PolyLine畫一條連接多個指定點的折線,不使用也不改變當前位置PolylineTo從當前位置開始畫一條連接多個點的折線,并將當前位置移至折線終點PolyBezier畫一條或多條貝賽爾樣條曲線,不使用也不改變當前位置PolyBezierTo畫一條或多條貝賽爾樣條曲線,第一條樣條曲線從當前位置開始,并將當前位置移至最后一條樣條曲線的終點PolyDraw通過一組點畫一條折線和貝賽爾樣條曲線,并將當前位置移至折線或樣條曲線的終點【例10.7】編寫一個單文檔界面應用程序,在視圖窗口的客戶區(qū)域內(nèi)畫一條正弦曲線。利用AppWizard創(chuàng)建一個單文檔界面應用程序框架,項目名為EX10_7。在視圖類CEX10_7View的實現(xiàn)文件EX10_7View.cpp的開始處添加如下命令:

#include"math.h"

#definePI3.1415926

#defineSEGMENTS500在視圖類CEX10_7View的成員函數(shù)OnDraw中添加如下黑體代碼:

voidCEX10_7View::OnDraw(CDC*pDC)

{ CRectrect; GetClientRect(&rect); //獲取客戶區(qū)域大小

intnWidth=rect.Width(); //計算客戶區(qū)域?qū)挾?/p>

intnHeight=rect.Height(); //計算客戶區(qū)域高度

CPointaPoint[SEGMENTS];//定義畫折線的坐標點數(shù)組

for(inti=0;i<SEGMENTS;i++)

//根據(jù)正弦曲線初始化坐標點

{ aPoint[i].x=(i*nWidth)/SEGMENTS; aPoint[i].y=(int)((nHeight/2)*(1-(sin(2*PI*i/SEGMENTS)))); } pDC->MoveTo(0,nHeight/2); pDC->LineTo(nWidth,nHeight/2); //畫水平坐標軸

pDC->Polyline(aPoint,SEGMENTS);

//畫折線來近似正弦曲線

}編譯、鏈接和運行程序,運行結(jié)果如圖10-9所示。圖10-9例10.7運行結(jié)果在使用這些繪圖函數(shù)時需要注意其繪圖的起點。有些函數(shù)的起點是從當前位置開始的,如LineTo、PolylineTo和PolyBezierTo等。另外,其中有些函數(shù)繪制后不改變當前位置,而另一些函數(shù)會改變當前位置??梢哉{(diào)用CDC::GetCurrentPosition函數(shù)獲取當前位置坐標。所有畫直線和曲線的GDI函數(shù)都有一個特點:不畫最后一個點。例如用下面的語句畫一條從(0,0)到(100,100)的直線:

pDC->MoveTo(0,0);

pDC->LineTo(100,100);則從(0,0)到(99,99)位置上的點都被設置成該直線的顏色,但點(100,100)上的顏色保持不變。如果需要畫出該線的最后一個點,則必須自己再調(diào)用CDC::SetPixel畫一次該點。10.3.2畫封閉圖形

GDI不僅提供了畫直線和曲線的函數(shù),還提供了畫橢圓、矩形、扇形、弦形和多邊形等封閉圖形的函數(shù)。同樣,MFC的CDC類將這些相關(guān)的GDI函數(shù)封裝在類的成員函數(shù)中。表10-10列出了常用的畫封閉圖形的CDC函數(shù)。表10-10用來畫封閉圖形的常用CDC函數(shù)函數(shù)說明Chord畫一個弦形。弦形是由一條弧和連接弧兩個端點的弦構(gòu)成的封閉圖形Ellipse畫一個圓或橢圓Pie繪制扇形。扇形是一條弧和從弧的兩個端點到中心的連線構(gòu)成的封閉圖形Polygon繪制連接兩個或多個頂點的多邊形Rectangle畫直角矩形RoundRect畫圓角矩形在畫這些封閉圖形時,Windows用選入設備環(huán)境的當前畫筆畫圖形的邊界,用選入設備環(huán)境的當前畫刷填充圖形內(nèi)部區(qū)域?!纠?0.8】編寫一個單文檔界面應用程序,在視圖窗口的客戶區(qū)域用扇形顯示用戶對生活質(zhì)量調(diào)查的結(jié)果。在對生活質(zhì)量的調(diào)查中,表示滿意、基本滿意、不滿意和非常不滿意的比例分別為34%、43%、14%和9%。利用AppWizard創(chuàng)建一個單文檔界面應用程序框架,項目名為EX10_8。在視圖類CEX10_8View的實現(xiàn)文件EX10_8View.cpp的開始添加如下命令:

#include"math.h"

#definePI3.1415926

在視圖類CEX10_8View的成員函數(shù)OnDraw中添加如下黑體代碼:

voidCEX10_8View::OnDraw(CDC*pDC)

{ doublefProportion[]={0.34,0.43,0.14,0.09}; CRectrect; GetClientRect(&rect);//將視口原點移至客戶區(qū)中心

pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2); CRectpieRect(-150,-100,150,100); //畫扇形的外接矩形

CBrush*pOldBrush,NewBrush; intnBrushStyle[]={HS_CROSS,HS_BDIAGONAL,

HS_DIAGCROSS,HS_FDIAGONAL}; intx1=0; inty1=-1000; doublefSum=0.0; pDC->SetBkColor(RGB(192,192,192));

//設置填充畫刷間隙的顏色

for(inti=0;i<4;i++) { fSum+=fProportion[i]; doublerad=fSum*2*PI+PI; intx2=(int)(sin(rad)*1000); inty2=(int)(cos(rad)*1000*3)/4; NewBrush.CreateHatchBrush(nBrushStyle[i],RGB(0,0,0)); pOldBrush=pDC->SelectObject(&NewBrush); pDC->Pie(pieRect,CPoint(x1,y1),CPoint(x2,y2)); x1=x2; y1=y2; pDC->SelectObject(pOldBrush); NewBrush.DeleteObject(); }

}

編譯、鏈接和運行程序,程序運行結(jié)果如圖10-10所示。圖10-10例10.8運行結(jié)果10.4文

體在應用程序中文本輸出是必不可少的,WindowsGDI具有豐富的文本輸出能力。事實上,在Windows中,文本也是作為圖形來處理的。文本輸出是按照所選用的字體的格式繪制出來的。所有的GDI文本輸出函數(shù)都使用當前選入設備環(huán)境的字體屬性。在應用程序中除了可以使用系統(tǒng)預定義的字體外,還可以自定義字體,并選入設備環(huán)境。10.4.1文本輸出

WindowsGDI文本處理函數(shù)被封裝在MFC的CDC類中。編程時最常用的文本輸出函數(shù)是CDC::TextOut,其函數(shù)原型為:

virtualBOOLTextOut(intx,inty,LPCTSTRlpszString,intnCount);

BOOLTextOut(intx,inty,constCString&str);該函數(shù)用于在指定邏輯坐標(x,y)處輸出單行文本。此函數(shù)在輸出文本時不能自動換行。要想輸出多行文本可以使用CDC::DrawText函數(shù),其函數(shù)原型為:

virtualintDrawText(LPCTSTRlpszString,intnCount,LPRECTlpRect,UINTnFormat);

intDrawText(constCString&str,LPRECTlpRect,UINTnFormat);其中,參數(shù)“l(fā)pszString”指定要輸出的字符串,如果參數(shù)“nCount為-1,則字符串必須以“\0”結(jié)尾。“nCount”指定輸出的字符個數(shù),若為-1,則函數(shù)自動計算字符個數(shù)?!發(fā)pRect”指定格式化文本的矩形區(qū)域(使用邏輯坐標)。“nFormat”指定格式化文本的方式,如對齊方式、是否單行顯示等(其取值可以參考MSDN)。例如:

pDC->DrawText(“文本輸出示例”,-1,CRect(10,10,200,200),

DT_SINGLELINE|DT_CENTER|DT_VCENTER);將文本在指定的矩形區(qū)域內(nèi)垂直與水平居中顯示為單行。與TextOut函數(shù)工作方式相似的另一個函數(shù)為TabbedTextOut,如果輸出的字符串中包含制表符“\t”,則此函數(shù)將按照指定的制表符位置將其展開為空格。函數(shù)ExtTextOut在指定的矩形區(qū)域內(nèi)輸出文本,此矩形區(qū)域可以被當前背景色填充,也可以作為一個剪裁區(qū)域?qū)ξ谋具M行剪裁。

CDC類中與文本輸出有關(guān)的成員函數(shù)比較多,常用的函數(shù)如表10-11所示。表10-11CDC類中的文本處理函數(shù)函數(shù)說明TextOut在指定位置或當前位置輸出一行文本ExtTextOut在矩形區(qū)域內(nèi)輸出一行文本,并給矩形區(qū)域填充背景色或用矩形區(qū)域剪裁文本TabbedTextOut在指定位置輸出文本,并將字符串中的制表符按指定位置展開DrawText在指定的矩形區(qū)域內(nèi)輸出格式化文本GetTextExtent根據(jù)當前設備環(huán)境的字體屬性計算一行文本的寬度和高度GetTextAlign獲取當前文本的對齊方式SetTextAlign設置顯示文本的對齊方式GetTextMetrics獲取當前字體的規(guī)格(如字符高度、字符平均寬度等)GetTextFace獲取當前字體的字體名SetTextColor設置設備環(huán)境的文本輸出顏色SetBkColor設置設備環(huán)境的背景色,即確定輸出文本下的填充色GetTextCharacterExtra獲取顯示文本的字符間距SetTextCharacterExtra設置輸出文本的字符間距SetTextJustification確定對齊文本時需要增加的寬度10.4.2設置文本的設備環(huán)境屬性當使用GDI文本輸出函數(shù)輸出文本時,GDI設備環(huán)境的屬性決定了文本輸出的效果。默認情況下,文本顏色為黑色,以白色填充文本背景,字符間距被設置為0,文本為左對齊。在輸出文本前可以使用相應的CDC成員函數(shù)改變這些屬性值。函數(shù)SetT

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論