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的值一样。不多说了
为什么对话框和控件的转换之间略有差别(两次转换结果不太一样),主要是对话框包含了非客户区,使得相对坐标不一致
GetWindowRect和GetClientRect比较学习的更多相关文章
- GetWindowRect和GetClientRect的区别详解
一:关于坐标 MFC中绘图时经常涉及到坐标计算,GetWindowRect和GetClientRect这两个函数,是获取逻辑坐标系中窗口或控件(其实也是窗口)大小和坐标的常用函数了,有什么不一样的? ...
- GetWindowRect和GetClientRect的注意事项
发现GetClientRect()函数取值不正确,特此找来了些资料以供参考,具体如下,就可以明白怎么回事了. 一:关于坐标 MFC中绘图时经常涉及到坐标计算,GetWindowRect和GetClie ...
- GetWindowRect与GetClientRect 的区别
GetWindowRect 函数功能:该函数返回指定窗口的边框矩形的尺寸.该尺寸以相对于屏幕坐标左上角的屏幕坐标给出. 函数原型:BOOL GetWindowRect(HWND hWnd,LPRECT ...
- GetWindowRect和GetClientRect的异同
由于项目需要,需要学习CGridCtrl控件的使用,测试控件时发现了一个问题,我无法将控件放在对话框的制定位置. 该问题的原因很容易发现,其实就是GetWindowRec()函数和GetClientR ...
- GetWindowRect、GetClientRect、ScreenToClient与ClientToScreen
GetWindowRect是取得窗口在屏幕坐标系下的RECT坐标(包括客户区和非客户区),这样可以得到窗口的大小和相对屏幕左上角(0,0)的位置. GetClientRect取得窗口客户区(不包括非客 ...
- VC:GetWindowRect、GetClientRect、ScreenToClient与ClientToScreen
GetWindowRect是取得窗口在屏幕坐标系下的RECT坐标(包括客户区和非客户区),这样可以得到窗口的大小和相对屏幕左上角(0,0)的位置. GetClientRect取得窗口客户区(不包括非客 ...
- MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)
1.SystemParametersInfo函数可以获取和设置数量众多的windows系统参数 MFC中可以用 SystemParametersInfo(……) 函数来获取和设置系统信息,如下面例子所 ...
- vc++ mfc中拖动效果的实现 借助于CImageList
拖动是界面编程频繁使用的一个效果,在windows系统下可谓大行其道.纵观时下的应用软件几乎各个都支持各种各样拖动的效果,windows7更是把拖动做到了极致.其实说起来拖动的实现也很简单,对于有句柄 ...
- VC++的菜单控制和自绘菜单
菜单控制为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态 需要将CFrameWnd:: m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值), ...
随机推荐
- sublime livereload插件
1.首先在chrome商店下载livereload 安装之后记得在 chrome 的 扩展程序 里面 勾上 允许访问文件地址 2.sublime text 3 中下载插件 Livereload 3.配 ...
- Atitit.获取approot api 应用根路径 java c#.net php asp
Atitit.获取approot api 应用根路径 java c#.net php asp 1. 如果根路径返回empty,否则返回/app,兼容getContextPath() <scrip ...
- Python之内置类型
python有6大内置类型 数字.序列.映射.类.实例.异常. 下面就慢慢来说明: 1.数字 有3个明确的数字类型,整型,浮点型及复数.另外,布尔是整型的一个子类型. (另外标准库还包含额外的数字类型 ...
- maven+eclipse+mac+tomcat 多模块发布
之前项目中有用到过maven,但是没运行过web的maven,所以这里记录一下. 项目的结构: ---master //parent ---web-project // ---client-proj ...
- 使用eclipse开发hbase程序
一:在eclipse创建一个普通的java项目 二:新建一个文件夹,把hbase需要的jar放进去,我这里把hbase/lib/*.jar 下所有的jar都放进去了,最后发现就用到了下面三个jar ...
- SpringCloud如何配置Eureka授权
现在已经成功的实现了一个Eureeka的服务启动以及微服务的注册配置操作,但是现在的程序有一个问题,你自己公司的Eureka服务应该可以注册的服务只能够是满足于认证要求的微服务,所有这样来在之前所进行 ...
- 在Eclipse中使用JUnit4进行单元测试(初级篇、中级篇、高级篇)
本文转载自以下 初级篇: http://blog.csdn.net/andycpp/article/details/1327147 中级篇: http://blog.csdn.net/andycpp/ ...
- 跟我一起写 Makefile(三)[转]
原文链接 http://bbs.chinaunix.net/thread-408225-1-1.html(出处: http://bbs.chinaunix.net/) make 的运行—————— 一 ...
- Hibernate: 数据持久层框架
Hibernate 是一种Java语言下的对象关系映射解决方案. 它是使用GNU宽通用公共许可证发行的自由.开源的软件.它为面向对象的领域模型到传统的关系型数据库的映射,提供了一个使用方便的框架.Hi ...
- OWASP-A5-安全配置错误
1.安全配置错误 安全配置错误可以发生在一个应用程序堆栈的任何层面,包括平台.Web服务器.应用服务器.数据库.框架和自定义代码. 开发人员和系统管理员需共同努力,以确保整个堆栈的正确配置.自动扫描器 ...