理解SetMapMode,SetWindowOrg,SetViewportOrg,SetWindowExt,SetViewportExt

CDC::SetMapMode 

virtual int SetMapMode( int nMapMode );

函數功能描述:該函數設置指定設備環境的映射方式,映射方式定義了將邏輯單位轉換爲設備單位的度量單位,並定義了設備的X、Y軸的方向。

nMapMode:指定新的映射方式,此參數可以是下面列出的任何一個值。

  MM_ANISOTROPIC:邏輯單位轉換成具有任意比例軸的任意單位,用SetWindowExtExSetViewportExtEx函數可指定單位、方向和比例。

  MM_HIENGLISH:每個邏輯單位轉換爲0.001英寸,X的正方面向右,Y的正方向向上。

  MM_HIMETRIC:每個邏輯單位轉換爲0.01毫米,X正方向向右,Y的正方向向上。

  MM_ISOTROPIC:邏輯單位轉換成具有均等比例軸的任意單位,即沿X軸的一個單位等於沿Y軸的一個單位,用和函數可以指定該軸的單位和方向。圖形設備界面(GDI)需要進行調整,以保證XY的單位保持相同大小(當設置窗口範圍時,視口將被調整以達到單位大小相同)。

  MM_LOENGLISH:每個邏輯單位轉換爲0.1英寸,X正方向向右,Y正方向向上。

  MM_LOMETRIC:每個邏輯單位轉換爲0.1毫米,X正方向向右,Y正方向向上。

  MM_TEXT:每個邏輯單位轉換爲一個圖素,X正方向向右,Y正方向向下。

MM_TWIPS;每個邏輯單位轉換爲打印點的120(即11400英寸),X正方向向右,Y方向向上。

 

備註:

MM_TEXT方式允許應用程序以設備像素爲單位來工作,像素的大小根據設備不同而不同。MM_HIENLISH, MM_HIMETRIC, MM_LOENGLISH, MM_LOMETRICMM_TWIPS方式對必須用物理意義單位(如英寸或毫米)製圖的應用程序是非常有用的。MM_ISOTROPIC方式保證了11的縱橫比。MM_HIENLISH方式允許對XY座標分別進行調整。

 

按習慣,(0,0)就原點,原點就是(0,0),但是如果用此來理解windows的map mode,就會走彎路。其實,稍微改變一下觀念,windows的map mode就比較好理解了。舉例說明:

page space---->device space
pDC->SetMapMode(MM_LOMETRIC);
pDC->SetWindowOrg(40,0);  //這句“設定”page space的原點爲(40,0),注意,
//這時(40,0)就是原點,原點就是(40,0)這個點,其實,(0,0)與原點沒有必然聯繫。這
//一句對下面的畫圖函數在page space中所作的圖不會有任何影響。一句話:SetWindowOrg
//就是指定一下,page space中哪個點爲原點。
pDC->Rectangle(0,0,100,-100);
pDC->Rectangle(0,-100,50,-200);

同理,SetViewportOrg也是指定一下,device space中哪個點爲原點,兩個座標系映射時,兩個原點重合

SetWindowExt設定page space的大小,SetViewportOrg設定device space的大小,其實,真正有意義的只是兩者的比例關係,例如,在一個1024*768的顯示屏上:

pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(10240,7680);
pDC->SetViewportExt(1024,768);
pDC->Rectangle(0,0,100,100);//給出的是邏輯單位,但是具體繪製出來要轉化爲設備單位,轉化比例由模式確定

  就會畫一個10 pixels*10 pixels的矩形。其本質就是,X方向,每個邏輯單位有1024/10240個象素,Y方向每個邏輯單位有768/7680個象素。因此,下面的代碼有相同的作用:

pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(102400,76800);
pDC->SetViewportExt(10240,7680);
pDC->Rectangle(0,0,100,100);

兩者本質一樣,前者更易於理解。
================================
 

SetWindowOrg和SetViewportOrg這兩個函數比較難搞懂,經過本人的google和實踐終於弄明白了這兩個函數的本質區別。

1.SetWindowOrg(x, y) 是把設備座標的原點(視口)映射到邏輯座標的(X, Y)處

2.SetViewportOrg(x, y) 是把邏輯座標的原點(窗口)映射到設備座標的(X, Y)處

3. 設備原點永遠是客戶區的左上角頂點(upper left corner of the client area)。

(後面的一幅圖顯示了這兩個函數的意義)
注意設備座標和邏輯座標的區別:

1.設備座標的X, Y軸方向固定的,單位也是固定的,X軸向右遞增,Y向下遞增,單位都是像素

2.邏輯座標的X, Y軸方向不固定單位不固定,根據選擇的映射模式而變化。

有了以上的解釋,相信大家應該能明白爲什麼下面的代碼的現實結果會是這樣的了吧。

void CEx05aView::OnDraw(CDC* pDC)
{
pDC->SetMapMode(MM_LOMETRIC);
pDC->SetWindowOrg(100, 100);
pDC->Rectangle(0, 0, 200, 200);

pDC->SetViewportOrg(100, 100);
pDC->SelectStockObject(GRAY_BRUSH);
pDC->Rectangle(0, 0, 200, 200);
}

 

====================================================

建立一個合適的座標系可以爲我們的繪圖帶來很大的方便 。下面介紹一下如何在VC中建立我們想要的座標系。
一 設備座標和邏輯座標
  設備座標(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軸向上爲正。

MM_LOENGLISH、MM_HIENGLISH、MM_LOMETRIC、MM_HIMETRIC、MM_TWIPS這一組是Windows提供的重要的固定比例映射模式。

它們都是x值向右方向遞增,y值向下遞減,並且無法改變。它們之間的區別在於比例因子見下:(我想書上P53頁肯定是印錯了,因爲通過程序實驗x值向右方向也是遞增的)

MM_LOENGLISH 0.01英寸
MM_HIENGLISH 0.001英寸
MM_LOMETRIC 0.1mm
MM_HIMETRIC 0.01mm
MM_TWIPS 1/1440英寸 //應用於打印機,一個twip相當於1/20磅,一磅又相當於1/72英寸。

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