閱讀937 返回首頁    go 阿裏雲 go 技術社區[雲棲]


VC++技術內幕(第四版)筆記--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);

 

最後更新:2017-04-02 06:51:27

  上一篇:go evhttp處理POST請求的技巧
  下一篇:go 窗口和視口