Windows應用程序繪制圖形時使用的是一種邏輯單位,每個邏輯單位的大小由映射模式決定, 這個邏輯單位既可以與設備單位(屏幕或打印機上的一個像素點)相同,也可以是一種物理單 位(如毫米),還可以是用戶自定義的一種單位。在Windows應用程序中,只要與輸出有關系,都 要使用映射模式。本文的目的是幫助讀者了解映射模式的一些基本知識,並對在使用中經常 出現的一些問題提出解決方案。
一、映射模式基本知識
當Windows應用程序在其客戶區繪制圖形時,必須給出在客戶區的位置,其位置用x和y 兩個坐標表示,x表示橫坐標,y表示縱坐標。在所有的GDI繪制函數中,這些坐標使用的是一 種"邏輯單位"。當GDI函數將輸出送到某個物理設備上時,Windows將邏輯坐標 轉換成設備坐標(如屏幕或打印機的像素點)。邏輯坐標和設備坐標的轉換是由映射模式決 定的。映射模式被儲存在設備環境中。GetMapMode函數用於從設備環境得到當前的映射模 式,SetMapMode函數用於設置設備環境的映射模式。
1.邏輯坐標
邏輯坐標是獨立於設備的,它與設備點的大小無關。使用邏輯單位,是實現"所見即所得"的基礎。當程序員在調用一個畫線的GDI函數LineTo,畫出25.4mm(1英寸) 長的線時,他並不需要考慮輸出的是何種設備。若設備是VGA顯示器,Windows自動將其轉化為96個像素點;若設備是一個300dpi的激光打印機,Windows自動將其轉化為300個像素點。
2.設備坐標
Windows將GDI函數中指定的邏輯坐標映射為設備坐標,在所有的設備坐標系統中,單位以像素點為准,水平值從左到右增大,垂直值從上到下增大。
Windows中包括以下3種設備坐標,以滿足各種不同需要:
(1)客戶區域坐標,包括應用程序的客戶區域,客戶區域的左上角為(0,0)。
(2)屏幕坐標,包括整個屏幕,屏幕的左上角為(0,0)。屏幕坐標用在WM_MOVE消息中(對於非子窗口)以及下面的Windows函數中:CreateWindow和MoveWindow(都對於非子窗口)、GetMessage、GetCursorPos、GetWindowRect、WindowFromPoint和SetBrushOrg中。用函數ClientToScreen和ScreenToClient可以將客戶區域坐標轉換成屏幕區域坐標,或反之。
(3)全窗口坐標,包括一個程序的整個窗口,包括標題條、菜單、滾動條和窗口框,窗口的左上角為(0,0)。使用GetWindowDC得到的窗口設備環境,可以將邏輯單位轉換成窗口坐標。
3.邏輯坐標與設備坐標的轉換方式
映射方式定義了Windows如何將GDI函數中指定的邏輯坐標映射為設備坐標。要繼續討論映射方式我們要介紹Windows有關映射模式的一些術語:我們將邏輯坐標所在的坐標系稱為"窗口",將設備坐標所在的坐標系稱為"視口"。
"窗口"依賴於邏輯坐標,可以是像素點、毫米或程序員想要的其他尺度。
"視口"依賴於設備坐標(像素點)。通常,視口和客戶區域等同。但是,如果程序員用GetWindowDC或CreateDC獲取了一個設備環境,則視口也可以指全窗口坐標或屏幕坐標。點(0,0)是客戶區域的左上角。x的值向右增加,y的值向上增加。
對於所有映射模式,Windows都用下面兩個公式將窗口坐標轉換成視口坐標:
xViewport=(xWindow-xWinOrg)*(xViewExt/xWinExt)+xViewOrg
yViewport=(yWindow-yWinOrg)*(yViewExt/yWinExt)+yViewOrg
其中,(xWindow,yWindows)是待轉換的邏輯點,(xViewport,yViewport)是轉換後的設備點。如果設備坐標是客戶區域坐標或全窗口坐標,則Windows在畫一個對象前,還必須將這些坐標轉換成屏幕坐標。
這兩個公式使用了分別指定窗口和視口原點的點:(xWinOrg,yWinOrg)是邏輯坐標的窗口原點;(xViewOrg,yViewOrg)是設備坐標的視口原點。在缺省的設備環境中,這兩個點均設置為(0,0),但它們可以改變。此公式意味著,邏輯點(xWinOrg,yWinOrg)總被映射為設備點(xViewOrg,yViewOrg)。
Windows還能將視口(設備)坐標轉換為窗口(邏輯)坐標:
xWindow=(xViewport-xViewOrg)*(xWinExt/xViewExt)+xWinOrg
yWindow=(yViewport-yViewOrg)*(yWinExt/yViewExt)+yWinOrg
可以使用Windows提供的兩個函數DPtoLP和LPtoDP在設備坐標及邏輯坐標之間互相轉換。