GetWindowRect和GetClientRect的區別

轉載地址:http://www.cnblogs.com/wb-DarkHorse/archive/2013/07/08/3178201.html

一:關於座標

  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的值一樣。不多說了

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章