1. 程式人生 > >MFC 邏輯座標原點與裝置座標原點的移動

MFC 邏輯座標原點與裝置座標原點的移動

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

參考:http://blog.csdn.net/benny5609/archive/2007/10/26/1845645.aspx

http://www.cnblogs.com/finema/archive/2011/05/30/2059067.html http://baike.baidu.com/view/4059670.htm 這幾個網站上講的不太全面,自己正在總結,先佔個坑 自己總結,不對的地方望大家指正:
《MFC Windows 程式設計》P41中講解的關於SetWindowOrg和SetViewportOrg的使用,這裡先呈上自己摘自網路和課本的一些知識: ①原點概念的理解:在數學中常稱點(0,0)為座標原點,但是在windows中原點是一個座標,但並未必是(0,0)點。原點這個說法的使用時為了聯絡裝置座標和邏輯座標---裝置座標的原點一定要和邏輯座標的原點重合。 ②對映模式被定義為從視窗(window也即邏輯座標)到視口(viewport也即裝置座標)的對映,具體的內容可以參考:《MFC Windows 程式設計》P36和《Windows程式設計》P147。 ③既然用座標來標註裝置座標系和邏輯座標系的原點,那麼二者座標值的求取必須具有同一個參考物件,也就是說必須有一個參考點來確定裝置座標中原點和邏輯座標中的原點的座標。在windows中選擇裝置座標點(0,0)為參考點,裝置座標點(0,0)始終都位於客戶區的左上角。(
《Windows程式設計》P147 ④傳送給CDC輸出函式的是邏輯座標,《MFC Windows 程式設計》P36 邏輯座標:可理解成幾何作業本上的直角座標系,座標值是無限的,Windows的繪圖是以邏輯座標作為引數,也就是說Windows繪圖是在邏輯平面上進行的。 裝置座標:是物理的,就理解成手上拿著的方形框框(如顯示器),通過該方框可以看到在邏輯平面上所畫的東西。裝置座標的左上角永遠是(0,0)點,且X軸的正方向向右,Y軸的正方向向下。裝置總是有尺寸的,只能顯示某個範圍的內容。 預設情況下,邏輯座標採用MM_TEXT對映模式,該對映模式下邏輯座標的方向與裝置座標系的方向相同:X軸的正方向向右,Y軸的正方向向下。再加上座標原點重合,故給人的感覺是隻有一個座標系,具體如圖1所示:

MFC <wbr>邏輯座標原點與裝置座標原點的移動

圖1

⑥舉例說明SetWindowOrg和SetViewportOrg的使用

在預設的情況下邏輯座標到裝置座標的對映模式為:MM_TEXT,為方便起見這裡不再更改對映模式,在預設的情況下:視窗原點為(0,0)點,視口原點也為(0,0)點。

假設將裝置原點移到視窗的中心點,即現有的視口原點不再是(0,0)而是視窗中心點。

設dc為一個裝置描述表物件,具體實現如下:

CRect rect;
GetClientRect (&rect);//返回的是裝置座標,而SetViewportOrg需要的也是裝置座標,故此處不用轉換
dc.SetViewportOrg (rect.Width ()/2, rect.Height ()/2);

圖解分析如圖2所示

MFC <wbr>邏輯座標原點與裝置座標原點的移動

圖2

具體分析:Ⅰ:將視口原點由(0,0)點移至(x,y)等價於把邏輯點(0,0)對映成裝置點(x,y)。 Ⅱ:裝置座標原點與邏輯座標原點必須重合。 Ⅲ:預設情況下邏輯座標的原點為(0,0)點,且本處只移動了裝置座標原點,並沒有移動邏輯座標原點,故邏輯座標的原點仍為(0,0)點,不過要滿足Ⅱ中的條件,邏輯座標系發生了移動,移動結果如圖2所示,此時移動後的裝置原點(rect.Width ()/2, rect.Height ()/2)與邏輯原點(0,0)重合。 ⑦在上面的⑥中將視口原點移到視口的中點,並完成了將邏輯原點到視口中點的對映。為達到相同的效果,用
SetWindowOrg移動邏輯座標原點也可以達到相同的效果。
為使理解更加清晰透徹,這裡做了兩組對比的實驗 實驗一: CRect rect;
GetClientRect (&rect);
CPoint point (rect.Width () / 2, rect.Height () / 2);
dc.DPtoLP (&point);
dc.SetWindowOrg (point.x, point.y);
該實驗的邏輯座標原點移動的示意圖如圖3所示:

MFC <wbr>邏輯座標原點與裝置座標原點的移動

圖3

在圖3中若進行正常移動則邏輯原點將移至裝置座標系的中點,為保證邏輯原點與裝置原點的重合,必須移動裝置原點(注:由於裝置原點沒有移動,仍是(0,0)點),但是根據規定裝置座標點是不能移動的,由前面的③可知,作為參考點的裝置點(0,0)是不能移動的,不過此處裝置點(0,0)恰好又是裝置原點而已,故不能移動。既然裝置原點不能移動,卻又要滿足邏輯座標原點(point.x, point.y)與裝置座標原點(0,0)的重合,只能進行等價移動邏輯座標系,移動如圖3所示:很明顯邏輯座標原點為(point.x, point.y)且滿足改點與
裝置座標原點(0,0)的重合。不過對比圖2,很明顯通過對裝置座標原點進行該種移動不能達到相同的效果,即實驗一並未得到與⑥中同樣的結果。

實驗二
CRect rect;
GetClientRect (&rect);
CPoint point (rect.Width () / 2, rect.Height () / 2);
dc.DPtoLP (&point);
dc.SetWindowOrg (-point.x, -point.y);
該實驗的邏輯座標原點移動的示意圖如圖4所示:

MFC <wbr>邏輯座標原點與裝置座標原點的移動

圖4

具體的分析與實驗一類似,這裡不再贅述了,與圖2對比很明顯得到:對邏輯座標原點進行這種移動可達到與移動裝置座標原點相同的效果,但有一點值得注意:達到的效果相同,但進行這種移動後設備座標原點為(0,0),邏輯座標原點為(-point.x, -point.y),而在圖2中經過移動裝置座標原點後:裝置原點為(rect.Width ()/2, rect.Height ()/2),邏輯原點為(0,0)。
總結:關於其餘對映模式下的移動以及同時採用邏輯座標原點和誰被座標原點移動的情況同樣可採用上面的分析方法,不過特別注意不同對映模式下的原點移動
P.S.本文是作者本文根據網站參考資料和書籍進行的總結,有不對之處望大家指正,在此也謝過網友博文的指點。