屏幕坐標系和窗口客戶區坐標系最明顯的區別在於坐標原點,屏幕坐標系的坐標原點在整個屏幕的左上角,而窗口客戶區坐標系的坐標原點在窗口客戶區的左上角,通常這兩個點是不重合的。
一 設備坐標和邏輯坐標
設備坐標(Device Coordinate)又稱為物理坐標(Physical Coordinate),是指輸出設備上的坐標。通常將屏幕上的設備坐標稱為屏幕坐標。設備坐標用對象距離窗口左上角的水平距離和垂直距離來指定對象的位置,是以像素為單位來表示的,設備坐標的X軸向右為正,Y軸向下為正,坐標原點位於窗口的左上角。
邏輯坐標(Logical Coordinate)是系統用作記錄的坐標。在缺省的模式(MM_TEXT)下,邏輯坐標的方向和單位與設備坐標的方向和單位相同,也是以像素為單位來表示的,X軸向右為正,Y軸向下為正,坐標原點位於窗口的左上角。邏輯坐標和設備坐標即使在缺省模式下其數值也未必一致,除了在以下兩種情況下:
1. 窗口為非滾動窗口
2. 窗口為滾動窗口,但垂直滾動條位於滾動邊框的最上端,水平滾動條位於最左端,但如果移動了滾動條這兩種坐標就不一致了。
在VC中鼠標坐標的坐標位置用設備坐標表示,但所有GDI繪圖都用邏
坐標表示,所以用鼠標繪圖時,那么必須將設備坐標轉換為邏輯坐標,可以使用CDC 函數DptoLP()將設備坐標轉化為邏輯坐標,同樣可以用LptoDP()將邏輯坐標轉化為設備坐標。
二 坐標模式
為了在不同的領域使用邏輯坐標,Windows提供了以下8種坐標模式:
分別為MM_TEXT、MM_HIENGLISH、MM_LOENGLISH、MM_HIMETRIC、MM_LOMETRIC、MM_TWIPS、MM_ANISOTROPIC和MM_ISOTROPIC。
三 實例解析
(一) 建立以左上角為原點,X軸和Y軸為1000的坐標,如下圖
我們可以用以下代碼:
void CTtView::OnDraw(CDC* pDC)
{
CTtDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CRect rect;
GetClientRect(&rect);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetViewportOrg(0,0);
pDC->SetViewportExt(rect.right,rect.bottom);
pDC->SetWindowOrg(0,0);
pDC->SetWindowExt(1000,1000);
pDC->MoveTo(50,50);
pDC->LineTo(50,950);
pDC->LineTo(950,950);
pDC->LineTo(50,50);
}
代碼分析:
1. GetClientRect(&rect); 取得客戶區矩形區域,將其存放在rect中
2. 用pDC->SetMapMode(MM_ANISOTROPIC); 設置映射模式
3. 通過pDC->SetViewportOrg(0,0);設置邏輯坐標的原點
4. 通過pDC->SetViewportExt(rect.right,rect.bottom);和
pDC->SetWindowExt(1000,1000);來確定邏輯坐標下和設備坐標下的尺寸對應關系
5. 在MM_ANISOTROPIC模式下,X軸單位和Y軸單位可以不相同
6. 坐標方向的確定方法是如果邏輯窗范圍和視口范圍符號相同,則邏輯坐標的方向和視口的方向相同,即X軸向右為正,Y軸向下為正。
7. 如果將顯示模式改為MM_ISOTROPIC,那么X軸單位和Y軸單位一定相同,感興趣的讀者可以自己使一下。
(二) 建立以視窗中心為原點的坐標,如下圖
用如下代碼:
void CTtView::OnDraw(CDC* pDC)
{
CTtDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CRect rect;
GetClientRect(&rect);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetViewportOrg(rect.right/2,rect.bottom/2);
pDC->SetViewportExt(rect.right,rect.bottom);
pDC->SetWindowOrg(0,0);
pDC->SetWindowExt(1000,-1000);
pDC->MoveTo(150,150);
pDC->LineTo(-150,-200);
pDC->LineTo(150,-150);
pDC->LineTo(150,150);
}
代碼分析:
1. 用 pDC->SetViewportOrg(rect.right/2,rect.bottom/2); 設置視口的原點。
2. 用pDC->SetViewportExt(rect.right,rect.bottom);和pDC->SetWindowExt(1000,-1000);來確定設備坐標和邏輯坐標的單位對應關系。
3. 因為邏輯窗范圍和視口范圍的符號不一致,縱坐標取反,所以Y軸向上為正。