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

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

四:小结

算是把这个小问题给弄清楚了,适合和我一样的新手学习。网上太多资料,很多都是错的,还是自己动手,丰衣足食~!有错误,请指正!

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

GetWindowRect和GetClientRect的注意事项的更多相关文章

  1. GetWindowRect和GetClientRect的区别详解

    一:关于坐标 MFC中绘图时经常涉及到坐标计算,GetWindowRect和GetClientRect这两个函数,是获取逻辑坐标系中窗口或控件(其实也是窗口)大小和坐标的常用函数了,有什么不一样的? ...

  2. GetWindowRect和GetClientRect比较学习

    一:关于坐标 MFC中绘图时经常涉及到坐标计算,GetWindowRect和GetClientRect这两个函数,是获取逻辑坐标系中窗口或控件(其实也是窗口)大小和坐标的常用函数了,有什么不一样的? ...

  3. GetWindowRect与GetClientRect 的区别

    GetWindowRect 函数功能:该函数返回指定窗口的边框矩形的尺寸.该尺寸以相对于屏幕坐标左上角的屏幕坐标给出. 函数原型:BOOL GetWindowRect(HWND hWnd,LPRECT ...

  4. GetWindowRect和GetClientRect的异同

    由于项目需要,需要学习CGridCtrl控件的使用,测试控件时发现了一个问题,我无法将控件放在对话框的制定位置. 该问题的原因很容易发现,其实就是GetWindowRec()函数和GetClientR ...

  5. GetWindowRect、GetClientRect、ScreenToClient与ClientToScreen

    GetWindowRect是取得窗口在屏幕坐标系下的RECT坐标(包括客户区和非客户区),这样可以得到窗口的大小和相对屏幕左上角(0,0)的位置. GetClientRect取得窗口客户区(不包括非客 ...

  6. VC:GetWindowRect、GetClientRect、ScreenToClient与ClientToScreen

    GetWindowRect是取得窗口在屏幕坐标系下的RECT坐标(包括客户区和非客户区),这样可以得到窗口的大小和相对屏幕左上角(0,0)的位置. GetClientRect取得窗口客户区(不包括非客 ...

  7. MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)

    1.SystemParametersInfo函数可以获取和设置数量众多的windows系统参数 MFC中可以用 SystemParametersInfo(……) 函数来获取和设置系统信息,如下面例子所 ...

  8. vc++ mfc中拖动效果的实现 借助于CImageList

    拖动是界面编程频繁使用的一个效果,在windows系统下可谓大行其道.纵观时下的应用软件几乎各个都支持各种各样拖动的效果,windows7更是把拖动做到了极致.其实说起来拖动的实现也很简单,对于有句柄 ...

  9. VC++的菜单控制和自绘菜单

    菜单控制为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态 需要将CFrameWnd:: m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值), ...

随机推荐

  1. todo: 改变字体的动画

    todo: 截取指定区域的图片, 改变字体的动画

  2. 数据库使用:sql server/mysql/sqlite

    本科学过sql server数据库,上研刚开始在做研究时自己想点子自己做,为了简便使用了论文中看到的一个简易数据库sqlite存储使用数据.后来随着数据量的增长,以及数据处理的需求sqlite速度明显 ...

  3. C#生成exe、dll版本号自动增加

    修改AssemblyInfo.cs 1.注释[assembly: AssemblyFileVersion("1.0.0.0")] 2.[assembly: AssemblyVers ...

  4. loadrunner压测工具

    https://www.cnblogs.com/xxyBlogs/p/4579509.html https://www.cnblogs.com/jaazz/p/8668214.html

  5. jquery-ui 之dialog

    1,引入css和js <script type="text/javascript" src="${ctx}/js/ytd/platform/zdjsDlbyqbh/ ...

  6. vue/cli 3.0 font-size随屏幕大小变化而变化 rem设置

    在安装cube-ui框架时 安装成功后在[E:\WWW\xxx\node_modules\vue-cli-plugin-cube-ui\generator\rem\index.js]修改remUnit ...

  7. jQuery-velocity.js 插件的简易使用

    初识Velocity动画,感觉它并没有那么强大,但是渐渐感觉它的ui动画可以让我们简易的使用到我们的项目中. Velocity动画的简介: 下载地址:http://www.julian.com/res ...

  8. 分组加密的四种模式(ECB、CBC、CFB、OFB)

    加密一般分为对称加密(Symmetric Key Encryption)和非对称加密(Asymmetric Key Encryption).对称加密又分为分组加密和序列密码.分组密码,也叫块加密(bl ...

  9. ntp开机无法自启

    1.1 查询ntp状态 [root@host-172-18-0-37 ~]# service ntpd status Redirecting to /bin/systemctl status ntpd ...

  10. tf实现LSTM时rnn.DropoutWrapper

    转自:https://blog.csdn.net/abclhq2005/article/details/78683656 作者:abclhq2005 1.概念介绍 所谓dropout,就是指网络中每个 ...