視口

視口

在 Windows的作圖函數中,涉及邏輯坐標到設備坐標的轉換。這裡提到的窗口(window)、視口(viewport)是對應的概念。視口是與設備相關的一個矩形區域,坐標單位是與設備相關的“像素”,大多數情況下,視口與客戶區相同。窗口的坐標是邏輯坐標,與設備無關,可能是像素、毫米或者英寸。窗口坐標的原點與視口坐標的原點始終對應於同一點。對於同一個圖形,用窗口坐標系統表達的該區域的長和寬與視口的坐標系統表達的長和寬是不同的。二者就定義了這兩個坐標系統的比例關係。程序作圖時,使用的坐標總是是窗口坐標。而實際的顯示或輸出設備卻各有自己的坐標。

概述


繪圖操作只能在客戶區中進行。除客戶區以外的部分都叫非客戶區
例如,有的印表機設備水平和垂直解析度不同,其像素實際上是長方形。程序編寫畫一個圓,若不經任何坐標轉換,在印表機上輸出的就是個橢圓。下面程序示範了如何將窗口邏輯坐標的x,y向象素寬度均映射為輸出設備中的 1/64 英寸。

代碼


[code]
SetMapMode(hDC, MM_ISOTROPIC);
SetWindowExt(hDC, 64, 64, NULL);
SetViewportExt(hDC, GetDeviceCaps(hDC, LOGPIXELSX),
GetDeviceCaps(hDC, LOGPIXELSY), NULL);
[/code]

代碼解釋


調用SetWindowExt()函數后,緊接著應調用SetViewportExt()函數,它的任務是規定水平及垂直坐標軸的單位。可以這樣認為,SetWindowExt()函數對應著“窗口”,SetViewportExt()函數對應著“視口”。幾點:
1.窗口是基於邏輯坐標的.
2.視口是基於設備坐標.
3.設備坐標是以像素為單位的,邏輯坐標是以.cm,m,mm,.....
4.系統最後一定要把邏輯坐標變為設備坐標.
5.設備坐標有3種:
a.GetDC() 客戶區坐標.
b.GetWindowDC().窗口坐標.
c.GetDC(NULL),or CreateDC() .屏幕坐標.

問題


問題如下:
void CMyView::OnDraw(CDC *pDC)
{
...
(1):pDC->SetMapMode(MM_ISOTROPIC);
(2):pDC->SetWindowExt(4000,3000);
(3):AfxGetMainWnd()->GetClientRect(cRect);
(4):pDC->SetViewportExt(cRect.Width(),-cRect.Height ()/2);
(5):pDC->DPtoLP(cRect);
(6):pDC->SetWindowOrg(-(cRect.Width()/2),-(cRect.Height()/2));
(7):pDC->TextOut(-850,1400,"abc");
...
}
我想問一下:上面每一步執行完后,窗口和視口的原點、範圍分別是多少?屏幕解析度是(800,600)。謝謝!

問題解釋


第一句:定義邏輯單位和具體的設備單位的映射模式
第二句:設置與設備上下文關聯的窗口的X和Y坐標的範圍。其中4000和3000是邏輯坐標。此時窗口大小為(4000,3000),視口大小未知。
第三句:得到客戶區尺寸。此尺寸就是當前視口尺寸。如果(800,600),在最大化時此尺寸為(800,600).
第四句:設置視口的範圍,第二個參數為負數,表示視口坐標往下移了cRect高度的一半。
第五句:將設備坐標轉換成邏輯坐標。因為GetClientRect得到的設備坐標
第六句:設置設備上下文窗口的起始坐標。
最後一句:在第六句的基礎上,在邏輯坐標位置輸出文本abc. 記住兩個原則:
1.總是由窗口原點映射為視口原點。即無論你窗口的原點和視口的原點怎麼變,窗口的原點總是映射到視口的原點。(記住:映射方向是窗口到視口,而不是視口向窗口映射)
2.不管利用函數(如:SetViewportOrgExt和SetWindowOrgEx)對窗口和視口的原點做怎麼改變,設備點(0,0)始終是客戶區的左上角。