各位高手,小弟请教关于GetWindowRect,GetClientRect以及ClientToScreen,ScreenToClient的使用!先谢谢啦
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了各位高手,小弟请教关于GetWindowRect,GetClientRect以及ClientToScreen,ScreenToClient的使用!先谢谢啦相关的知识,希望对你有一定的参考价值。
网上看了很多关于这方面的回答,但还是有点模糊,我现在理解的程度:
GetWindowRect,以屏幕左上角为(0,0),获取的时整个窗口(包括菜单栏等)的大小与位置。
GetClientRect,以窗口客户区左上角为(0,0),获取的只是窗口客户区大小,而位置无法获取。因为它左上角永远为(0,0)。
他们之间通过ClientToScreen,ScreenToClient进行转化。MSDN上说它们使用的都是设备坐标空间。
以下我特意通过实验进行验证:
新建一个基于对话框的应用程序;设两个成员变量m_rectWindow,m_rectClient分别用来获取窗口坐标矩形与客户区坐标矩形;在初始化窗口函数中添加代码:
GetWindowRect(m_rectWindow);
ScreenToClient(m_rectWindow);
GetClientRect(m_rectClient);
ClientToScreen(m_rectClient);
并在每条语句上设置断点进行观察,执行完各语句后,结果为
1,m_rectWindow :top=0 bottom=408 left=0 right=593 ,
2、m_rectWindow :top=-30 bottom=378 left=-4 right=589
3、m_rectClient top=0 bottom=374 left=0 right=585
4、m_rectClient top=30 bottom=404 left=4 right=589
我给出解释:
1,所获取的是整个对话框窗口(包括菜单栏等)的矩形尺寸,其原点即为窗口的左上角,宽度为593,高度为408;
2,转换后,以客户区左上角为原点,实际上由于边框上下左右各占4个像素(由上面推知),加上标题栏占26个像素(也由上推知),所以客户区比整个窗口宽窄8个像素,高窄34个像素,这就导致此时原点窗口原点为(-4,-30),其相对客户区左上角而言,宽度高度不变;
3,以客户区左上角为(0,0),宽度为589,高度为374;
4,此时以窗口左上角为原点,则客户区原点坐标为(4,30),宽度高度不变。
我现在想问的是,为什么第一条语句的左上角坐标也为(0,0)不是说GetWindowRect以屏幕左上角为原点吗?那它左上角肯定不应该是(0,0)啊???
还有,以上我对它们的理解或解释对不对?或者也可以把你们的理解告诉我,最好有程序验证结果,非常感谢啊,答的好再多送点分,我只能这样回报你们啦!!!
按2楼说法,我重新测试
void CTestDlg::OnButton1()
CWnd* pCtrlWnd;
pCtrlWnd=GetDlgItem(IDC_BUTTON);
CRect rect;
pCtrlWnd->GetWindowRect(&rect);
ScreenToClient(&rect);
CRect rect1;
pCtrlWnd->GetClientRect(&rect1);
ClientToScreen(&rect1);
1,rect top=403 bottom=424 left=591 right=666
2, top=155 bottom=176 left=191 right=266
3,rect1 top=0 bottom=21 left=0 right=75
4, top=248 bottom=269 left=400 right=475
我的解释:
1,按钮左上角相对于屏幕左上角为(591,403)
2,转换后,按钮左上角位置相对客户区左上角为(191,155)
3,获取的只能是按钮的大小,坐标值不能获取
4,由于客户区左上角距离屏幕(400,248),所以尽管转换,但仍不能获取按钮位置
结论:1,不能通过GetClientRect获取控件位置,,即使转换后仍不能,但能获取客户区离屏幕左上角的距离
2,要获取控件的坐标位置只能用GetWindowRect,转换后还是一样。只是它相对的分别是屏幕与客户区左上角
另网上说GetWindowRect,再ScreenToClient就相当于GetClientRect这样理解有问题吧?还有为什么在OnInitDialog会先将窗口放在屏幕左上角呢?
我觉得你对于这几个函数的理解已经很正确了。
msdn的解释很清晰很正确,没有任何疑义,和你的理解是一致的。
呵呵,我觉得只要解释一下第一个执行为啥左上角是(0,0),你的所有疑问就没有了。
我想请问一下,你是不是在对话框初始化的时候,也就是OnInitialDlg里面执行的以上代码?我相信答案肯定是“是的”。
在对话框初始化的时候,窗口是先有可能放置在屏幕左上角,然后在这个初始化函数结束后,窗口被移动到屏幕正中。
也就是说,你在对话框初始化过程中获取窗口位置的时候,窗口确实就在左上角!
如果你想验证一下我的结论,不妨在程序中设置一个按钮,在这个按钮的消息响应中,再次执行这几句代码,然后你观察一下结果,是不是就完全符合你的预期了^_^
欢迎采纳!追问
太感谢你的回答了,我重新测试了下,但这里不能输入太多字,所以我放在问题补充里面,希望你能继续关注啊。。。。
追答楼主,你的理解从头到尾都是非常正确的。
稍微有点问题就是理解错我的一点意思了,我是说你在按钮响应里面执行你上面那段代码,不是对按钮进行一下同样的操作。主要原因是,但你点击按钮的时候,对话框肯定已经完成了全部的初始化。这才是我让你在按钮消息响应中处理的原因。
对于对话框的理解,你完全正确,不过对于按钮的理解,你的第4点不正确:ClientToScreen是能够获得按钮位置的。你调用pCtrlWnd->ClientToScreen(&rect1)就可以了。直接调用ClientToScreen,相当于将当前窗口(即主窗口)的客户区域转为绝对区域,加上pCtrlWnd就可以将按钮的客户区域转为绝对区域了。甚至你不用调用GetClientRect,直接用CRect(0, 0, 0, 0),都可以达到获取按钮绝对位置的目的。
ClientToScreen之类的函数其实很简单,你其实已经理解很清楚了,唯一欠缺的是,你要知道这些函数的执行对象(就是this、pCtrlWnd之类的)和执行效果有关系。网上的说法没问题,你理解上面这一点就知道为啥了。
至于OnInitDialog为啥将窗口放在左上角呢,你可以这么理解,在OnInitialDlg之前,记录窗口位置的变量还没有初始化。至于这一点,在MFC的不同版本中,其实效果未必相同,VC6中,可能OnInitialDlg中就已经完成位置的初始化了。而我目前用的VS2005和VS2008,它们已经这么做了,而为什么这么做,这个就没有太大意义,纯属MFC开发者的喜好问题,总之没有问题就行。
你如果想深入理解这个过程,不妨重载WM_SIZE和WM_MOVE的消息响应,全部加上断点,观察一下在窗口位置哪个时候发生的变化。
嘿嘿,观察后你可能会比较吃惊,不过那样对于你理解窗口的初始化过程很有益,当然与本问题无关了。
最后补充一点吧,感觉你对GetWindowRect,GetClientRect理解很正确,对ClientToScreen,ScreenToClient的理解有欠缺。欠缺之处在于,你忽略了这两个函数和调用这两个函数的实例是有关系的。
例如:
CRect rc(0, 0, 0, 0);
pDlg->ClientToScreen(rc);
rc = CRect(0, 0, 0, 0);
pButton1->ClientToScreen(rc);
rc = CRect(0, 0, 0, 0);
pButton2->ClientToScreen(rc);
仔细体会一下它们执行效果上的差异吧。
而第二条(-4, -30)是窗口的左上角的坐标(屏幕左上角坐标因为这个取出来是(0,0)刚好跟屏幕左上角坐标一样),相对窗口客户区左上角。
第3条好理解的。
第4条客户区的左上角坐标,相对于屏幕左上角坐标。
GetWindowRect() 得到的是在屏幕坐标系下的RECT;(即以屏幕左上角为原点,得到窗口的大小和相对屏幕左上角(0,0)的位置)关于问题1,你的窗口应该刚好放在屏幕的右上角,所以是(0,0),它取的是整个窗口的矩形。。。
GetClientRect() 得到的是在客户区坐标系下的RECT; (即以所在窗口左上角为原点),
取的仅是客户区的矩形,也就是说不包括标题栏,外框等。。。
ScreenToClient() 就是把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标。
GetWindowRect()获得的是窗口在屏幕上的位置,得到的结果可能是这样CRect(10,10,240,240);
GetClientRect()则不同,它只获得了客户区的大小,因此得到的结果总是这样CRect(0,0,width,height);追问
首先谢谢你的回答!
你回答的我也曾经看到很多,现在唯一的问题应该就是GetWindowRect() ,我所新建的对话框程序,唯一做得改变就是稍微在资源视图里面把它拉大了些,但绝对不可能像你说的放在屏幕右上角,这就是我迷糊的关键。因为实际上我单步运行后,对话框是直接出现在屏幕中间位置的!所以为什么第1个它的左上角也是(0,0)???
既然得到的坐标不是相对于屏幕而言,那么你用ScreentoCllient就没有任何意义了。
你的其他理解都是正确的。
原来我一直想当然的认为GetWindowRect得到的是0,0开始的整个窗口的坐标,看了你的问题才知道我的理解存在问题,但貌似我想当然是正确的……
印象中还有一些msdn的说明是云里雾里,不着边际(可能我英语不太好),所以还是以程序为准吧,以后楼主这类问题照这规则办就成了
请教各位高手 oracle 存储过程 如何获得 捕获异常的内容
rt
参考技术A --通过sqlcode , sqlerrm 这两个内置变量来查看,例如:DECLARE
--声明异常
some_kinds_of_err EXCEPTION; -- Exception to indicate an error condition
v_ErrorCode NUMBER; -- Variable to hold the error message code
v_ErrorText VARCHAR2(200); -- Variable to hold the error message text
BEGIN
--...
--抛出异常
IF ( ... ) THEN --(括号内填抛出异常的条件)
RAISE some_kinds_of_err;
END IF;
--...
EXCEPTION
--捕捉异常
WHEN some_kinds_of_err THEN
/* do something to Handler the errors */
null;
--捕捉其他异常,并获得 捕获异常的内容
WHEN OTHERS THEN
v_ErrorCode := SQLCODE;
v_ErrorText := SUBSTR(SQLERRM, 1, 200);
-- Note the use of SUBSTR here.
dbms_output.put_line(v_ErrorCode || '::'||v_ErrorText);
END;
/
/**
sqlcode 就是错误代码
sqlerrm 就是sql错误信息。注意用substr来截取,否则输出很难看。
**/本回答被提问者采纳 参考技术B begin
plsql语句串;
exception when others
then
dbms_output.put_line(sqlcode||' '|| SQLERRM);
end;
以上是关于各位高手,小弟请教关于GetWindowRect,GetClientRect以及ClientToScreen,ScreenToClient的使用!先谢谢啦的主要内容,如果未能解决你的问题,请参考以下文章
【Winfrom】 小弟请教各位大哥一个问题,我想在一个窗体上绘制像下面图片一样结构的图
请教高手 小弟刚开始学UNIX。想做个能有下列功能的.sh。
关于MATLAB自己编程求解特征值的问题?(比如QR法,幂法,牙可比跌代法,等)请教高手
请教高手关于西门子S7-300的ModbusTCP通讯问题,急!!
请教一些关于JasperReport+iReport的相关问题,各位前辈帮帮忙.
请教Java SE高手一个简单的“@SuppressWarnings("unlikely-arg-type")”注释的含义是啥?