• GetWindowRect和GetClientRect比较学习


    一:关于坐标

      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的值一样。不多说了

    为什么对话框和控件的转换之间略有差别(两次转换结果不太一样),主要是对话框包含了非客户区,使得相对坐标不一致

  • 相关阅读:
    luogu P1144 最短路计数
    luogu P1440 求m区间内的最小值
    cogs 1075. [省常中2011S4] 最短路径问题
    luogu P2485 [SDOI2011]计算器
    luogu P1220 关路灯
    笨小猴 2008年NOIP全国联赛提高组
    [CF580E]Kefa and Watch
    [HDU2138]How many prime numbers
    [NOIp2014提高组]解方程
    [洛谷1390]公约数的和
  • 原文地址:https://www.cnblogs.com/microtiger/p/7843213.html
Copyright © 2020-2023  润新知