《C++開發(fā)GIS系統(tǒng)》第4章-與繪圖操作有關(guān)的MFC類及操作_第1頁
《C++開發(fā)GIS系統(tǒng)》第4章-與繪圖操作有關(guān)的MFC類及操作_第2頁
《C++開發(fā)GIS系統(tǒng)》第4章-與繪圖操作有關(guān)的MFC類及操作_第3頁
《C++開發(fā)GIS系統(tǒng)》第4章-與繪圖操作有關(guān)的MFC類及操作_第4頁
《C++開發(fā)GIS系統(tǒng)》第4章-與繪圖操作有關(guān)的MFC類及操作_第5頁
已閱讀5頁,還剩86頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第4章與繪圖操作有關(guān)的MFC類及操作ForwithyNew從本章到第10章這七章將介紹用MFCAppWizard產(chǎn)生的應(yīng)用程序Draw的根底上,具體組織一個根本矢量圖形系統(tǒng)的開發(fā)。將討論與矢量圖形系統(tǒng)設(shè)計有關(guān)的類及其主要操作。從矢量圖形系統(tǒng)的類組織、文檔管理、視圖組織、圖形交互繪制、圖形操作、圖形選中、圖形旋轉(zhuǎn)、圖形移動、圖形刪除、圖形存取等各個方面開發(fā)實現(xiàn)一個用于GIS的根本矢量圖形系統(tǒng)。通過本篇的學(xué)習(xí),引導(dǎo)讀者能夠從理論和技術(shù)上掌握根本矢量圖形系統(tǒng)的設(shè)計方法,掌握MFC應(yīng)用程序的設(shè)計技術(shù)。本章各小節(jié)目錄4.1繪圖類4.2繪圖設(shè)備類4.3坐標映射方式4.4窗口和視口4.5其他繪圖類操作函數(shù)在MFC中,有很多與圖形操作有關(guān)的類,在本章中,將對主要與繪圖有關(guān)的MFC類的功能及相關(guān)操作進行介紹。4.1繪圖類繪圖就要用到MFC的類CDC、CPaintDC、CClientDC、CWindowDC等,其中CDC類是根底,另外幾個類是為了特殊應(yīng)用由CDC類派生出來的。用VC++編程的讀者對怎么使用這幾個類往往容易模糊和混淆。這幾個類所包含的具體內(nèi)容,讀者可閱讀有關(guān)類庫說明的用戶手冊。作者感到,首先介紹一下各種情況下該使用哪個類,怎么引用這個類,這些最令人頭疼的問題,對讀者進行程序設(shè)計是非常有用的。4.1.1繪圖類簡介〔1〕CDC類CDC類是CObject類的一個派生類,CDC類是所有繪圖類的基類。CDC類定義了一個設(shè)備描述對象。CDC類提供了對設(shè)備描述對象進行操作的成員函數(shù),以及對與窗口客戶區(qū)有關(guān)的顯示區(qū)進行操作的成員函數(shù)。通過CDC類及其派生類創(chuàng)立的對象,可以利用CDC類的所有成員函數(shù)完成圖形的繪制工作。CDC類提供的成員函數(shù),可以用于對設(shè)備描述對象進行的操作、繪圖工具的使用、圖形設(shè)備界面〔GDI〕的選擇,以及顏色和調(diào)色板的操作。它提供的成員函數(shù)還用于取得和設(shè)置繪圖屬性、映像方式、視口和窗口范圍的操作、坐標的轉(zhuǎn)換、區(qū)域的使用、剪取、畫線,以及繪制圖形、文字等操作??傊?,CDC類中包含了與圖形繪制有關(guān)的大局部操作,為了能適應(yīng)Windows編程時的具體需要,又派生出了下面幾個派生類?!?〕CPaintDC類CPaintDC是CDC類的一個派生類,它用于模擬響應(yīng)Windows消息WM_PAINT的設(shè)備環(huán)境,在這個類中可以使用CDC中的所有函數(shù)。CPaintDC類一般用在函數(shù)OnPaint內(nèi),以響應(yīng)WM_PAINT消息。WM_PAINT消息是當(dāng)窗口的某個區(qū)域需要重畫時激發(fā)的窗口消息。一個用CPaintDC類創(chuàng)立的對象是按以下機制調(diào)用的:Windows的消息循環(huán)機制一直在采集各種消息,當(dāng)接到WM_PAINT消息時,當(dāng)接到WM_PAINT消息時,就自動調(diào)用消息處理函數(shù)OnPaint;在OnPaint函數(shù)中,創(chuàng)建CPaintDC類對象,通過這個類對象使用CDC類的成員函數(shù),完成視圖客戶區(qū)中的圖形繪制操作?!?〕CClientDC類CClientDC類也是CDC類的一個派生類,它為非響應(yīng)Windows消息WM_PAINT的成員函數(shù)提供了一個設(shè)備環(huán)境?!?〕CWindowDC類CWindowDC類也是CDC類的一個派生類,它提供了一個設(shè)備環(huán)境,以便成員函數(shù)在包括非客戶區(qū)在內(nèi)的整個屏幕區(qū)域內(nèi)繪圖。4.1.2幾個繪圖類的主要差異幾個繪圖類的主要區(qū)別表達如下。〔1〕CWindowDC類與CPaintDC、CClientDC類的區(qū)別CWindowDC類與CPaintDC、CClientDC類區(qū)別的一個方面是:用CPaintDC類和CClientDC類的對象繪制圖形時,繪制區(qū)只能是客戶區(qū),而不能在非客戶區(qū),而CWindowDC可以在非客戶區(qū)進行圖形繪制??蛻魠^(qū)和非客戶區(qū)的概念可以通過圖4-1來理解。當(dāng)畫一條起始坐標都在屏幕外且通過屏幕的直線時,用CPaintDC和CClientDC類對象繪制時,只有在客戶區(qū)的直線能夠繪制出來,而用CWindowDC類對象繪制時,直線可以畫在非客戶區(qū)。CWindowDC類一般在框架類〔CMainFrame〕中使用,在視圖類〔如CDrawView類〕中使用CWindowDC類時,由于視圖類只能管理客戶區(qū),所以并不能在非客戶區(qū)進行繪制。CWindowDC類與CPaintDC、CClientDC類區(qū)別的另一個方面是:在CWindowDC繪圖類下,坐標系是建立在整個屏幕上的,在像素坐標方式下,坐標原點在屏幕的左上角;而在CPaintDC和CClientDC繪圖類下,坐標系是建立在客戶區(qū)上的,在像素坐標方式下,坐標原點在客戶區(qū)的左上角。圖4-1中的粗線是分別用CWindowDC類和CClientDC類繪制的直線,直線的起點為〔100,0〕,終點為〔400,600〕,繪制時,框架窗口在屏幕上處于最大狀態(tài)。很明顯,CWindowDC類可以在非客戶區(qū)中進行圖形繪制?!?〕CPaintDC類與CClientDC類的區(qū)別CPaintDC類與CClientDC類對象都是在窗口的客戶區(qū)內(nèi)繪制圖形,但兩者在繪制機制上有著本質(zhì)的區(qū)別。CPaintDC類對象應(yīng)用在OnPaint函數(shù)中,以響應(yīng)Windows的WM_PAINT消息,而CClientDC類對象應(yīng)用在非響應(yīng)消息WM_PAINT的情況下。CPaintDC類響應(yīng)WM_PAINT消息,自動完成繪制,這對維護圖形的完整性有著重要的作用。例如在一個窗口中,已經(jīng)畫有n條直線,這個窗口完整性可能被破壞〔如被對話框覆蓋〕,當(dāng)破壞完整性的程序結(jié)束時〔如覆蓋取消〕,這個窗口就會收到一個WM_PAINT消息,激發(fā)消息處理函數(shù)OnPaint進行圖形繪制。CPaintDC類對象就擔(dān)負著此時的繪制任務(wù)。如果現(xiàn)在想在屏幕上再繪制一條消息〔如用鼠標實時繪制,當(dāng)?shù)诙吸c中鼠標左鍵時完成繪制〕,就要用到CClientDC類對象,這個類可以實時的將圖形繪制到屏幕上。如果用CPaintDC類對象完成同樣的工作,只能發(fā)出消息讓屏幕上包含這條直線的區(qū)域重畫,以把這條直線繪制到屏幕上。當(dāng)然,重畫區(qū)域內(nèi)的其他圖形元素同時也被重畫。4.1.3繪圖類的使用方法〔1〕CDC類因為CDC類不能用窗口對象指針初始化對象,所以一般不直接創(chuàng)立對象,但經(jīng)常用來建立一個內(nèi)存設(shè)備描述對象,創(chuàng)立方法如下:CDCdc;〔2〕CPaintDC類CPaintDC類一般用在窗口類的OnPaint函數(shù)中,可采取如下代碼創(chuàng)立一個CPaintDC類對象:CPaintDCdc(this);以上代碼創(chuàng)立了一個CPaintDC類對象dc,并用當(dāng)前的窗口對象指針this對對象進行了初始化。CClientDC類和CWindowDC也采用這樣的使用方法?!?〕CClientDC類以下代碼創(chuàng)立一個CClientDC類對象:CClientDCdc(this);以上代碼創(chuàng)立了一個CClientDC類對象dc,并采用當(dāng)前窗口對象指針this對對象進行了初始化。〔4〕CWindowDC類CWindowDC類一般在框架類CMainFrame中使用,以下代碼創(chuàng)立一個CWindowDC類對象:CWindowDCdc(this);以上代碼創(chuàng)立了一個CWindowDC類的對象dc,并采用當(dāng)前窗口對象指針this對對象進行了初始化。在應(yīng)用程序中創(chuàng)立CPaintDC、CClientDC、CWindowDC類的對象時,都要用一個參數(shù)來對創(chuàng)立的對象進行初始化,this指針是一個指向當(dāng)前窗口對象的指針,通過這個指針利用窗口的參數(shù)對繪圖類對象進行初始化,以保證繪圖類對象能夠在這個窗口中正確的進行繪圖繪制。4.2繪圖設(shè)備類繪圖設(shè)備類是一些已經(jīng)定義的MFC類??梢詫⑦@些繪圖設(shè)備類創(chuàng)立的對象選入到繪圖類對象中,完成有關(guān)的操作。在MFC中,主要有以下幾個繪圖設(shè)備類:CGdiObject及其派生類CPen、CBrush、CFont、CRgn、CPalette、Cbitmap。本節(jié)將討論這些繪圖設(shè)備類的使用。4.2.1CdiObject類CGdiObject類是CObject類的派生類,它為不同的Windows圖形設(shè)備界面〔GDI〕提供了基類。CGdiObject為它的派生類提供了大局部的操作,可利用這些派生類創(chuàng)立一個特定的GDI對象〔如畫筆、畫刷、字體、位圖等〕。4.2.2CPen類CPen類是CGdiObject類的一個派生類,它模擬畫筆圖形設(shè)備界面。以下是MFC中CPen類的定義:classCPen:publicCGdiObject{DECLARE_DYNAMIC(CPen)public:staticCPen*PASCALFromHandle(HPENhPen);//Constructors構(gòu)造器CPen();CPen(intnPenStyle,intnWidth,COLORREFcrColor);#ifndef_MACCPen(intnPenStyle,intnWidth,constLOGBRUSH*pLogBrush,intnStyleCount=0,constDWORD*lpStyle=NULL);#endifBOOLCreatePen(intnPenStyle,intnWidth,COLORREFcrColor);#ifndef_MACBOOLCreatePen(intnPenStyle,intnWidth,constLOGBRUSH*pLogBrush,intnStyleCount=0,cosntDWORD*lpStyle=NULL);#endifBOOLCreatePenIndirect(LPLOGPENlpLogPen);//AttributesoperatorHPEN()const;intGetLogPen(LOGPEN*pLogPen);#infndef_MACintGetExtLogPen(EXTLOGPEN*pLogPen);#endif//Implementationpublic:virtual~CPen();#ifdef_DEBUGvirtualvoidDump(CDumpContext&dc)const;#endif};以下介紹CPen對象的創(chuàng)立和在繪圖類對象中的引用方法?!?〕創(chuàng)立CPen對象有以下幾種方法來創(chuàng)立一個CPen對象:①創(chuàng)立一個CPen對象,用其成員函數(shù)CreatePen或CreatePenIndirect對其進行初始化。以下是用CreatePen成員函數(shù)初始化一個畫筆的代碼:CPenpen;pen.CreatePen(PS_SOLID,1,RGB(255,0,0));以上代碼創(chuàng)立一個CPen類對象pen,并把這個CPen類對象初始化為實心筆、一個像素寬、紅色。②創(chuàng)立一個CPen對象,并一次性地初始化它的所有參數(shù)。CPenpen(PS_SOLID,1,RGB(255,0,RGB(255,0,0)));用這種方法一次性的創(chuàng)立了一個同樣的CPen對象。③動態(tài)創(chuàng)立一個CPen對象。CPen*pen;pen=newCPen(PS_SOLID,1,RGB(255,0,0));除了CPen對象是動態(tài)分配的外,這種創(chuàng)立方法實際上與②相同。在一個函數(shù)中屢次創(chuàng)立一個CPen對象時,可以采用這種方法。應(yīng)用這種方法時,特別注意操作完畢后要刪除分配的CPen對象:deletepen;不管是采用哪一種方法,都是用三個參數(shù)來初始化畫筆,這三個參數(shù)分別是線型〔nPenStyle〕、線寬〔nWidth〕和顏色〔COLORREFcrColor〕。參數(shù)nPenStyle設(shè)置畫筆畫線的線型,可選的線型如圖4-2所示。注意,線型PS_SASH、PS_DOT、PS_DASHDOT、PS_DASHDOTDOT只有在畫筆寬度為1個邏輯單位時才有效。參數(shù)nWidth設(shè)置以邏輯單位衡量的線寬。參數(shù)crColor設(shè)置畫筆的顏色,顏色通過RGB宏來確定:COLORREFRGB(cRed,cGreen,cBlue);圖4-2nPenStyle可選的線型參數(shù)cRed、cGreen、cBlue分別指定紅、綠、藍三色的相對亮度,每個參數(shù)均賦予0~255之間的值?!?〕在繪圖對象中選入畫筆以在CDrawView::OnDraw(CDC*pDC)函數(shù)中操作為例,在繪圖對象中選入畫筆即CPen對象的方法:voidCDrawView::OnDraw(CDC*pDC){ //畫筆 CPenpen(PS_SOLID,1,RGB(255,0,0));//創(chuàng)立并初始化一個畫筆實例CPen*pOldPen=pDC->SelectObject(&pen);//將畫筆選入繪圖對象 ......//省略各種繪制操作代碼 pDC->SelectObject(pOldPen);//恢復(fù)原來的畫筆}在CClientDC、CWindowDC等其他繪圖對象中,可以用類似的方法來選入CPen對象。4.2.3CBush類CBrush類是CGdiObject的一個派生類,它模擬一個Windows畫刷圖形設(shè)備界面。CBrush類的用法與CPen類似。以下是MFC中CBrush類的定義:classCBrush:publicCGdiObject{DECLARE_DYNAMIC(CBrush);public:staticCBrush*PASCALFromHandle(HBRUSHhBrush);//構(gòu)造函數(shù)CBrush();CBrush(COLORREFcrColor);//CreateSolidBrushCBrush(intnIndex,COLORREFcrColor);//CreateHatchBrushCBrush(CBitmap*pBitmap);//CreatePatternBrushBOOLCreateSolidBrush(COLORREFcrColor);BOOLCreateHatchBrush(intnIndex,COLORREFcrColor);BOOLCreateBrushIndirect(constLOGBRUSH*lpLogBrush);BOOLCreatePatternBrush(CBitmap*pBitmap);BOOLCreateDIBPatternBrush(HGLOBALhPackedDIB,UINTnUsage);BOOLCreateDIBPatternBrush(constvoid*lpPackedDIB,UINTnUsage);BOOLCreateSysColorBrush(intnIndex);//AttributesoperatorHBRUSH()const;intGetLogBrush(LOGBRUSH*pLogBrush);//Implementationpublic:virtual~CBrush();#ifdef_DEBUGvirtualvoidDump(CDumpContext&dc)const;#endif}〔1〕創(chuàng)立CBrush對象CBrush類有四個構(gòu)造函數(shù),本節(jié)只對主要的幾個構(gòu)造函數(shù)進行介紹。以下按照實心、影線及位圖填充幾類畫刷來討論CBrush對象的創(chuàng)立過程。實心畫刷用實心畫刷進行圖形填充時,以這種畫刷的顏色實心填充圖形。與CPen對象類似,可以有幾種創(chuàng)立CBrush對象的方法:①一次性創(chuàng)立。創(chuàng)立CBrush類對象,并利用構(gòu)造對象對對象的參數(shù)進行初始化。CBrushbrush(RGB(255,0,0));②動態(tài)創(chuàng)立。用這種方法創(chuàng)立時,在操作完成后要刪除創(chuàng)立的CBrush對象。CBrush*brush;brush=newCBrush(RGB(255,0,0));......deletebrush;③創(chuàng)立CBrush對象,用函數(shù)CreateSolidBrush對對象進行初始化。CBrushbrush;brush.CreateSolidBrush(RGB(255,0,0));影線畫刷影線畫刷不是用畫刷的顏色實心填充圖形,而是填充不同的陰影圖案,填充方式如圖4-3所示。影線畫刷的創(chuàng)立方法同實心畫刷。圖4-3畫刷的影線方式①一次性創(chuàng)立CBrushbrush(HS_HORIZONTAL,RGB(255,0,0));②動態(tài)創(chuàng)立用這種方法創(chuàng)立的CBrush對象,在操作完成后要刪除CBrush對象。CBrush*brush;brush=newCBrush(HS_HORIZONTAL,RGB(255,0,0));...deletebrush;③創(chuàng)立CBrush對象,用函數(shù)CreateSolidBrush對對象進行初始化。CBrushbrush;brush.CreateSolidBrush(PS_SOLID,RGB(255,0,0));位圖畫刷位圖畫刷用位圖圖像來填充圖形。函數(shù)CreatePatternBrush用來初始化一個位圖畫刷。以下代碼創(chuàng)立一個位圖畫刷,pBitmap指向一個位圖對象:CBrushbrush;brush.CreatePatternBrush(pBitmap);〔2〕在繪圖對象中選入畫刷在繪圖對象中選入畫刷即CBrush對象的操作與選入畫筆的操作相同,我們?nèi)砸栽贑DrawView::OnDraw(CDC*pDC)函數(shù)中操作為例進行介紹:voidCDrawView::OnDraw(CDC*pDC){ CBrushbrush(HS_CROSS,RGB(255,0,0));//創(chuàng)立并初始化一個CBrush對象 CBrush*pOldBrush=pDC->SelectObject(&brush);//將畫刷選入繪圖對象 pDC->SelectObject(pOldBrush);//恢復(fù)原來的畫刷}4.2.4CFont類CFont類是CGdiObject類的一個派生類,它創(chuàng)立字體。以下是MFC中CFont類的定義:classCFont:publicCGdiObject{DECLARE_DYNAMIC(CFont)public:staticCFont*PASCALFromHandle(HFONThFont);//ConstructorsCFont();BOOLCreateFontIndirect(constLOGFONT*lpLogFont);BOOLCreateFont(intnHeight,intnWidth,intnEscapement,intnOrientation,intnWeight,BYTEbItalic,BYTEbUnderline,BYTEcStrikeOut,BYTEnCharSet,BYTEnOutPrecision,BYTEnClipPrecision,BYTEnQuality,BYTEpPitchAndFamily,LPCTSTRlpszFacename);BOOLCreatePointFont(intnPointSize,LPCTSTRlpszFaceName,CDC*pDC=NULL);BOOLCreatePointFontIndirect(constLOGFONT*lpLogFont,CDC*pDC=NULL);//AttributesoperatorHFONT()const;intGetLogFont(LOGFONT*pLogFont);//Implementationpublic:virtual~CFont();#ifdef_DEBUGvirtualvoidDump(CDumpContext&dc)const;#endif};〔1〕創(chuàng)立CFont對象CFont類只有一個構(gòu)造函數(shù),創(chuàng)立一個CFont對象后,必須用成員函數(shù)CreateFont或CreateFontIndirect來初始化CFont對象的參數(shù)。CreateFont函數(shù)的參數(shù)非常多,各個參數(shù)的含義如下:Nheight定義以邏輯單位度量的字體高度。Nwidth定義以邏輯單位度量的字體的平均寬度。NEscapement定義字體標注行的逆時針方向的旋轉(zhuǎn)角度〔以1/10度為單位〕,正常情況〔即水平進行標注時〕的角度為0。當(dāng)標注行逆時針旋轉(zhuǎn)時,字體也旋轉(zhuǎn)同樣的角度。以下是當(dāng)旋轉(zhuǎn)角度為100〔10度〕時顯示的字符串〔圖4-4〕。圖4-4旋轉(zhuǎn)角度為10度時的文本繪制nOrientation定義字體的角度〔以1/10度為單位〕,該角度是一個字符的基線與X軸之間的夾角。當(dāng)Y坐標的值是向下為增加時,計算從X軸開始逆時針方向的角度;相反,當(dāng)Y坐標的值是向上增大時,計算從X軸開始順時針方向的角度。nWeight定義了字體的濃度即字體的粗細程度〔像素數(shù)/100〕。表4-1列出了參數(shù)nWeight的通用常量的值。圖4-5是分別將參數(shù)nWeight取值900和100書寫的同樣文字的比照。bItalic

確定字體是否為斜體。bUnderline確定字體是否加下劃線。bStrikeOut確定字體是否被穿透〔字符中央有一條橫線〕。圖4-6是將參數(shù)bItalic、bUnderline、cStrikeOut設(shè)為1后輸出的字符串。cCharSet指出了字體的字符集。表4-2定義了預(yù)定義的字符集常量的值。nOutputPrecision指出了所要求的輸出精度。該精度確定了輸出與所要求的字體高度、寬度、控制、字符方位及間距的匹配和接近程度。我們所建立的字體的高度、寬度等并不是與實際的參數(shù)確定的值完全相同的,匹配越精確,顯示時花費的時間就越長。這個參數(shù)可以控制匹配和接近程度。一般取以下七個值之一:OUT_CHARACTER_PRECISOUT_DEFAULT_PRECISOUT_DEVICE_PRECISOUT_STRING_PRECISOUT_STROKE_PRECISOUT_TT_PRECISOUT_RASTER_PRECISnClipPrecision指定了所要求的裁剪精度。當(dāng)對圖像的一個區(qū)域進行裁剪時,字體可能正好在裁剪線上。該參數(shù)說明怎樣裁剪位于裁剪區(qū)之外的局部字符。nQuality指出了輸出字體的重量。nPitchAndFamily確定了字體的間距和所屬的族。這個8位參數(shù)的低2位確定了字體的間距,它們可以是DEFAULT_PITCH,F(xiàn)IXED_PITCH或VARIABLE_PITCH。高4位指定了字體族。lpszFacename是一個指向ASZHZ字符串的指針。該字符串確定了目標字體的字型名。該參數(shù)的值一定不能超過30個字節(jié)長度,這個名稱可由用戶任意定義。〔2〕CFont對象的選用以下介紹創(chuàng)立CFont對象和在繪圖對象中選用的過程。仍以在CDrawView::OnDraw(CDC*pDC)函數(shù)中操作為例進行介紹,在函數(shù)中參加以下代碼:voidCDrawView::OnDraw(CDC*pDC){ //字體 CFontfont;//定義一個CFont對象 //以下用各種參數(shù)初始化CFont對象 font.CreateFont(30,15,0,0,200,0,0,0,255,0,0,2,DEFAULT_PITCH,"VC"); CFont*pOldFont=pDC->SelectObject(&font);//將CFont對象選入繪圖對象 pDC->SelectObject(pOldFont);//恢復(fù)繪圖對象中原來的字體對象}4.2.5CRgn類CRgn類是CGdiObject類的一個派生類,它封裝了區(qū)域的種種特性和操作。它是窗口中的橢圓或多邊形區(qū)域的組合,可被用來進行填充、反顯、移動、判定某點是否在區(qū)域內(nèi)等操作。在MFC中CRgn類被定義如下:classCRgn:publicCGdiObject{DECLARE_DYNAMIC(CRgn)public:staticCRgn*PASCALFromHandle(HRGNhRgn);operatorHRGN()const;//Constructors構(gòu)造器CRgn();BOOLCreateRectRgn(intx1,inty1,intx2,inty2);BOOLCreateRectRgnIndirect(LPCRECTlpRect);BOOLCreateEllipticRgn(intx1,inty1,intx2,inty2);BOOLCreateEllipticRgnIndirect(LPCRECTlpRect);BOOLCreatePolygonRgn(LPPOINTlpPoints,intnCount,intnMode);#ifndef_MACBOOLCreatePolyPolygonRgn(LPPOINTlpPoints,LPINTlpPolyCounts,intnCount,intnPolyFillMode);#endifBOOLCreateRoundRectRgn(intx1,inty1,intx2,inty2,intx3,inty3);#ifndef_MACBOOLCreateFromPath(CDC*pDC);BOOLCreateFromData(constXFORM*lpXForm,intnCount,constRGNDATA*pRgnData);#endif//OperationsvoidSetRectRgn(intx1,inty1,intx2,inty2);voidSetRectRgn(LPCRECTlpRect);intCombineRgn(CRgn*pRgn1,CRgn*pRgn2,intnCombineMode);intCopyRgn(CRgn*pRgnSrc);BOOLEqualRgn(CRgn*pRgn)const;intOffsetRgn(intx,inty);intOffsetRgn(POINTpoint);intGetRgnBox(LPRECTlpRect)const;BOOLPtInRegion(intx,inty)const;BOOLPtInRegion(POINTpoint)const;BOOLRectInRegion(LPCRECTlpRect)const;#ifndef_MACintGetRegionData(LPRGNDATAlpRgnData,intnCount)const;#endif//Implementationvirtual~CRgn();}〔1〕創(chuàng)立CRgn對象CRgn類的構(gòu)造函數(shù)只有一個,創(chuàng)立一個CRgn對象后,必須調(diào)用一個初始化函數(shù)對對象進行初始化后才能被使用。下面介紹它的一些常用初始化函數(shù)。①函數(shù)CreateRectRgn和CreateRectRgnIndirect這兩個函數(shù)在CRgn類中的完整定義如下:BOOLCreateRectRgn(intx1,inty1,intx2,inty2);BOOLCreateRectRgnIndirect(LPCRECTlpRect);這兩個函數(shù)都是用來初始化一個矩形區(qū)域,矩形區(qū)域的頂點坐標必須在小于32767并大于-32768范圍內(nèi)〔邏輯坐標〕。在第一個函數(shù)中,矩形區(qū)域的對角坐標分別為〔x1,y1〕和〔x2,y2〕;在第二個函數(shù)中,矩形區(qū)域的對角坐標存儲一個RECT結(jié)構(gòu)或CRect對角中。下面代碼分別調(diào)用了這兩個函數(shù),初始化形成一個矩形區(qū)域〔0,0,200,200〕:CRectrr;//創(chuàng)立一個CRect對象CRgnm_Rgn;//創(chuàng)立一個CRgn對象m_Rgn.CreateRectRgn(0,0,200,100);//用CreateRectRgn函數(shù)初始化CRgn對象rr.left=0;rr.top=0;rr.right=200;rr.bottom=100;m_Rgn.CreateRectRgnIndirect(&rr);//用CreateRectRgnIndirect函數(shù)初始化CRgn對象②函數(shù)CreateEllipticRgn和CreateEllipticRgnIndirect這兩個函數(shù)在CRgn類中的完整定義如下:BOOLCreateEllipticRgn(intx1,inty1,intx2,inty2);CreateEllipticRgnIndirect(LPCRECTlpRect);這兩個函數(shù)都用來初始化一個橢圓區(qū)域,橢圓的矩形邊界頂點坐標必須小于32767并大于-32768(邏輯坐標)。在用CreateEllipticRgn函數(shù)初始化橢圓區(qū)域時,橢圓的矩形邊界頂點坐標用參數(shù)〔x1,y1〕和〔x2,y2〕來表示;用CreateEllipticRgnIndirect函數(shù)來初始化橢圓區(qū)域時,橢圓的矩形邊界頂點坐標用一個RECT結(jié)構(gòu)或一個CRect對象來表示。這兩個函數(shù)的使用方法與①中的兩個函數(shù)相同。③函數(shù)CreatePolygonRgn函數(shù)在CRgn類中的完整定義為:BOOLCreatePolygonRgn(LPPOINTlpPoints,intnCount,intnMode);CreatePolygonRgn函數(shù)初始化一個多邊形區(qū)域,多邊形區(qū)域的頂點坐標必須小于32767并大于-32768〔邏輯坐標〕。參數(shù)lpPoints指向一個POINT結(jié)構(gòu)數(shù)組或CPoint對象數(shù)組;參數(shù)nCount是多邊形區(qū)域頂點的數(shù)目;參數(shù)nMode是多邊形的填充模式,可選用參數(shù)ALTERNATE或WINDING。如下代碼創(chuàng)立了一個三角形區(qū)域,三角形頂點為〔0,0〕,〔10,1〕,〔20,0〕:CPointpoint[3];//創(chuàng)立一個CPoint對象數(shù)組CRgnm_Rgn;//創(chuàng)立一個CRgn對象//以下設(shè)置CPoint對象數(shù)組中存儲的三角形區(qū)域頂點的坐標point[0].x=0;point[0].y=0;point[1].x=10;point[1].y=10;point[2].x=20;point[2].y=0;m_Rgn.CreatePolygonRgn(point,3,0);//初始化一個三角形區(qū)域④函數(shù)CreatePolyPolygonRgn函數(shù)在CRgn類中的完整定義為:BOOLCreatePolyPolygonRgn(LPPOINTlpPoints,LPINTlpPolyCounts,intnCount,intnPolyFillMode);CreatePolyPolygonRgn函數(shù)用來初始化一個包含一系列多邊形的區(qū)域,其頂點坐標必須小于32767并大于-32768〔邏輯坐標〕。創(chuàng)立的多邊形可是獨立的,也可相交。參數(shù)lpPoints指向一個POINT結(jié)構(gòu)數(shù)組或CPoint對象數(shù)組,數(shù)組中的每個結(jié)構(gòu)或?qū)ο笥脕肀硎疽粋€頂點的坐標。參數(shù)lpPolyCounts是一個整數(shù)數(shù)組,存儲的是各個多邊形的頂點數(shù)。參數(shù)nCount表示區(qū)域中多邊形的數(shù)目,也就是表示lpPolyCounts數(shù)組的項數(shù)。參數(shù)nPolyFillMode表示填充模式。以下代碼用函數(shù)CreatePolyPolygonRgn創(chuàng)立了包含三個多邊形的區(qū)域:CRgnm_Rgn;POINTpoint[12];//定義一個POINT結(jié)構(gòu)數(shù)組......//省略對坐標的數(shù)值輸入intnCount[3];nCount[0]=3;nCount[1]=4;nCount[2]=5;//區(qū)域中各個多邊形的頂點數(shù)目m_Rgn.CreatePolyPolygonRgn(point,nCount,3,0);//初始化區(qū)域?qū)ο笠陨洗a初始化一個包含三個多邊形的區(qū)域,三個多邊形的頂點數(shù)分別為3,4,5,結(jié)構(gòu)數(shù)組Point中存放的是頂點坐標,一共有12個頂點,順序放著三個多邊形的頂點坐標?!?〕刪除CRgn對象一個CRgn類的構(gòu)造函數(shù)沒有進行對象的初始化工作,創(chuàng)建一個CRgn對象后,由〔1〕中介紹的一些函數(shù)對對象進行初始化。同樣,CRgn類的析構(gòu)函數(shù)也不能刪除初始化后的CRgn對象,需要調(diào)用基類的DeleteObject函數(shù)來刪除。例如,對于一個初始化的CRgn對象m_Rgn可采用以下的代碼刪除它:m_Rgn.DeleteObject();//刪除m_Rgn對象〔3〕常用操作以下介紹CRgn類中的幾個常用的成員函數(shù)及這些函數(shù)所完成的操作功能。①CombineRgn函數(shù)函數(shù)在CRgn類中的完整定義為:intCombineRgn(CRgn*pRgn1,CRgn*pRgn2,intnCombineMode);CombineRgn函數(shù)也可以初始化一個區(qū)域,不過這個區(qū)域是通過兩個已經(jīng)存在區(qū)域的相互關(guān)系確定的。參數(shù)pRgn1和pRgn2分別指向兩個已經(jīng)存在的CRgn對象,參數(shù)nCombineMode是兩個參數(shù)指向的區(qū)域相互操作時采用的模式。下面是參數(shù)nCombineMode可以采用的一些參數(shù)值及對應(yīng)的操作模式:RGN_AND以兩個區(qū)域的相交局部初始化新區(qū)域。RGN_COPY初始化一個同第一個區(qū)域相同的區(qū)域。RGN_DIFF用第一區(qū)域中沒有與第二個區(qū)域相交的局部初始化區(qū)域。RGN_OR初始化一個包含兩個區(qū)域的區(qū)域。RGN_XOR初始化一個包含兩個區(qū)域但不包含兩個區(qū)域相交局部的區(qū)域。根據(jù)操作結(jié)果,函數(shù)返回如下值,其含義如下:COMPLEXREGION區(qū)域覆蓋邊界。ERROR操作無效。NULLREGION區(qū)域為空。SIMPLEREGION區(qū)域沒有覆蓋邊界。②CopyRgn函數(shù)函數(shù)在CRgn類中的完整定義為:intCopyRgn();CopyRgn函數(shù)用一個存在的區(qū)域復(fù)制初始化當(dāng)前的區(qū)域。CopyRgn函數(shù)是CombineRgn函數(shù)采用RGN_COPY參數(shù)時的一種特殊情況。如下操作可把區(qū)域m_Rgn1初始化成與區(qū)域m_Rgn2相同:CRgnm_Rgn1,m_Rgn2;//創(chuàng)立兩個CRgn對象m_Rgn2.CreateRectRgn(0,0,200,100);//初始化m_Rgn2對象m_Rgn1.CopyRgn(&m_Rgn2);//將m_Rgn1對象初始化成與m_Rgn2對象相同③EqualRgn函數(shù)函數(shù)在CRgn類中的完整定義為:BOOLEqualRgn(CRgn*pRgn)const;EqualRgn函數(shù)檢查當(dāng)前區(qū)域與參數(shù)pRgn指向的區(qū)域是否相同。相同時函數(shù)返回TRUE,否那么函數(shù)返回FALSE。以下操作代碼將返回TRUE〔yN=1〕:CRgnm_Rgn1,m_Rgn2;//創(chuàng)立兩個CRgn對象m_Rgn2.CreateRectRgn(0,0,200,100);//初始化CRgn對象m_Rgn2m_Rgn1.CopyRgn(&m_Rgn2);//將m_Rgn1對象初始化成與m_Rgn2對象相同BOOLyN=m_Rgn1.EqualRgn(&m_Rgn2);//檢查兩個區(qū)域是否相同④OffsetRgn函數(shù)OffSetRgn函數(shù)在CRgn類中有兩個重載定義:intOffsetRgn(intx,inty);intOffsetRgn(intx,inty);intOffsetRgn(POINTpoint);OffSetRgn函數(shù)的作用是將當(dāng)前的區(qū)域相對移動一個距離。函數(shù)的參數(shù)代表橫縱移動的距離量〔在第一個函數(shù)中,橫向移動量為x,縱向移動量為y;在第二個函數(shù)中,橫向移動量為point.x,縱向移動量為point.y〕。函數(shù)的返回值及含義同①中的CombineRgn函數(shù)。⑤GetRgnBox函數(shù)函數(shù)在CRgn類中的完整定義為:intGetRgnBox(LPRECTlpRect)const;GetRgnBox函數(shù)用來獲得區(qū)域的邊界矩形。邊界矩形是能夠包含一個區(qū)域的最小矩形,邊界矩形的對角頂點坐標通過一個RECT結(jié)構(gòu)或一個CRect對象返回。如下代碼將創(chuàng)立一個區(qū)域,并返回區(qū)域的邊界矩形:CPointpoint[3];//創(chuàng)立一個CPoint對象數(shù)組CRgnm_Rgn;//創(chuàng)立一個CRgn對象RECTrr;//創(chuàng)立一個CRect對象point[0].x=0;point[0].y=0;point[1].x=10;point[1].y=10;point[2].x=20;point[2].y=0;m_Rgn.CreatePolygonRgn(point,3,0);//初始化一個有三個頂點的多邊形區(qū)域m_Rgn.GetRgnBox(&rr);實際運行以上代碼,會得到邊界矩形(0,0,20,10)。⑥PtInRegion函數(shù)PtInRegion函數(shù)在CRgn類中有兩個重載定義:BOOLPtInRegion(intx,inty)const;BOOLPtInRegion(POINTpoint)const;PtInRegion函數(shù)用來檢查一個點是否在當(dāng)前區(qū)域內(nèi),如果在當(dāng)前區(qū)域內(nèi),函數(shù)返回TRUE,否那么返回FALSE。點的坐標在兩個重載函數(shù)中分別通過兩個整型變量x和y或一個POINT結(jié)構(gòu)point確定。以下代碼創(chuàng)立一個區(qū)域,并能夠檢查一個點是否在區(qū)域內(nèi):CPointpoint[3];//創(chuàng)立一個對象數(shù)組CRgnm_Rgn;//創(chuàng)立一個CRgn對象POINTpoint;point[0].x=0;point[0].y=0;point[1].x=10;point[1].y=10;point[2].x=20;point[2].y=0;m_Rgn.CreatePolygonRgn(point,3,0);//初始化一個有三個頂點的多邊形區(qū)域point.x=5;point.y=5;//需要檢查的點的坐標BOOLYN=m_Rgn.PtInRegion(point);如果將以上代碼放在函數(shù)中運行,得到Y(jié)N的值為1(TRUE),說明點在區(qū)域內(nèi)。⑦RectInRegion函數(shù)函數(shù)在CRgn類中的完整定義為:BOOLRectInRegion(LPCRECTlpRect)const;RectInRegion函數(shù)用來檢查一個矩形是否在一個區(qū)域內(nèi)。矩形的坐標存儲在參數(shù)lpRect中。如果矩形在區(qū)域內(nèi),函數(shù)返回TRUE,否那么函數(shù)返回FALSE。RectInRegion的具體使用方法與函數(shù)PtInRegion類似,不再舉例。〔4〕CRgn對象的引用創(chuàng)立并初始化的CRgn對象,可以作為其他函數(shù)的參數(shù)被引用。本節(jié)討論的CRgn類的成員函數(shù)CombineRgn中,就是用CRgn對象作為參數(shù)。還有其他一些函數(shù)也使用CRgn對象作為參數(shù),如在視圖類中,以下代碼使視圖中m_Rgn對象確定的區(qū)域失效并重畫:InvalidateRgn(&m_Rgn);4.2.6CPalette和CBitmap類調(diào)色板是應(yīng)用程序和彩色輸出設(shè)備〔如彩顯〕之間的接口。這個接口允許應(yīng)用程序充分利用彩色設(shè)備的顏色特性,而不太影響其他應(yīng)用程序的顯示效果。Windows使用應(yīng)用程序的邏輯調(diào)色板和系統(tǒng)調(diào)色板來確定使用的顏色。CPalette類封裝了Windows調(diào)色板的操作的各方面的功能。CBitmap類封裝了進行位圖操作的各方面的功能。本書中沒有具體討論有關(guān)CPalette和CBitmap類的具體操作。作者所著的《矢量圖形系統(tǒng)開發(fā)與編程》一書的第18章,詳細討論了CPalette類和CBitmap類的使用方法,實例介紹了顯示位圖圖像的多種方法,讀者可參閱。4.3坐標映像方式在VC++中進行Windows應(yīng)用程序設(shè)計時,可以采用多種不同的映像方式即不同的坐標系。本節(jié)介紹對映像方式的分類、特點和設(shè)置方法。4.3.1Windows映像方式及其設(shè)置方法〔1〕Windows映像方式Windows映像方式就是Windows下的邏輯坐標方式。一個實際物理屏幕是由像素組成的,如平常所說的640×480,1024×768指的就是顯示器屏幕的實際寬度和高度的像素數(shù)目。為了方便各種情況下的程序開發(fā),Windows提供了幾種映像方式,每一種映像方式提供不同的測量單位和坐標原點,如表4-3所示。表4-3Windows映像方式映像方式映像識別碼邏輯單位X和Y軸正向MM_TEXT1Pixels右下MM_LOMETRIC20.1mm右上MM_HIMETRIC30.01mm右上MM_LONGLISH40.1inch右上MM_HIENGLISH50.01inch右上MM_TEXT方式〔默認方式〕根本上等價于DOS文本方式,不同的是DOS在字符狀態(tài)下操作,而MM_TEXT方式允許應(yīng)用程序利用設(shè)備像素工作,這是一種與設(shè)備坐標方式相同的映像方式。屏幕〔窗口〕的原點約定在屏幕〔窗口〕的左上角,而X和Y的正方向為向右和向下。MM_LOMETRIC,MM_HIMETRIC,MM_LONGLISH,MM_HIENGLISH這四種映像方式默認的坐標原點在窗口的左上角,其坐標的正方向為向右和向上〔笛卡爾坐標〕。坐標位置用英寸〔in〕或毫米〔mm〕表示,這對一些應(yīng)用程序〔例如一個繪圖程序〕來說是很方便的,可以直接利用原來的單位繪圖,而不必進行坐標轉(zhuǎn)換。MM_TWIPS61/1440inch右上MM_ISOTROPIC7Variable(x==y)變化的MM_ANISOTROPIC8Variable(x<>y)變化的MM_ISOTROPIC和MM_ANISOTROPIC映像方式用的也是笛卡爾坐標,這兩種映像方式提供可變的邏輯單位和可變的原點。在MM_ISOTROPIC映像方式中,X軸和Y軸方向坐標刻度是相同的。而MM_ANISOTROPIC方式,允許對X軸和Y軸設(shè)置不同的刻度。MM_TWIPS方式是一種專門為排版設(shè)計的映像方式,TWIPS是對“一個點的1/20”這個詞稍微刪改后的縮寫?!包c”是排版的一個術(shù)語,也稱之為“磅”〔簡寫pt〕,一“點”等于1/72英寸。設(shè)立這個映像方式完全是為了設(shè)計排版用應(yīng)用程序的需要。這八種Windows映像方式,滿足了各種具體方式下的需要,并以MM_TEXT方式〔像素方式〕為根底。它是通過在Windows內(nèi)置一些完成各種映像方式下的邏輯坐標到屏幕設(shè)備坐標的轉(zhuǎn)換函數(shù)來實現(xiàn)的。任何一種映像方式都可以用MM_TEXT方式通過程序設(shè)計轉(zhuǎn)換而成。不同的是,直接應(yīng)用各種映像方式時的轉(zhuǎn)換是由Windows內(nèi)置程序來完成的,不需要程序設(shè)計者自己再編制程序?!?〕設(shè)置映像方式的方法在MFC應(yīng)用程序中,通過調(diào)用CDC類的SetMapMode函數(shù)設(shè)置映像方式。例如,在函數(shù)CDrawView::OnDraw(CDC*pDC)中,可以通過以下代碼設(shè)置第n種映像方式:pDC->SetMapMode(n);n是在表4-3中列出的映像方式的識別碼。4.3.2邏輯坐標和設(shè)備坐標的轉(zhuǎn)換〔1〕設(shè)備無關(guān)性Windows提供了八種映像方式,并實現(xiàn)了設(shè)備無關(guān)性。所謂設(shè)備無關(guān)性,指的是只要設(shè)定了映像方式,那么就會在不同的輸出設(shè)備上顯示出同樣大小的圖形。例如,在MM_LOMETRIC(邏輯單位時0.1mm)映像方式下,畫一條100邏輯單位的線,不管用什么樣的顯示器和分辨率下這條線的顯示長度為1cm(100個0.1mm),在打印機上打印輸出時長度也是1cm,Windows系統(tǒng)內(nèi)部實現(xiàn)了這個與設(shè)備無關(guān)的映像過程。所以使用MM_LOMETRIC、MM_HIMETRIC、MM_LONGLISH、MM_HIENGLISH、MM_TWIPS這些映像方式時,可以保證在不同的輸出設(shè)備上顯示相同大小的圖形。對于MM_TEXT映像方式來說,因為其單位是像素,長度是不固定〔即一個像素所占的實際長度隨著設(shè)備的不同而不同〕,所以在不同輸出設(shè)備上不能保證顯示的圖形大小一樣?!?〕邏輯坐標和設(shè)備坐標的轉(zhuǎn)換方法為了完成各種映像方式下邏輯坐標和設(shè)備坐標的轉(zhuǎn)換,VC++提供了兩個成員函數(shù):DPtoLP(LPPOINTlpPoints);//實現(xiàn)從設(shè)備坐標轉(zhuǎn)換到邏輯坐標LPtoDP(LPPOINTlpPoints);//實現(xiàn)從邏輯坐標轉(zhuǎn)換到設(shè)備坐標以下代碼將一個點由設(shè)備坐標轉(zhuǎn)換成邏輯坐標:CPointpoint;//創(chuàng)立一個CPoint對象point.x=100;point.y=100;//給點賦一坐標值pDC->DPtoLP(&point);//將點從設(shè)備坐標轉(zhuǎn)換成邏輯坐標4.4窗口和視口本節(jié)討論窗口和視口的概念,以及窗口和視口的坐標轉(zhuǎn)換方法。4.4.1窗口和視口的概念窗口指的是虛擬存在的一個屏幕,而視口是在屏幕上看到的視圖客戶區(qū)域。之所以分為窗口和視口,是與Windows進行圖形繪制的機制有關(guān)。Windows繪制圖形時,并不是把圖形直接繪制到屏幕上,而是以各種映像方式下的邏輯坐標系將圖形繪制到虛擬的窗口中,然后將這個窗口內(nèi)的內(nèi)容映像到視口中,如果是映像到屏幕上,就實現(xiàn)了圖形的顯示,映像到打印機等輸出設(shè)備上,而實現(xiàn)了圖形的打印輸出。千萬不要把窗口原點和視口原點與坐標系中的原點混淆起來。在這里窗口原點和視口原點指的是同一個點在窗口邏輯坐標系和視口設(shè)備坐標系中的坐標值,它決定了圖形由窗口映像到視口時的相對位置。4.4.2窗口和視口有關(guān)的操作函數(shù)本小節(jié)中,介紹在CWnd類中與窗口和視口有關(guān)的操作函數(shù)的功能和使用方法?!?〕SetWindowOrg函數(shù)函數(shù)SetWindowOrg用來設(shè)置一個與設(shè)備環(huán)境有關(guān)的窗口原點。函數(shù)SetWindowOrg有以下兩個重載定義:CPointSetWindowOrg(intx,inty);CPointSetWindowOrg(POINTpoint);參數(shù)x和y或point用來記錄要設(shè)置的窗口原點。函數(shù)返回設(shè)置前的窗口原點?!?〕SetViewportOrg函數(shù)函數(shù)SetViewportOrg用來設(shè)置一個與設(shè)備環(huán)境有關(guān)的視口原點。函數(shù)SetViewportOrg有以下兩個重載定義:CPointSetViewportOrg(intx,inty);CPointSetViewportOrg(POINTpoint);參數(shù)x和y或point用來記錄要設(shè)置的視口原點。函數(shù)返回設(shè)置前的視口原點。〔3〕SetWindowExt函數(shù)函數(shù)SetWindowExt用來設(shè)置與設(shè)備環(huán)境有關(guān)的窗口在x和y方向的幅度。只有在MM_ANISOTROPIC和MM_ISOTROPIC映像方式下該函數(shù)才有效。函數(shù)SetWindowExt有以下兩個重載定義:virtualCSizeSetWindowExt(intcx,intcy);virtualCsizeSetWindowExt(SIZEsize);參數(shù)cx和cy或size用來記錄要設(shè)置的x和y方向的窗口幅度。函數(shù)返回設(shè)置前的幅度值?!?〕SetViewportExt函數(shù)函數(shù)SetViewportExt用來設(shè)置與設(shè)備環(huán)境有關(guān)的視口在x和y方向的幅度。只有在MM_ANISOTROPIC和MM_ISOTROPIC映像方式下該函數(shù)才有效。函數(shù)SetViewportExt有以下兩個重載定義:virtualCsizeSetWindowExt(intcx,intcy);virtualCsizeSetWindowExt(SIZEsize);參數(shù)cx和cy或size用來記錄要設(shè)置的x和y方向的視口幅度。函數(shù)返回設(shè)置前的幅度值。必須注意,在MM_ISOTROPIC映像方式下,必須先設(shè)置窗口幅度,再設(shè)置視口幅度。4.4.3窗口邏輯坐標與視口設(shè)備坐標的轉(zhuǎn)換VC++窗口和視口的作用是為了實現(xiàn)設(shè)備無關(guān)性。所謂設(shè)備無關(guān)性就是可以把圖形以實際邏輯單位的大小顯示到任何設(shè)備上〔如屏幕,打印機〕,而不必考慮這些設(shè)備的硬件情況。下面對表4-3所列的八種映像方式下的坐標轉(zhuǎn)換進行討論,借以進一步理解關(guān)于窗口和視口的概念?!?〕邏輯坐標和設(shè)備坐標的轉(zhuǎn)換方法假定在窗口中有一幅圖形,圖形用的是邏輯坐標系,它的原點在〔0,0〕,寬度為1000個邏輯單位,高度也為1000個邏輯單位〔如在MM_LOMETRIC映像方式下,邏輯單位就是0.1mm〕。在這幅圖形中設(shè)置一個點〔a1,h1〕為窗口原點:pDC->SetWindowOrg(a1,b1);a1和b1是窗口原點在窗口邏輯坐標系中的坐標值。該坐標值的單位是邏輯單位〔如在MM_LOMETRIC映像方式下,邏輯單位就是0.1mm〕。當(dāng)Windows把這幅圖形映像到視口〔如屏幕〕上時,在視口中坐標單位不再是邏輯單位,而是設(shè)備坐標〔像素坐標〕。根據(jù)設(shè)備的無關(guān)性,圖形映像在視口上時圖形的大小應(yīng)該是不變的,但是因為視口中坐標系的單位是像素而不是邏輯單位,所以映像出來的圖形用像素表示的幅度是不一樣。這就要求應(yīng)該有像素與邏輯單位〔0.1mm〕的轉(zhuǎn)換比例〔這個比例的大小隨著顯示器屏幕的大小和分辨率的上下而不同〕。假定一個像素的實際大小等于n個邏輯單位,那么這幅圖形的實際寬度為1000/n個像素,實際高度為〔1000/n〕個像素。另外,當(dāng)把這個圖形映像到視口上時,還需要確定把圖形映像到視口的什么位置。在窗口中,在圖形上取定了一個點〔a1,b1〕為窗口原點,現(xiàn)在只要能夠確定這個點映像到視口時,在視口中的坐標位置,就確定了整個圖形的映像位置。這個點在視口中的坐標可以通過設(shè)置視口原點來實現(xiàn),如將視口原點設(shè)置為〔a2,b2〕:pDC->SetViewportOrg(a2,b2);a2和b2是視口原點在視口的像素坐標系中的坐標值。通過窗口原點和視口原點就確定了圖形從窗口映像到視口時的位置,即一個在窗口的邏輯坐標系中坐標為〔a1,b1〕的點,映像到視口后在設(shè)備像素坐標系中的坐標值為〔a2,b2〕。通過窗口原點和視口原點,可以得到圖形中的同一個點的設(shè)備坐標和邏輯坐標的對應(yīng)關(guān)系。假定一個點在窗口邏輯坐標為〔x1,y1〕,在視口設(shè)備像素坐標為〔x2,y2〕,在兩個坐標系y軸同向的情況下,根據(jù)在窗口和視口中這個點到原點的距離相等,那么有如下轉(zhuǎn)換關(guān)系:(x1-a1)=(x2-a2)*n(y1-b1)=(y2-b2)*n在y軸反向的情況下,那么有如下的轉(zhuǎn)換關(guān)系。(x1-a1)=(x2-a2)*n(y1-b1)=-(y2-b2)*n〔2〕MM_TEXT映像方式的坐標轉(zhuǎn)換MM_TEXT映像方式是最簡單的一種方式,此時窗口中的邏輯坐標也是像素坐標,方向與視口中的相同。在這種方式下,如果窗口原點和視口原點相同,設(shè)備像素坐標〔視口中〕和邏輯坐標〔窗口中〕是相同的。圖形映像時,實際上是原封不動的由窗口映像到視口。當(dāng)窗口原點與視口原點不同時,兩者的坐標轉(zhuǎn)換如下:在MM_TEXT映像方式下,因為在窗口和視口中都采用像素坐標,所以n等于1。依據(jù)以上討論的坐標轉(zhuǎn)換公式,可得到窗口邏輯坐標到視口設(shè)備坐標的轉(zhuǎn)換公式為:x2=x1-a1+a2;y2=y1-b1+b2;將窗口原點設(shè)置為〔100,100〕,視口原點設(shè)置為〔50,50〕時:pDC->SetWindowOrg(100,100);pDC->SetViewportOrg(50,50);那么有如下的轉(zhuǎn)換關(guān)系:x2=x1-50+100;y2=y1-50+100;同樣,可以得到視口設(shè)備坐標到窗口邏輯坐標的轉(zhuǎn)換公式:x1=x2+a1-a2;y1=y2+b1-b2;所以在MM_TEXT映像方式下,當(dāng)視口原點和窗口原點重合在一起時,窗口和視口中坐標系是完全一樣的,這是系統(tǒng)默認的映像方式。通過移動視口原點和窗口原點都可以到達移動圖形的目的?!?〕MM_LOMETRIC等五種映像方式下的坐標轉(zhuǎn)換MM_LOMETRIC、MM_HIMETRIC、MM_LONGLISH、MM_HIENGLISH、MM_TWIPS等五種映像方式,除了邏輯坐標單位不一樣外,其他方面都一樣,現(xiàn)在就以MM_LOMETRIC映像方式為例,討論這五種映像方式下的坐標轉(zhuǎn)換問題。在MM_LOMETRIC映像方式下,窗口中的邏輯坐標單位是0.1mm,而視口中的坐標單位仍然是像素,假定一個像素等于n個邏輯單位〔0.1mm〕。因為MM_LOMETRIC映像方式下的邏輯坐標與設(shè)備坐標Y軸反向,所以得到邏輯坐標到設(shè)備坐標的轉(zhuǎn)換公式為:x2=(x1-a1)/n+a2;y2=-(y1-b1)/n+b2窗口原點和視口原點的坐標都為〔0,0〕時,邏輯坐標到設(shè)備坐標的轉(zhuǎn)換公式為:x2=x1/n;y2=-y1/n;//因為邏輯坐標系和設(shè)備坐標系方向相反,所以為負值窗口原點坐標為〔100,100〕而視口原點坐標為〔0,0〕時,坐標轉(zhuǎn)換公式為:x2=100+x1/n;y2=100-y1/n;窗口原點坐標為〔0,0〕而視口原點坐標為〔100,100〕時,坐標轉(zhuǎn)換公式為:x2=(x1-100)/n;y2=-(y1-100)/n;窗口原點坐標為〔100,100〕而視口原點坐標為〔100,100〕時,坐標轉(zhuǎn)換公式為:x2=(x1-100)/n+100;y2=-(y1-100)/n+100;在MM_LOMETRIC等五種映像方式下,雖然移動窗口原點和視口原點都可以到達移動圖形的目的,但移動量是不一樣的。移動窗口原點時,移動量是以邏輯坐標為單位,而移動視口原點時,移動量是以設(shè)備坐標〔像素〕為單位?!?〕MM_ISOTROPIC和MM_ANSIOTROPIC映像方式的坐標轉(zhuǎn)換對于Windows系統(tǒng)來說,MM_ISOTROPIC和MM_ANSIOTROPIC映像方式是非常重要的。在這兩個映像方式下,有著與其他六種映像方式不同的映像概念。其他六種映像方式,一個共同的特點是由窗口映像到視口時,圖形大小不變,而且視口都采用設(shè)備〔像素〕坐標。而在這兩種映像方式下,映像后圖形的大小要發(fā)生變化,視口中的坐標也不再以像素為單位,而窗口中的邏輯坐標那么是以像素為單位。通過SetWindowExt建立一個窗口的范圍,通過SetViewportExt建立一個視口的范圍,這兩個范圍決定了由窗口映像到視口的操作,進行映像操作時,就像放縮復(fù)印一樣把窗口內(nèi)的圖形復(fù)制到視口內(nèi),與前面討論六種映像方式一樣,靠窗口原點和視口原點來確定映像操作時圖形的相對位置。在MM_ISOTROPIC映像方式下,X和Y兩方向同比例放縮,而在MM_ANISOTROPIC映像方式下,允許兩方向不同比例放縮。以下代碼設(shè)置MM_ANISOTROPIC映像方式,并設(shè)置窗口和視口的幅度:pDC->SetMapMode(MM_ANISOTROPIC);pDC->SetWindowExt(100,100);//設(shè)置窗口的x和y方向的幅度為100和100單位pDC->SetViewportExt(500,300);//設(shè)置視口的x和y方向的幅度為500和300單位當(dāng)窗口和視口在原點都在〔0,0〕的情況下,進

溫馨提示

  • 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)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論