[置顶] GetWindowRect和GetClientRect的区别详解

1 理论学习:

 
MFC中,在给对话框贴图时遇到对话框的大小问题。

  于是深入研究GetWindowRect和GetClientRect这两个函数,上网搜索加上自己的实验终于解决了问题。

GetWindowRect和GetClientRect这两个函数,是获取逻辑坐标系中窗口或控件(其实也是窗口)大小和坐标的常用函数。

  逻辑坐标,它相对的一个概念是设备坐标。是为了屏蔽掉不同设备属性差别而设置的抽象坐标系,就是独立于设备坐标的统一接口,程序员不需要去在具体的设备上进行绘图操作,而只需要在虚拟的环境下进行绘图,就是CDC。然后由设备驱动去负责虚拟坐标到实际设备坐标之间的转换。通常逻辑坐标与设备坐标之间有不同的映射转换关系,缺省模式下的映射方式是MM_TEXT,这种方式下的逻辑坐标的方向和单位与设备坐标的相同,也是以像素为单位来表示,X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。

然后再说上面的两个函数之间的差别:


GetWindowRect得到的是相对于屏幕左上角的坐标,但也不是绝对,分以下两种情况:
1 窗口还没有初始化完成时:原点是整个窗口的左上角
2 初始化完成后,原点是设备屏幕左上角
GetClientRect取得窗口客户区(不包括非客户区)在客户区坐标系下的坐标,可以得到窗口的大小,而不能得到相对屏幕的位置,因为这个矩阵是在客户区坐标系下(相对于窗口客户区的左上角)的。

2 代码试验:

以下都是在对话框初始化后进行的。

以加法计算器MFC程序为例,在“计算”按钮的响应函数中添加代码

    CRect  rtWnd,rtTitle,rtWnd2;
    GetWindowRect(&rtWnd); //相对于屏幕的坐标
    GetClientRect(&rtWnd2);//相对于客户区的坐标 
    //取得标题栏的位置
    //SM_CXSIZEFRAME is the width of the horizontal border,应该指的是左右边框的宽度
    //SM_CYSIZEFRAME is the height of the vertical border,应该指的是上下边框的高度
    //SM_CXSIZE  窗口标题栏宽度
    //SM_CYSIZE  窗口标题栏高度
    rtTitle.left = GetSystemMetrics(SM_CXFRAME);//SM_CYFULLSCREEN
    rtTitle.top = GetSystemMetrics(SM_CYSIZEFRAME);//SM_CYFRAME
    rtTitle.right = rtWnd.right - rtWnd.left - GetSystemMetrics(SM_CXFRAME);
    rtTitle.bottom = rtTitle.top + GetSystemMetrics(SM_CYSIZE);
    //GetDlgItem(IDD_ADDITION_DIALOG)->GetWindowRect(&rect);
    //ScreenToClient(rect);
    CString a;
    a.Format(_T("top=%d,bottom=%d,left=%d,right=%d"),rtWnd.TopLeft().y,rtWnd.BottomRight().y,rtWnd.TopLeft().x,rtWnd.BottomRight().x);
    AfxMessageBox(a);
    CString b;
    b.Format(_T("边框:top=%d,bottom=%d,left=%d,right=%d"),rtTitle.top,rtTitle.bottom,rtTitle.left,rtTitle.right);
    AfxMessageBox(b); 
    CString c;
    c.Format(_T("客户区:top=%d,bottom=%d,left=%d,right=%d"),rtWnd2.top,rtWnd2.bottom,rtWnd2.left,rtWnd2.right);
    AfxMessageBox(c);

GetClientRect(&rtWnd2);//相对于客户区的坐标 。得到的是客户区的大小。
下面在对话框中添加静态文本框,寻找文本框的顶点坐标。

    CRect ctrlRect1;
    CRect ctrlRect2;
    CStatic *pCtrl = (CStatic*)GetDlgItem(IDC_STC_TEST);
    pCtrl->GetClientRect(&ctrlRect1); 
    //输出top=0,bottom=142,left=47,right=228
    pCtrl->ClientToScreen(&ctrlRect1);
    //输出top=129,bottom=271,left=471,right=699
    CString d;
    d.Format(_T("top=%d,bottom=%d,left=%d,right=%d"),ctrlRect1.TopLeft().y,ctrlRect1.BottomRight().y,ctrlRect1.TopLeft().x,ctrlRect1.BottomRight().x);
    AfxMessageBox(d);

    pCtrl->GetWindowRect(&ctrlRect2);
    //输出top=129,bottom=271,left=471,right=699
    pCtrl->ScreenToClient(&ctrlRect2); 
    //输出top=0,bottom=142,left=47,right=228
    CString e;
    e.Format(_T("top=%d,bottom=%d,left=%d,right=%d"),ctrlRect2.TopLeft().y,ctrlRect2.BottomRight().y,ctrlRect2.TopLeft().x,ctrlRect2.BottomRight().x);
    AfxMessageBox(e);

GetClientRect得到是控件的大小.
GetWindowRect得到的是控件相对于屏幕左上角的坐标。网上很多讲解说的是相对于对话框左上角的坐标,这点应该质疑。

3 学习总结


对话框初始化后。
对于对话框来说:
GetWindowRect()是以屏幕左上角为坐标原点得到的坐标。
GetClientRect()是以相对于自身的客户区范围左上角为坐标原点得出的坐标。得到客户区的矩形,也就是说不包括标题栏,外框等。
对于控件来说:
GetWindowRect()是以屏幕左上角为坐标原点得到的坐标。
GetClientRect()是以控件左上角为坐标原点得出的坐标。,即控件本身大小。

对话框初始化前,即在OnInitDialog()中添加代码。
GetWindowRect()坐标原点是整个窗口的左上角 。
GetClientRect()与对话框初始化后相同。

欢迎前来交流!

有关对话框更多内容推荐:
http://blog.csdn.net/xshown/article/details/6712140
http://www.cnblogs.com/wb-DarkHorse/archive/2013/07/08/3178201.html

你可能感兴趣的:(对话框,mfc窗口大小)