临港税收优惠政策新城注册公司

GetWindowRect和GetClientRect的异同 - canger - 博客园
随笔 - 37, 文章 - 0, 评论 - 8, 引用 - 0
  由于项目需要,需要学习CGridCtrl控件的使用,测试控件时发现了一个问题,我无法将控件放在对话框的制定位置。
  该问题的原因很容易发现,其实就是GetWindowRec()函数和GetClientRect()函数在不同情况下返回的Rect含义不同,以及CWnd::Create()函数的特性造成的。
  在Dialog上创建一个CGridCtrl控件,控件的位置由一个PictureBox控件(拖动到对话框模板上的控件)决定,即在PictureBox控件的位置上创建一个与其大小相同的CGridCtrl,下图中虚线内即为PictureBox。
GetClientRect()
  获取窗口客户区的大小,返回的CRect的左上角坐标永远为(0,0)
GetWindowRect()
  首先说一说GetWindowRect()在帮助文档中的介绍是:The dimensions are given in screen coordinates relative to the upper-left corner of the display screen. The dimensions of the caption, border, and scroll bars, if present, are included。就是GetWindowRect()返回的是相对屏幕左上角的的坐标,包括标题栏、边框和滚动条。
& & &在实际测试中我发现,如果调用该函数的CWnd没有父窗口,即CWnd::GetParent()返回null,那么GetWindowRect()返回的CRect的左上角坐标永远为(0,0),如图所示,其中this代表一个基于对话框工程的主对话框。
  如果调用该函数的CWnd有父窗口,即CWnd::GetParent()不返回null,那么GetWindowRect()返回的CRect的坐标为相对父窗口(包括标题栏、边框等)左上角的坐标,如下图所示,其中IDC_GRid是一个对话框控件的资源ID。  
CWnd::Create()函数的特性
  CWnd::Create()函数在不同的派生类中有不同的实现,其中一种形式为:
1 BOOL CWnd::Create(const RECT& rect, CWnd* pParentWnd, UINT nID, DWORD dwStyle)
& &即指定父窗口和在父窗口中的位置,加入要在一个对话框中创建一个Grid控件,采用如下代码:
CRect rectGridW
GetDlgItem(IDC_GRID)-&GetWindowRect(&rectGridWnd);
//获取Grid控件的位置,相对于整个Dlg
m_pGrid = new CGridCtrl(5,5);
m_pGrid-&Create(rectGridWnd,this,IDC_GRID);
  那么呈现的效果如下:
  即CGridCtrl与PictureBox有了错位,原因在于CWnd::Create()中的CRect是以父窗口客户区的左上角为原点坐标,而GetWindowRect()是以父窗口(包括非客户区)的左上角为原点,所以造成了错位。
&要想正确显示,需要采用以下的代码,即根据对话框的边框和标题的尺寸对rectGridWnd进行平移:
// TODO: 在此添加额外的初始化代码
int captionHeight = ::GetSystemMetrics(SM_CYCAPTION);
int cxframe = GetSystemMetrics(SM_CXFRAME);
int cyframe = GetSystemMetrics(SM_CYFRAME);
CRect rectGridW
GetDlgItem(IDC_GRID)-&GetWindowRect(&rectGridWnd);
rectGridWnd.OffsetRect(-cxframe,-cyframe-captionHeight);
m_pGrid = new CGridCtrl(5,5);
m_pGrid-&Create(rectGridWnd,this,IDC_GRID);
  最终界面如下图所示:扫二维码下载作业帮
