WINDOWS 幾種座標系

在窗口中繪圖

圖形設備接口(GDI)與設備描述表(DC)

圖形設備接口(GDI)
許多MS-DOS程序都直接往視頻存儲區或打印機端口輸送數據, 
這種做法的不利之處在於需要對每種顯示卡或打印機類型提供相應的驅動程序。
Windows則提供了一抽象的接口,稱之爲圖形設備接口(GDI)。
Windows己經提供了各種顯示卡及打印機的驅動程序,
這樣我們的程序就可以不必關心與系統相連的顯示卡及打印機的類型。
我們的程序可以通過調用GDI函數和硬件打交道,
而各種GDI函數會自動參考被稱爲設備環境(CDC)的數據結構。
Windows會自動將設備環境結構映射到相應的物理設備,並且會提供正確的輸入輸出指令。

設備描述表(DC)

在Windows環境中,各程序的輸出必須限制在自己的窗口中。
GDI使用一種簡單的機制保證在窗口中畫圖的各程序遵循這個規則。
這種機制即爲設備描述表(DC);

當Windows程序在屏幕、打印機或其它設備上畫圖時,
它並不是將像素直接輸出到設備上,而是將圖繪製到由設備描述表表示的邏輯意義上的"顯示平面"上去。

設備描述表是深寓於Windows中的一種數據結構,
它包含GDI需要的所有關於顯示平面情況的描述字段,包括相連的物理設備和各種各樣的狀態信息。

設備描述表對象
在使用MFC編制Windows程序時,設備描述表具有更加突出的作用。
除了可作爲通往各種設備的橋樑之外,設備描述表對象還封裝了程序用來產生輸出的GDI函數。
在MFC中,你不用捕獲設備描述表句柄和調用GDI輸出函數,至少不必直接捕獲和調用,
而是通過創建一設備描述表對象並調用它的成員函數來畫圖。

設備描述表句柄
在平面上畫圖之前,Windows程序從GDI獲取設備描述表句柄,
並在每次調用完GDI輸出函數時將句柄返回給GDI。
在MFC應用程序中獲取設備描述表的一種方法是調用CWnd::GetDC,
它返回指向表示Windows設備描述表的CDC對象的指針。
在畫圖完畢,要用CWnd::ReleaseDC釋放指針(注:在OnPaint處理程序中,不用顯示調用這兩個函數)

CDC派生類
爲了避免獲取和釋放設備描述表所帶來的麻煩,
MFC提供了一些CDC派生類,如CPaintDC,CClientDC,CWindowDC這些類被設計爲可直接進行實例化。
各個類的構造函數和析構函數調用相應的函數捕獲和釋放設備描述表,
從而便得設備描述表的使用非常方便簡捷。

例如:
CPaintDC dc(this);
//Do some drawing
傳送給類構造函數的指針確定了設備描述表所屬的窗口。

設備描述表屬性
當使用CDC輸出函數在屏幕上畫圖時,
輸出的某些特性並沒有在函數調用過程中規定(採用系統默認的屬性畫圖),
但我們可以通過設備描述表自身獲得或得新設置屬性。
MFC提供了獲得和設置這些屬性的函數,我們可以用這些函數方便地改變畫圖時的默認屬性。
例如:
CDC::SetTextColor//設置文本顏色
CDC::GetTextColor//獲得文本顏色
CDC::SetBkColor//設置背景顏色
CDC::SetBkMode//設置背景模式
CDC::SetMapMode//設置映射模式
CDC::CDC::SetROP2//設置繪圖模式
CDC::MoveTo//當前位置
CDCL::SelectObject//當前畫筆,當前畫刷,當前字體

(如果想忽略背景色,可將背景設置爲"Transparent",dc.SetBkMode(TRANSPARENT);)

SelectObject函數
最常用來定義設備描述表屬性的CDC函數是SelectObject。
例如:
CPen pen(PS_SOLID,2,RGB(0,192,0));
CPen* pOldPen = dc->SelectObject(&pen);//把新的CDC對象選入設備描述表,同時保存舊的CDC對象
dc->Ellipse(0,0,100,100);
dc.SelectObject(pOldPen);//

繪圖模式與SetROP2
GDI將像素點輸出到邏輯平面上時,它不只是簡單地輸出像素點顏色。
相反,它能過一系列的布爾運算將輸出像素點的顏色和目標位置上像素點的顏色合成一起。
它所使用的邏輯關係由設備描述表當前的繪圖模式確定。
使用CDC::SetROP2(Set Raster Operation To)可更改繪圖模式。
默認繪圖模式爲R2_COPYPEN,它將將像素點複製到顯示平面上。

