GetWindowRect和GetClientRect的區別詳解

來源:互聯網
上載者:User

標籤:style   blog   http   color   strong   os   

一:關於座標

  MFC中繪圖時經常涉及到座標計算,GetWindowRect和GetClientRect這兩個函數,是擷取邏輯座標系中視窗或控制項(其實也是視窗)大小和座標的常用函數了,有什麼不一樣的?

先說說什麼叫邏輯座標?講到邏輯座標,它相對的一個概念是裝置座標,是為了屏蔽掉不同裝置屬性差別而設定的抽象座標系,說白了,就是獨立於裝置座標的統一介面,程式員不需要去在具體的裝置上進行繪圖操作,而只需要在虛擬環境下進行繪圖,就是CDC。

然後由裝置驅動去負責虛擬座標到實際裝置座標之間的轉換。通常邏輯座標與裝置座標之間有不同的映射轉換關係,預設模式下的映射方式是MM_TEXT,這種方式下的邏輯座標的方向和單位與裝置座標的相同,也是以像素為單位來表示,X軸向右為正,Y軸向下為正,座標原點位於視窗的左上方

然後再說上面的兩個函數之間的差別:

GetWindowRect得到的是相對於當前介面的整個視窗左上方的座標,比如一個對話方塊程式,那就是相對於對話方塊左上方的座標,從左往右是X方向,從上往下是Y方向。

注意:這個函數的相對座標原點分兩種情況:

1 視窗還沒有初始化完成時:原點是整個視窗的左上方

2 初始化完成後,原點是裝置螢幕左上方

GetClientRect得到的是相對於視窗客戶區左上方的座標。

二:驗證

下面通過一段代碼來理解:

建立一個MFC對話方塊程式,在Dialog資源中,把一個靜態框加入進來。OnInitDialog中添加如下代碼:

BOOL CmfcdialogtestDlg::OnInitDialog(){/*.............其它代碼.............*//*****************for testing***************/    CRect wndRect1;    CRect wndRect2;    /****首先看對話方塊的******/    this->GetWindowRect(&wndRect1); //PrintRect("Dialog:GetWindowRect", wndRectScreen1);    this->ScreenToClient(&wndRect1); //PrintRect("Dialog:ScreenToClient", wndRectClient1);    this->GetClientRect(&wndRect2); //PrintRect("Dialog:GetClientRect", wndRectClient2);    this->ClientToScreen(&wndRect2); //PrintRect("Dialog:ClientToScreen", wndRectScreen2);    /****再看控制項的**********/    CRect ctrlRect1;    CRect ctrlRect2;    CStatic *pCtrl = (CStatic*)GetDlgItem(IDC_STC_TEST);    pCtrl->GetClientRect(&ctrlRect1); //PrintRect("static:GetClientRect", ctrlRectClient1);    pCtrl->ClientToScreen(&ctrlRect1); //PrintRect("static:ClientToScreen", ctrlRectScreen1);    pCtrl->GetWindowRect(&ctrlRect2); //PrintRect("static:GetWindowRect", ctrlRectScreen2);    pCtrl->ScreenToClient(&ctrlRect2); //PrintRect("static:ScreenToClient", ctrlRectClient2);    /*****************ending********************//*.............其它代碼.............*/}

 

三:分析

我們分別觀察對整個對話方塊和靜態控制項,分別調用這兩個函數的效果。首先看看對話方塊的:

(1)對話方塊部分的程式運行結果:

對話方塊:GetWindowRect: +        &wndRect1    0x0017f410 {top=0 bottom=378 left=0 right=566}    CRect *ScreenToClient:+        &wndRect1    0x0017f410 {top=-25 bottom=353 left=-3 right=563}    CRect *GetClientRect: +        &wndRect2    0x0017f3f8 {top=0 bottom=350 left=0 right=560}    CRect *ClientToScreen:+        &wndRect2    0x0017f3f8 {top=25 bottom=375 left=3 right=563}    CRect *

我們給出一份圖片分析:

第一個GetWindowRect得到的是整個視窗相對於視窗左上方的座標,實際上就是這個對話方塊的大小。

然後ScreenToClient,注意了,我們發現top和left都變成了負值?為什麼呢,因為這個時候的轉換是基於Client的原點進行的,即客戶區的左上方。因為原來的視窗左上方位於Client原點的左上方,所以是負值。

第二個GetClientRect得到的是客戶區的大小,因為不包含視窗周邊的藍色地區,所以比第一個的視窗大小要小。

然後ClientToScreen,這個就很好解釋了,計算相對於視窗左上方的座標。你可以自己動手算一下。

(2)控制項的程式運行結果:

控制項:GetClientRect:    +        &ctrlRect1    0x0017f3e0 {top=0 bottom=170 left=0 right=285}    CRect *ClientToScreen:  +        &ctrlRect1    0x0017f3e0 {top=127 bottom=297 left=73 right=358}    CRect *GetWindowRect:    +        &ctrlRect2    0x0017f3c8 {top=127 bottom=297 left=73 right=358}    CRect *ScreenToClient:  +        &ctrlRect2    0x0017f3c8 {top=0 bottom=170 left=0 right=285}    CRect *

還是圖片分析:

同理,第一個GetClientRect得到是控制項的大小。

然後ClientToScreen,可以看到這個時候,控制項相對於對話方塊視窗左上方的位移是(127,73)。

第二個GetWindowRect,得到的值與上面的值相同,這個很好理解了,他們的含義是一樣的,就是控制項在視窗中的座標。

然後ScreenToClient,得到的值與第一個GetClientRect的值一樣。不多說了

為什麼對話方塊和控制項的轉換之間略有差別(兩次轉換結果不太一樣),主要是對話方塊包含了非客戶區,使得相對座標不一致。

 

四:小結

算是把這個小問題給弄清楚了,適合和我一樣的新手學習。網上太多資料,很多都是錯的,還是自己動手,豐衣足食~!有錯誤,請指正!

可以看看這篇博文:http://www.cnblogs.com/flying-roc/articles/1970298.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.