2亿学生的选择
下载作业帮安装包
扫二维码下载作业帮
2亿学生的选择
GetClientRect,GetWindowRect,ClientToScreen,ScreenToClient这四个函数如何理解?GetClientRect,GetWindowRect获得的Crect分别是相对什么来说的?还有其它能获得位置的函数吗?还有ClientToScreen,ScreenToClient两个函数是怎么理解的,请举个例子说明下好吗?我当前的问题是想在Ctabctrl控件的一页上放置一个对话框,如何才能把对话框移到刚好完美覆盖的地方?还有我这个TAB控件的父窗口不是最大化的,是否还有区别的?谢谢这位大哥的完整回答,辛苦了呵呵.可是我还是有些不明白,就如“它的大小就是整个窗口的大小.”这句话里的窗口是指TAB控件(TAB也是窗口)还是指他的父窗口?大哥能否留下E_MAIL以后多向你请教!
槿夏忻0235
扫二维码下载作业帮
2亿学生的选择
GetClientRect的CRect是相对它的窗口的客户区的原点而言的,即它的左上角坐标总是(0,0),大小总是客户区的长宽.GetWindowRect得到的CRect则是相对于屏幕坐标而言的,它的左上角坐标就是窗口在屏幕上的左上角坐标,它的大小就是整个窗口的大小.ClientToScreen,可以把一个CPoint对象或CRect对象的坐标从客户区坐标系(以客户区左上角为原点)变换为屏幕坐标系(以屏幕左上角为原点).如:// 把对话框的大小变成客户区的大小 void CAboutDlg::OnButton1() { CRect myR GetClientRect(&myRect);//取得客户区的大小 ClientToScreen(myRect);//转换为屏幕坐标 MoveWindow(myRect.left,myRect.top,myRect.Width(),myRect.Height());//MoveWindow使用的是屏幕坐标 } ScreenToClient,则可以把一个CPoint对象或CRect对象的坐标从屏幕坐标系变换为客户区坐标系.例如:CPoint pos( ::GetMessagePos() ); //::GetMessagePos() 得到发生事件时鼠标的屏幕坐标 ScreenToClient(&pos);//把它转换为客户区坐标以便随后在绘图时使用 ...使用以下代码,可以把对话框移到刚好覆盖的地方:CRect rcT // 整个Tab CRect rcI // Tab上方的按钮 // 取得并计算要移动的矩形框 m_tab1.GetWindowRect(&rcTab); // 屏幕坐标 ScreenToClient(rcTab); // 化成父窗口的客户区坐标 m_tab1.GetItemRect(0,&rcItem); // 取得Tab上方按钮的大小 rcTab.DeflateRect(0,rcItem.bottom+1,0,0); // 缩小Tab的矩形 // 把对话框移动到这个矩形框上 m_Page1->MoveWindow(rcTab); // 相对于父窗口的客户区移动补充:关于这些函数的最权威、最详细的描述,请参看MSDN.GetClientRect(),GetWindowRect()这两个函数都是CWnd类的成员函数,或称为方法(Method).所以调用它们得到的矩形都是属于调用它们的那个CWnd对象的窗口的,如m_tab1.GetWindowRect(&rcTab); 得到的矩形rcTab就是Tab控件的窗口大小和位置(屏幕坐标系)."它的大小就是整个窗口的大小"这句话中说的窗口就是发出GetWindowRect()调用的这个CWnd窗口.
为您推荐:
其他类似问题
扫描下载二维码3956人阅读
在VC++中,关于窗口位置的调整,移动,拉伸时总少不了获取控件所在的位置坐标区域,
所以&GetWindowRect,GetClientRect和ScreenToClient必不可少:
&& GetWindowRect()&&&& 得到的是在屏幕坐标系下的RECT(即以屏幕左上角为原点)。
&&&GetClientRect()&&&&& 得到的是在客户区坐标系下的RECT(即以所在窗口左上角为原点,去掉了标题栏计算,仅仅是个大小,返回值的左上角永远为0,0)&
&&&&ScreenToClient()&&&&& 就是把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标。
&& ClientToScreen();&&&& 客户区坐标系下的RECT坐标转化屏幕坐标系下的坐标
如果需要获得窗体在屏幕上的位置,使用GetWindowRect
如果需要获得窗体的大小,使用GetClientRect
第一个函数获得的是窗口在屏幕上的位置,得到的结果可能是这样CRect(10,10,240,240); &
& 第二个函数和它不同,它只获得了客户区的大小,因此得到的结果总是这样CRect(0,0,width,height);&&
&是引用,只是传递的地址。不加就是把值复杂到新的地址去了。&&
加&与不加&可就完全不一样了。 &
& 如果不加,那么只是进行值传递,在GetWindowRect函数内部,会为这个rect建立一个拷贝,函数所有的操作是对这个拷贝进行,那样,将无法返回窗口的矩形了。因为你传进去的变量根本就不发生变化。 &
& 而加了&后,就不同了,引用与指针类似,会告诉函数一个变量的地址,然后函数就直接去这个变量进行操作了,而不是建立一个拷贝进行操作。
请问在对话框中有一个Picture控件,怎样得到它在父窗口对话框中的位置坐标及size?
void & CXXXDlg::GetPictureRect(CRect & &rect) &
& & & CWnd & *pWnd & = & GetDlgItem(IDC_PICTURE_ID); &
& & & if(pWnd) & { &
& & & & & & pWnd-&GetWindowRect(rect); &
& & & & & & ScreenToClient(rect); &
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:320586次
积分:4154
积分:4154
排名:第6986名
原创:104篇
转载:85篇
评论:24条
(1)(2)(8)(52)(34)(42)(12)(17)(21)4065人阅读
//目的:获得控件在客户区的坐标,封装类似MFC中类似void& ScreenToClient( LPRECT lpRect )方法
//返回RECT包括左上角的坐标,不只是(0,0)
&& &虽然MFC封装了不少Windows的API类库,但是有时候使用MFC 时总是不如人意!特别别扭,还是钟情在SDK平台下编写。于是问题出现:
在SDK平台下,能获得窗口的大小的常用API函数有:&
BOOL GetWindowRect(HWND hWnd,LPRECT lpRect);&&&&&& //获得窗口相对屏幕的大小
BOOL GetClientRect(HWND hWnd, LPRECT lpRect );&&&&&&&&&&&&&//获得窗口相对客户区的大小
BOOL ScreenToClient(HWND hWnd, LPPOINT lpPoint);&&&&//把屏幕坐标转换为客户区坐标
注意ScreenToClient的参数 lpPoint是指向POINT结构指针,明显不能达到要求。
在MFC中CWin类库中提供void ScreenToClient( LPRECTlpRect )方法,而在SDK下没有,造成很不便。
提供以下算法能很好解决问题:
BOOL GetControlClientRect(HWND hwnd,int iID,RECT &ControlRect)
&RECT WinRect,ClienWinR&
//&WinRect 是主窗口相对屏幕的大小
//&ClienWinRect是主窗口相对客户区的大小
//ControlRect是控件相对客户区的坐标
&GetWindowRect(hwnd,&WinRect);
&GetClientRect(hwnd,&ClienWinRect);
&&GetWindowRect(GetDlgItem(hwnd,iID),&ControlRect);
&int SizeFim=(WinRect.right-WinRect.left-ClienWinRect.right)/2;&&& //获得客户区的边框大小
&ControlRect.left=ControlRect.left-WinRect.left-SizeF &
&ControlRect.right=ControlRect.right-WinRect.left-SizeF
&ControlRect.top=ControlRect.top-(WinRect.bottom-SizeFim-ClienWinRect.bottom);
&ControlRect.bottom=ControlRect.bottom-(WinRect.bottom-SizeFim-ClienWinRect.bottom);
&return TRUE;
//另外一种方法是保证没有错误的。
void NewScreenToClient(HWND hwndPar,HWND hwndChild,RECT &rect)
int ixPos,iyP
GetWindowRect(hwndChild,&rect);
pt.x=rect.
pt.y=rect.
ScreenToClient(hwndPar,&pt);
rect.left=pt.x;
rect.top=pt.y;
pt.x=rect.
pt.y=rect.
ScreenToClient(hwndPar,&pt);
rect.right=pt.x;
rect.bottom=pt.y;
//可以设置为全局函数。这样在较快地得到子窗口相对父窗口的客户区坐标。
/////////////////////////////////////////////////////////////
我发现很多人转载的都没有经过测试!!!
上面这位兄弟的可以用,非常感谢。
----------------------------------------
再转一些MFC的方法
1. 函数原型(源自MSDN)
&&&&&&virtual BOOL PreTranslateMessage(MSG* pMsg);
&&&&&& 功能:
&&&&&&重载该函数可以实现窗口消息在派发给窗口函数TranslateMessage()和DispatchMessage()之前的过滤.缺省的实现是完成加速键的翻译.因为您必须在你的重载版本中调用CWinApp:PreTranslateMessage()函数.
&&&&&&在MFC中,PreTranslateMessage()是虚函数,我们可以重载它来处理键盘和鼠标消息。
&&&&&&在SDK中,这又有所不同,我们必须在回调函数中
&&&&&& LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)处理消息,它和PreTranslateMessage起的作用是类似的。只是MFC封装的更好而已。
&&&&&& 该函数表示在消息处理(TranslateMessage()和DispatchMessage()等)前所作的操作,如果函数返回值为TRUE,那么消息处理即终止,不会调用TranslateMessage()和DispatchMessage()来翻译和分发消息给相应的窗口;若返回值为FALSE,才会调用翻译和分发消息函数。
&&&&&& 该函数是MFC消息控制流最具特色的地方,它是CWnd类的虚拟函数,通过重载这个函数,我们可以改变MFC的消息控制流程,甚至可以作一个全新的控制流出来。
&&& 在win32程序中,关于消息有两种传递方式:
&&&&& a. MFC消息,MFC会把所有的消息一条条放到一个AFX_MSG_MAP_ENTRY结构中,形成一个数组,该数组存放了所有的消息和与它们相关的参数。也可以说是放到消息队列里去。
&&&&& b. 采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息。
&&& 这两种方式中只有第一种(穿过消息队列的消息)才受PreTranslateMessage()影响,第二种消息并不会理睬PreTranslateMessage()的存在。
&&&&&& PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用,当你需要在MFC之前处理某些消息时,常常要在这里添加代码.
&&&&&& MFC消息控制流最具特色的地方是CWnd类的虚拟函数PreTranslateMessage(),通过重载这个函数,我们可以改变MFC的消息控制流程,甚至可以作一个全新的控制流出来。只有穿过消息队列的消息才受PreTranslateMessage()影响,采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息根本不会理睬PreTranslateMessage()的存在。
&&&&&& 一、是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。
&&&&&& 二、传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。例如可以在该函数中使用(pMsg-&wParam == VK_RETURN)来拦截回车键。
&&&&&& 三、在WindowProc里不能处理WM_CHAR消息。(WindowProc函数见MFC消息响应机制一文)
&&&&&& 四、SetWindowText会发送WM_CHAR给窗口。
&&&&&& 五、PeekMessage和GetMessage的区别:
&&&&&&GetMessage在没有消息的时候等待消息,效率低。PeekMessage没有消息的时候立刻返回,所以CPU占用率高。因为游戏不能靠Windows消息驱动,所以要用PeekMessage();
&&&&&& 在一个WIN32程序中,WINDOWS会将消息传递给相应的窗口。但是消息不是立即就被传递给相应的窗口,而是会从整个程序最顶层的窗口传递到下一级窗口,再传递到下一级窗口,直到传递给目标窗口。在整个过程中,有些消息,在某些特定的情况下,无法默认传递到目标窗口的。比如用户在EDIT控件中按下回车键,CANCEL键等,如果EDIT窗口之前有对话框窗口,对话框会默认处理回车消息(即响应ONOK函数,然后关闭对话框),然后退出消息传递。所以
EDIT会收不到。要解决这个问题,可以在EDIT窗口之前所有的对话框中重载PreTranslateMessage函数,然后在函数内加上:&&&如此,就可避开对话框默认处理,将消息传递下去。注意:只有对话框才会默认处理按下回车,CANCEL消息,其他控件窗口则不会,所以在其他窗口中不必重载PreTranslateMessage函数,当然如果重载了也不会错。
if (pMsg-&message==
WM_KEYDOWN&& pMsg-&wParam== VK_RETURN)&&&&//如果消息类型为WM_KEYDOWN并且用户按下的是回车
&&&&&&&&&return FALSE;&&&
//不翻译消息,直接将消息传递下去。具体可查MSDN。注意,这里返回值不能为TRUE,TRUE的意思是翻译消息后退出消息传递,如此一来虽然也能避开对话框默认处理,但是会退出消息传递,这样EDIT控件照样得不到消息。(我一开始所犯的错误)
附:关于PreTranslateMessage()函数的小程序示例:
BOOL CUserDlg::PreTranslateMessage(MSG* pMsg)
&&&&if(pMsg-&message==
WM_KEYDOWN)//判断是否有按键按下
&&&&&&&switch(pMsg-&wParam)
&&&&&&&&&&case VK_DOWN:&&&&&//表示是方向键中的向下的键
&&&&&&&&&&&&&&// code here
&&&&&&&&&&&&&&&break;
&&&&&&&&&&case VK_UP:&&&&&&//表示是方向键中的向上的键
&&&&&&&&&&&&&&&// code here
&&&&&&&&&&&&&&&break;
&&&&&&&&&&default:
&&&&&&&&&&&&&&&break;
BOOL AcameraCT::PreTranslateMessage(MSG* pMsg)
&&int buID;
&buID= GetWindowLong(pMsg-&hwnd,GWL_ID);//由窗口句柄获得ID号,GetWindowLong为获得窗口的ID号。
&&if(pMsg-&message==WM_LBUTTONDOWN)&
&&if(buID==IDC_BUTTON_CT1) //按下
&&&//在这里添加单击按下事件的程序
&if(pMsg-&message==WM_LBUTTONUP)&
&&if(buID==IDC_BUTTON_CT1)
&&&//在这里添加单击松开事件的程序
&return CDialog::PreTranslateMessage(pMsg);
BOOL AcameraCT::PreTranslateMessage(MSG* pMsg)
&&int buID;
&CWnd* pWnd=WindowFromPoint(pMsg-&pt); //获得指定点句柄
&buID=pWnd-&GetDlgCtrlID();//获得该句柄的ID号。
&&if(pMsg-&message==WM_LBUTTONDOWN)&
&&if(buID==IDC_BUTTON_CT1) //按下
&&&//在这里添加单击按下事件的程序
&if(pMsg-&message==WM_LBUTTONUP)&
&&if(buID==IDC_BUTTON_CT1)
&&&//在这里添加单击松开事件的程序
&return CDialog::PreTranslateMessage(pMsg);
在MFC中判断单击的是某个按钮时可以和SDK一样在WM_COMMAND获取LPARAM获得,也可以通过判断WM_LBUTTONDOWN和WM_LBUTTONUP后的坐标参数是否在按钮区域。
在MFC中使用CRect较RECT简单点
GetDlgItem(IDC_CB)-&GetWindowRect(rt);&& //取得在屏幕中的位置
ScreenToClient(rt);&&&&&&&&& //转换到在对话框中的位置
rt.left和rt.top为该控件在对话框中的位置;
GetDlgItem(IDC_CB)-&SetWindowPos(NULL,rt.left,rt.top,0,0,SWP_NOSIZE);//设置该位置(其实还是在原位置,因为rt.left和rt.top本来就是控件在对话框中的位置,如果要调整控件的位置,修改第二和第三个参数即可);
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:97993次
积分:1011
积分:1011
排名:千里之外
转载:91篇
(1)(1)(1)(3)(4)(2)(4)(1)(2)(3)(3)(1)(1)(2)(9)(3)(1)(8)(1)(10)(12)(13)(2)(3)}

我要回帖

更多关于 临港新城注册公司条件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信