SetWindowOrg

SetWindowOrg是設定設備上下文的視窗初始位置(LP:Logical point)。它和設備上下文視窗一起說明了GDI如何將邏輯坐標(LP)中的點映射到實際設備坐標(DP)中。換言之,它們說明了GDI如何將邏輯坐標轉換為設備坐標。內部的機制就是進行坐標點的平移轉換。

基本信息

CDC::SetWindowOrg

CPoint SetWindowOrg(int x ,int y );

CPoint SetWindowOrg(POINT point )

返回值:CPoint對象,是視窗初始位置的前一次取值(邏輯單位)。

參數: x 指定視窗初始位置的X邏輯坐標。

y 指定視圖連線埠初始位置的Y邏輯坐標。

point 指定視窗初始位置。其值必須在設備坐標系統範圍內。可以為該參數傳遞POINT結構或CPoint對象。

說明

視窗初始位置表明在設備坐標系統中的點,GDI將視圖連線埠初始位置與該點映射。視窗初始位置是由SetWindowOrg成員函式在邏輯坐標系統中指定的。GDI在映射其它點時遵從同樣的過程,這需要視窗初始位置與視圖連線埠初始位置的映射。例如,所有以視窗初始位置為中心的圓周上的點同樣是以視圖連線埠初始位置為中心的圓周上的點。同樣地,通過視窗初始位置的直線上的所有點也將形成一條通過視圖連線埠初始位置的直線。

在CMyStatic::OnPaint() 函式中測試

CPaintDC dc(this); // device context for painting

// TODO: Add your message handler code here

CRect rect;

GetClientRect(▭);//取得控制項大小

dc.SetMapMode(MM_ANISOTROPIC);//設定成可以改變作標軸方向和比例的,但下面沒改變比例

1.先討論X軸正向向左,Y軸正向向下的情況,即默認的狀態

dc.SetWindowExt(100, 100);// 邏輯上是長100個單位,寬100個單位

dc.SetViewportExt(200,200);//設備是長200像素,寬200像素

即一個邏輯單位 = 200 / 100 = 2個像素

如果上面第一行改成dc.SetWindowExt(100, 200);//那么,一個邏輯長單位就是2像素,邏輯高單位就是1個像素

同樣的dc.Rectangle(0, 0, 10, 10);第一個就是正方形,而第二個就是長是寬2倍的長方形

2.關於設備原點和邏輯原點的問題。

我的理解是,設備原點永遠在左上角,也就是最初的(0,0)的位置

邏輯原點是可以移動的,Y軸的正向是向上還是向下是可以改變的

考慮Y軸向下為正向時,邏輯原點的移動問題。

dc.SetWindowOrg(0, 0);//這個可省略

dc.SetViewportOrg(rect.right, rect.bottom);

這個就是把設備的(rect.right, rect.bottom)映射為邏輯原點(0, 0)

那就就相當於,把邏輯原點從原來設備原點(0,0)平移到了(rect.right, rect.bottom)

即整個作標系,向右平移了rect.right,向下平移了rect.bottom.

dc.SetViewportOrg(0, 0);//這個可省略

dc.SetWindowOrg(rect.right, rect.bottom);

這個是把邏輯的(rect.right, rect.bottom)映射為設備的(0, 0);也可以說是把設備的(0, 0)映射為邏輯的(rect.right, rect.bottom)

可以想像,設備原點(0, 0)永遠在左上角,由於Y軸是向下為正,X軸向右為正,那邏輯原點就被向上移動了rect.bottom,向左移動了rect.right,這樣,剛好邏輯坐標(rect.right, rect.bottom)落在了右上角的位置。

然而dc.Rectangle(0, 0, rect.right, rect.bottom);畫出的長方形,就正好完全落在視窗這外了

要想和dc.SetViewportOrg(rect.right, rect.bottom);達到相同的效果,

必須要把邏輯原點向右和向下移動,也就是,移動動後的邏輯坐標(-rect.right, -rect.bottom);落在設備原點上,即把邏輯的(-rect.right, -rect.bottom)映射為設備的(0, 0);

dc.SetWindowOrg(-rect.right, -rect.bottom);

如果SetWindowOrg和SetViewportOrg同時使用,例如

dc.SetWindowOrg(x, y);

dc.SetViewportOrg(x1, y1);//不推薦同時用,因為通常會把自己給搞糊塗(此處假設x>x1, y>y1)

即把邏輯坐標(x, y)映射為設備坐標(x1, y1),就相當於把邏輯原點向右移(x - x1),或者(x1 - x)當x1>x時, 向下移(y - y1)或者(y1 - y)當y1>y時;一定要注意,設備坐標點是不變的,變化的是邏輯坐標點

綜上所述,X軸正向向右,Y軸正向向下的情況下,

dc.SetWindowOrg(-rect.right, -rect.bottom);等價於dc.SetViewportOrg(rect.right, rect.bottom);

而dc.SetViewportOrg(rect.right, rect.bottom);和dc.SetViewportOrg(rect.right, rect.bottom);剛互補,同時運行則效果抵消。

3.X軸正向向左,Y軸正向向上的情況

dc.SetWindowExt(100, -100) ;//邏輯上是長100個單位,寬100個單位

dc.SetViewportExt(200,200);//設備是長200像素,寬200像素

dc.SetWindowExt(100, 100 );//邏輯上是長100個單位,寬100個單位

dc.SetViewportExt(200,-200);//設備是長200像素,寬200像素

如果

dc.SetWindowExt(100, -100);//邏輯上是長100個單位, 寬100個單位

dc.SetViewportExt(200,-200);//設備是長200像素,寬200像素

則Y軸仍向下

以下面為例:

dc.SetWindowExt(100, - 100);//邏輯上是長100個單位,寬100個單位

dc.SetViewportExt(200,200);//設備是長200像素,寬200像素

dc.SetWindowOrg(0, 0);//這個可省略

dc.SetViewportOrg(0, rect.bottom);

設備(0, rect.bottom)映射為邏輯原點(0, 0),即把邏輯原點,移到左下角了

dc.SetViewportOrg(0, 0);//這個可省略

dc.SetWindowOrg(0, rect.bottom);

邏輯(0, rect.bottom);映身為設備原點(0,0),即設備原點(0, 0)映射為邏輯(0, rect.bottom);由於Y軸向上,所以相當於把邏輯原點由設備原點,向下移動rect.bottom,這樣,邏輯(0, rect.bottom)剛好落在設備原點(0,0)上。即邏輯原點移動到了左下角。

這時可以發現,dc.SetViewportOrg(0, rect.bottom);與dc.SetWindowOrg(0, rect.bottom);等價了

推廣開來,即dc.SetViewportOrg(x, y);與dc.SetWindowOrg(-x, y);等價

總結:保持X軸正向向右不變,當Y軸正向向下時

dc.SetViewportOrg(x, y);與dc.SetWindowOrg(-x, -y);等價

當Y軸正向向上時

dc.SetViewportOrg(x, y);與dc.SetWindowOrg(-x, y);等價

需要強調一點,設備原點永遠不會移動,保持在(0,0),設備的坐標系永遠不會變,變的是邏輯原點在設備坐標系中的位置和邏輯坐標軸的方向。

相關詞條

熱門詞條

聯絡我們