VC++ 坐标问题总结,控件大小随窗口变化

【出处:blog.csdn.net/lanmanck】

一般变控件位置和大小在OnSize()消息中处理,不外乎几个函数:

GetClientRect(),GetClientRect(),ScreenToClient(),MoveWindow()。今天说下这几个函数用法。

假设有一个窗体,Dialog1,上面有一个Edit和一个Button,我们希望窗口大小改变时,Edit大小跟着变,最好铺满整个窗口,除了Button;而Button大小不变,但是位置要变。


GetWindowRect() 得到的是在屏幕坐标系下的RECT(对于父窗体来说,以屏幕左上角为原点的矩形[x,y,W,H];对于窗体的控件来说也是以屏幕左上角为原点的矩形[x,y,W,H]);


GetClientRect() 得到的是在客户区坐标系下的RECT(即以所在窗口左上角为原点,去掉了标题栏计算,仅仅是个大小,返回值的左上角永远为0,0。对于父窗体来说,是自己的大小[0,0,W,H];对于窗体内的控件来说,也是自己的大小[0,0,W,H]);


ScreenToClient() 就是把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标。 如果需要获得窗体在屏幕上的位置,使用GetWindowRect ;如果需要获得窗体的大小,使用GetClientRect;


对窗体来讲:先调用GetWindowRect后再调用ScreenToClient这个时候得到的rect和直接使用GetClientRect得到的值是相等的,表示的是窗体大小,坐标是自己。

例如:

GetWindowRect=[t=118,b=511,l=326,r=1000],ScreenToClient=[t=0,b=393,l=0,r=674],

而GetClientRect=[t=0,b=393,l=0,r=674]。

由此可见,实际的控件大小为393x674,前后结果一样,坐标一样。


对控件来讲:先调用GetWindowRect后再调用ScreenToClient这个时候得到的rect和直接使用GetClientRect得到的值是不相等的,前面表示的是相对于父窗体的坐标,而后面表示的是自己的大小,坐标是自己,

例如:

GetWindowRect=[t=320,b=323,l=328,r=999],ScreenToClient=[t=202,b=205,l=2,r=673],

而GetClientRect=[t=0,b=3,l=0,r=671]。

由此可见,实际的控件大小为3x671,前后的结果都可以算出,但是各自坐标不一样。


有时候需要获得窗口矩形的大小和客户区矩形的大小二者的值,故需要分别调用GetWindowRect和GetClientRect。如果只需要获得客户区矩形的大小,调用GetClientRect就行了。


MoveWindow()就是把控件移到某个区域,包括放大、缩小和位置,坐标是对于Client来说的,也就是父窗口。对大窗口来说,它的“父窗口”是大屏幕,对于小控件来说,它的“父窗口”是大窗口。

现在的问题就是,如何得到合适的MoveWindow内的RECT大小。


结合上述例子,我归结如下,各位拿回去偷偷Happy吧:

在OnSize里面,

1、先得到父窗体的本身大小:GetCLientRect(rcDlg);后面的控件变化以此坐标为参考

2、得到希望变化大小的控件坐标:GetWindowRect(rcEdit);ScreenToCLient(rcEdit); 然后根据需要变更上下左右,与rcDlg比较,最后Movewindow(); 这里的大小都直接是相对于父窗体来说的大小和偏移了。

3、得到希望移动位置的控件坐标:因为上面有大小变化的控件,而本控件不变大小,所以top要以上面的控件为准:

GetClientRect().保存长和宽,然后根据上面的rect加减,一般得到right和top即可,这样加减保存的长宽,就可以move到一个新位置了。


参考代码:

CRect rcDlg;
	GetClientRect(rcDlg);

	CRect rcEdit;
	m_Edit1.GetWindowRect(rcEdit);
	ScreenToClient(rcEdit);
	rcEdit.top = 10;
	rcEdit.bottom = rcDlg.bottom-30;
	rcEdit.left = rcDlg.left;
	rcEdit.right = rcDlg.right;
	m_Edit1.MoveWindow(rcEdit);

	CRect rcBtn;
	m_BtnOK.GetWindowRect(rcBtn);
	ScreenToClient(rcBtn); /* 我们只是记录大小,或者这2句改为m_BtnOK.GetClientRect(rcBtn);是一样的效果 */
	int nWidth = rcBtn.right-rcBtn.left;
	int nHeight = rcBtn.bottom - rcBtn.top;

	rcBtn.top = rcEdit.bottom+2;
	rcBtn.bottom = rcBtn.top+nHeight;
	rcBtn.right = rcDlg.right - 10;
	rcBtn.left = rcBtn.right-nWidth;
	m_BtnOK.MoveWindow(rcBtn);



原文地址:https://www.cnblogs.com/pangblog/p/3265441.html