映射模式

默認映射模式
固定比例映射模式
可編程映射模式

簡單地說,映射模式是設備描述表的屬性,用於確定從邏輯座標值到設備座標值的轉換方式。

默認的映射模式

默認的映射模式使MM_TEXT,它使以象素爲單位的。X軸向左爲正,Y軸向下爲正。默認的座標原點在左上角。

固定比例映射模式

固定比例的映射模式有MM_LOMETRIC、MM_HIMETRIC、MM_LOENGLISH、MM_HIENGLISH、MM_TWIPS種。
它們默認的座標原點都使在左上角。其區別在於每一個邏輯單位對應的物理大小不一樣。
所對用的邏輯單位分別爲0.1毫米,0.01毫米,0.01英寸,0.001英寸,1/1440英寸(0.0007英寸)。

可變比例映射模式(可編程映射模式)

對於可變比例的映射模式用戶可以自己定義一個邏輯單位代表的大小,其大小可以任意。
也可以讓這個大小隨環境改變而改變。有MM_ISOTROPIC,MM_ANISOTROPIC這兩種映射模式。
其邏輯單位的大小等於視口範圍和窗口範圍的比值。
兩者的不同在於前者要求X軸和Y軸的度量單位必須相同,而後者沒有這樣的限制。

 

可編程映射模式
MM_ISOTROPIC和MM_ANISOTROPIC是由用戶決定從邏輯座標值轉換成設備座標值的方式,
即是由用戶決定一個邏輯單位等於多少個設備單位(cm,mm,m等),而不是由Windows決定。
所以被稱之爲可編程映射模式;
MM_ISOTROPIC和MM_ANISOTROPIC映射模式最常用於根據窗口尺寸按比例自動調節畫圖的輸出大小的場合。

MM_ISOTROPIC和MM_ANISOTROPIC映射模式的區別
前者中X方向和Y方向具有同一個縮放比例因子,而後者兩個方向可以單獨縮放;

例子:
CRect rect;
GetClientRect(&rect);
dc.SetMapMode(MM_ISOTROPIC);
dc.SetWindowExt(500,500);//設置窗口範圍,將窗口的邏輯尺寸高爲500單位×500單位
dc.SetViewportExt(rect.Width(),rect.Height());//設置視口範圍
dc.Ellipse(0,0,500,500);

注:窗口的尺寸以邏輯單位計算,視口的尺寸以設備單位或像素計算。
特別說明
MM_TEXT爲默認映射模式,其原點在窗口的左上角,X軸的正向向右,Y軸的正向向下,
並且一個邏輯單位對應於設備座標下的一個象素

其它映射模式則原點不變,只是Y軸會翻轉使正向朝上,並且邏輯單位被按比例轉換爲實際距離大小,而不是像素數。
需要注意的是,使用公制映射模式(非默認映射模式)時,爲使輸出可見,Y座標必須爲負值。
例如:
dc.Rectangle(0,0,200,100);//默認模式下畫圖
dc.SetMapMode(MM_LOENGLISH);//改變映射模式
dc.Rectangle(0,0,200,-100);//畫圖

傳送給CDC輸出函數的是邏輯座標值。
設備座標值是指窗口中相應的像素點位置。

 


Windows中的幾種座標體系

1、屏幕座標

屏幕座標描述物理設備(顯示器、打印機等)的一種座標體系,
座標原點在屏幕的左上角,X軸向右爲正,Y軸向下爲正。度量單位是象素。
原點、座標軸方向、度量單位都是不能夠改變的。

2、設備座標(又稱物理座標)

設備座標是描述在屏幕和打印機顯示或打印的窗體的一種座標體系。
默認的座標原點是在其客戶區的左上角。X軸向右爲正,Y軸向下爲正。
度量單位爲象素。原點和座標軸方向可以改變,但是度量單位不可以改變。

3、邏輯座標

邏輯座標是在程序中控制顯示,打印使用的座標體系。
該座標系與定義的映射模式密切相關。默認的映射模式是MM_TEXT。
我們可以通過設置不同的映射模式來改變該座標體系的默認行爲。

注意:
首先,要記住兩點:
1。設備座標的(0, 0)點始終是客戶區的左上角。 
2。我們在繪圖時指定的點全部都是邏輯座標點。

座標轉換
調用CDC::LPtoDP可以將邏輯座標轉換爲設備座標;
高用CDC::DPtoLP可以將設備座標轉換爲邏輯座標;

