SetWindowExt和SetViewportExt

CRect rectClient;

GetClientRect(rectClient);

pDC->SetMapMode(MM_ANISOTROPIC);

pDC->SetWindowExt(CSize(1000,1000));

pDC->SetViewportExt(rectClient.right,-rectClient.bottom);

pDC->SetViewportOrg(rectClient.right/2,rectClient.bottom/2);

pDC->Ellipse(-500,-500,500,500);

 

可變比例映射模式,看到這一段的時候,一開始就把我的弄糊塗了。我一直沒弄明白中間加紅的幾行代碼是什麼意思。把其註釋掉,又沒有原先的效果。在網上百度了半天。得出以下注釋說明:

 

//SetWindowExe設定窗口尺寸,SetViewportExt設定視口尺寸。

//窗口尺寸以邏輯單位計算,視口尺寸以物理單位計算。

CRect rectClient;

  

GetClientRect(rectClient);//取窗口物理尺寸(單位:像素)

pDC->SetMapMode(MM_ANISOTROPIC);

pDC->SetWindowExt(1000, 1000);//窗口邏輯大小:1000*1000,

pDC->SetViewportExt(rectClient.right, -rectClient.bottom);//改變Y座標方向--viewport使用物理大小

pDC->SetViewportOrg(rectClient.right / 2, rectClient.bottom / 2);//設置窗口中心點爲座標系原點--Viewport使用物理大小  

pDC->Ellipse(CRect(-500, -500, 500, 500));//以邏輯單位畫圖---普通GDI API使用邏輯單位

 

//默認方式下,物理/邏輯值是11關係,可換用。但使用SetWindowExt/SetViewportExt後兩者不可混用。

 

以上紅色部分,我的解釋是以物理的原點爲座標系,以邏輯的大小爲單位畫圓。後面的代碼中會說明這一問題。

後來經過自己的捉摸,我想我終於搞清楚是怎麼一回事情了。

所謂映射就是物理和邏輯的映射。使用GetClientRect方法後,獲取到窗口的物理大小;然後再使用SetWindowExt,設置了窗口的邏輯大小,與之相對應的是SetViewportExt,也就是說在這裏作了一個映射。SetWindowExt中的第一個參數

cx
Specifies the x-extent (in logical units) of the window.

X寬度(可以這麼理解嗎?)與 SetViewportExt中的第一個參數

Cx
Specifies the x-extent of the viewport (in device units).

相對應起來。好像中學的比例一樣。邏輯寬度和物理寬度映射,邏輯高度和物理高度映射。這樣,一旦映射關係確立之後,再使用後面的方法進一步的操作。

 

一開始的代碼是在窗口中顯示一個與之限定的圓,並且會隨着窗口大小的改變亦會跟着改變。

 

我現在稍稍把其中的參數改變一下。

 

CRect rectClient;

GetClientRect(rectClient);

 

pDC->SetMapMode(MM_ANISOTROPIC);

pDC->SetWindowExt(CSize(800,800));

pDC->SetViewportExt(rectClient.right,-rectClient.bottom);

pDC->SetViewportOrg(rectClient.right/2,rectClient.bottom/2);

pDC->Ellipse(-500,-500,500,500);

 

注意上面紅色突出顯示的代碼。我現在將邏輯大小變小了一些。現在注意一下實際在畫圖的代碼中(綠色顯示),我並沒有修改其參數。現在將其編譯運行。會發現,實現中的圓的軌跡會超出窗口。

只是把物理與邏輯之前的映射調整了一下。

 

CRect rectClient;

GetClientRect(rectClient);

 

pDC->SetMapMode(MM_ANISOTROPIC);

pDC->SetWindowExt(CSize(1000,1000));

pDC->SetViewportExt(rectClient.right,-rectClient.bottom);

pDC->SetViewportOrg(rectClient.right/2,rectClient.bottom/2);

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

 

再調整一下參數,畫出來的圖你會發現,真正的成了二維座標圖。

 

經過以上一番測試,我想我應該明白每行代碼的意思了。轉換成自己的註釋,應該更容易理解和記憶些。

 

CRect rectClient;

GetClientRect(rectClient); //獲取物理設備大小

 

pDC->SetMapMode(MM_ANISOTROPIC); //設置映射模式

pDC->SetWindowExt(CSize(1000,1000));    //設備邏輯窗口大小(可能與物理窗口大小不一樣)

pDC->SetViewportExt(rectClient.right,-rectClient.bottom); //設置物理設備範圍,爲設定圓點作準備

pDC->SetViewportOrg(rectClient.right/2,rectClient.bottom/2); //設置物理設備座標原點,當然是在上一行代碼的基礎之上

pDC->Ellipse(-500,-500,500,500); //以物理設置座標原點爲基礎,以邏輯爲單位,畫圓。


可以改造一下,原來的代碼,使之後容易理解一些:

CRect rectClient;

GetClientRect(rectClient);

 

pDC->SetMapMode(MM_ANISOTROPIC);

pDC->SetWindowExt(CSize(1000,1000));

pDC->SetViewportExt(rectClient.right,-rectClient.bottom);

pDC->SetViewportOrg(rectClient.left,rectClient.bottom); //設置窗口左下角爲原點座標

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章