什麼時候用什麼座標系

  • 可以認爲CDC的所有成員函數都以邏輯座標作爲參數
  • 可以認爲CWnd的所有成員函數都以設備座標作爲其參數
  • 所有選中測試操作中都應該考慮設備座標。區域的定義應採用設備座標。
    某些像CRect::PtInRect之類的函數只有在採用設備座標參數時纔會保證有正確的結果
  • 將一些需要長期使用的值用邏輯座標或物理座標來保存。
    如果用邏輯座標來保存某點的座標的話,那麼只要用戶對窗口進行一下滾動,該點的座標就不再有效了。
  • 鼠標單擊事件下得到的座標都是設備座標!

移動原點
CDC::SetViewportOrg()移動視口的原點 
CDC::SetWindwosOrg()移動窗口的原點
正常情況下,只能使用其中之一,同時使用兩個會搞提一團糟。

獲取設備信息
獲得系統分辨率
CClientDC dc(this);
int cx = dc.GetDeviceCaps(HORZRES);
int cy = dc.GetDeviceCaps(VERTRES);

用GDI繪圖

MFC的CDC類將相關的GDI函數封裝在類成員函數中。
在設備描述表對象中或通過指向設備描述表對象的指針可以方便地調用這些函數

畫線
dc.MoveTo(0,0);//設置當前位置
dc.LineTo(100,100);//指定一個線的終點位置

畫圓
dc.Ellipse(0,0,100,100);
CRect rect(0,0,100,100);
dc.Ellipse(rect);

畫矩形
dc.Rectangle(0,0,100,100);//畫一個帶直角的矩形

GDI畫筆和CPen類
Windows用當前選入設備描述表的畫筆繪製直線和曲線,
並給用Rectangle,Ellipse以及其他圖形生成函數畫出的圖形鑲畫邊框。
默認畫筆畫出的是一個像素點寬的黑色實線。
如果要改變畫線方式,則需創建一個GDI畫筆,並由CDC::SelectOjbect將它選設備描述表

MFC用類CPen表示GDI畫筆。

創建畫筆的方法
創建畫筆的最簡單的方法是構造一個CPen對象並把定義畫筆所用的參數都傳送給該對象
CPen pen(PS_SOLID,1,RGB(255,0,0));

創建畫筆的第二種方法是構造 一個漢有初始化的CPen對象並調用CPen::CreatePen:
CPen pen;
pen.CreatePen(PS_SOLID,1,RGB(255,0,0));

創建畫筆的第三種方法是構造一個沒有初始化的CPen對象,向LOGPEN結構中填充描述畫筆特性的參數
,然後調用CPen::CreatePenIndirect生成畫筆
CPen pen;
LOGPEN lp;
lp.lognStyle = PS_SOLID;//樣式
lp.lopnWidth.x = 1;//寬度
lp.lopnColor = RGB(255,0,0);//顏色
pen.CreatePenIndirect(&lp);

從以上的畫筆定義可以看出,定義畫筆需要三個特性:樣式,寬度和顏色。
畫筆的樣式說明請參見MSDN

GDI畫刷和CBrush類
在默認情況下,則Rectangle,Ellipse以及其它CDC函數畫出的封閉圖形填充着白色像素點。
通過創建GDI畫刷並在畫圖之前將它選入設備描述表,可以改變圖形的填充顏色。
MFC的CBrush類封裝了GDI畫刷。
畫刷有三種基本類型:單色、帶陰影和帶圖案。
單色畫刷填充的單色。
陰影線畫刷採用預先定義好的交叉線圖案填充圖形。
圖案畫刷用位圖來填充圖形。

創建單色畫刷的方法類似於創建畫筆,如下所示:
CBrush brush(RGB(255,0,0));

CBrush brush;
brush.CreateSolidBrush(RGB(255,0,0));

創建帶陰影線畫刷
CBrush brush(HS_DIAGCROSS,RGB(255,0,0));//陰影索引,COLORREF值

CBrush brush;
brush.CreateHatchBrush(HS_DIAGCROSS,RGB(255,0,0));
HS_DIAGCROSS是可供選擇的六種陰影線樣式之一,其它樣式請參見MSDN

注意:
在用陰影線畫刷填充時,除非用CDC::SetBkColor改變設備描述表的當前背景色,
或用CDC::SetBkMode把背景模式OPAQUE改成TRANSPARENT,禁止背景填充,
否則WIndows就以默認的背景鈀(白色)填充陰影色線間的空白處。

 

原文出處:http://blog.programfan.com/article.asp?id=19140

發佈了28 篇原創文章 · 獲贊 27 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章