6.CControlUI的大小及位置
来源:互联网 发布:新浪短链接数据分析 编辑:程序博客网 时间:2024/05/16 00:53
1.简介
CControlUI中有三个重要的参数,分别为:
- RECT m_rcItem; //控件实际大小及位置 - SIZE m_cxyFixed; //控件预设大小- SIZE m_cXY; //控件预设位置
2.非float控件的讨论
控件的浮动与非浮动由参数 m_bFloat 标识,此处讨论 m_bFloat = false 的情形。
2.1 m_rcItem
//获取控件大小及位置const RECT& CControlUI::GetPos() const{ return m_rcItem;}//设置控件大小及位置:1.由父控件设置void CControlUI::SetPos(RECT rc){ //设置控件大小位置 m_rcItem = rc; //控件大小位置改变消息处理 if( !m_bSetPos ) { m_bSetPos = true; if( OnSize ) OnSize(this); m_bSetPos = false; } //计算需要重新刷新的区域,并进行刷新 m_pManager->Invalidate(invalidateRc);}
2.2 m_cxyFixed
设置 m_cxyFixed.cy 与下面设置 m_cxyFixed.cx 方式相同,不再重复。
int CControlUI::GetFixedWidth() const{ return m_cxyFixed.cx;}//预设置控件大小:1.父控件设置 2.通过“pos”参数时,pos.right-pos.left 3.通过“width”参数void CControlUI::SetFixedWidth(int cx){ //设置大小 m_cxyFixed.cx = cx; //更新父控件布局 NeedParentUpdate();}
重点:当容器在设置子控件布局时,会使用该参数估计子控件大小,从而为子控件分配实际大小及位置: SetPos()。
SIZE CControlUI::EstimateSize(SIZE szAvailable){ return m_cxyFixed;}
2.3 m_cXY
预设置控件的位置。
// 实际大小位置使用GetPos获取,这里得到的是预设的参考值(代码原注释)SIZE CControlUI::GetFixedXY() const{ return m_cXY;}//void CControlUI::SetFixedXY(SIZE szXY){ m_cXY.cx = szXY.cx; m_cXY.cy = szXY.cy; NeedParentUpdate();}
3.float控件的讨论
浮动控件与非浮动控件的主要区别在于,当控件的预设大小改变时,是否重新刷新父控件中子控件的布局。举例如下:
void CControlUI::SetFixedXY(SIZE szXY){ m_cXY.cx = szXY.cx; m_cXY.cy = szXY.cy; if( !m_bFloat ) NeedParentUpdate(); else NeedUpdate();}
另外一个区别在 SetPos() 函数中:
void CControlUI::SetPos(RECT rc){ //设置实际位置及大小 ...... //更新预设控件大小及位置 if( m_bFloat ) { CControlUI* pParent = GetParent(); if( pParent != NULL ) { RECT rcParentPos = pParent->GetPos(); if( m_cXY.cx >= 0 ) m_cXY.cx = m_rcItem.left - rcParentPos.left; else m_cXY.cx = m_rcItem.right - rcParentPos.right; if( m_cXY.cy >= 0 ) m_cXY.cy = m_rcItem.top - rcParentPos.top; else m_cXY.cy = m_rcItem.bottom - rcParentPos.bottom; m_cxyFixed.cx = m_rcItem.right - m_rcItem.left; m_cxyFixed.cy = m_rcItem.bottom - m_rcItem.top; } } //刷新重绘无效区域 ......}
注:其实 SetPos() 不仅会调整自身的位置和大小,如果其包含其他控件,则它会调整子控件的位置和大小。
4.结束
m_rcItem 为控件的实际大小,实际所占用的位置。
m_cxyFixed 为如果控件在某个容器中时,希望父容器能够为其分配的大小,但是仅仅是希望。一般情况下父容器也是很通情达理的。
父容器会调用子控件的 EstimateSize() 函数来询问子控件所希望设置的大小即 m_cxyFixed。
SetPos() 函数同样重要,不仅设置自己的位置,也会调整子控件的位置(前提它是容器且有子控件)。
5.附
(1) NeedUpdate() 函数
在各种调整预设大小的函数中,我们看到各种调用 NeedUpdate() 函数,在此简介一下:
void CControlUI::NeedUpdate(){ if( !IsVisible() ) return; m_bUpdateNeeded = true; Invalidate(); //通过设置m_pManager中的 m_bUpdateNeeded 设置控件大小更新 if( m_pManager != NULL ) m_pManager->NeedUpdate();}
m_bUpdateNeeded 主要用在处理 CPaintManagerUI::MessageHandler() 中的 WM_PAINT 消息时,判断是否需要重设控件位置及大小:
case WM_PAINT:{ //判断是否需要重绘 if( m_bUpdateNeeded ) { m_bUpdateNeeded = false; RECT rcClient = { 0 }; ::GetClientRect(m_hWndPaint, &rcClient); if( !::IsRectEmpty(&rcClient) ) { if( m_pRoot->IsUpdateNeeded() ) //是否需要更新 { m_pRoot->SetPos(rcClient); } else { //循环处理需要更新的控件 CControlUI* pControl = NULL; while( pControl = m_pRoot->FindControl(__FindControlFromUpdate, NULL, UIFIND_VISIBLE | UIFIND_ME_FIRST) ) { pControl->SetPos( pControl->GetPos() ); } } //第一次绘制的话,发送 DUI_MSGTYPE_WINDOWINIT 消息 } } //重绘...... // 如果仍需要调整大小,再调用 InvalidateRect() 更新刷新区域 // 在下一次处理 WM_PAINT 消息时进行重绘 if( m_bUpdateNeeded ) { ::InvalidateRect(m_hWndPaint, NULL, FALSE); }} return true;
当然 NeedParentUpdate() 也一样,效果和 NeedUpdate() 基本相同,只是把父控件也设置成了需要更新。
void CControlUI::NeedParentUpdate(){ if( GetParent() ) { GetParent()->NeedUpdate(); GetParent()->Invalidate(); } else { NeedUpdate(); } if( m_pManager != NULL ) m_pManager->NeedUpdate();}
(2) Invalidate() 函数
在 SetPos() 的最后一句,调用了 m_pManager->Invalidate(invalidateRc); Invalidate() 函数的效果是更新刷新区域,在下一次处理 WM_PAINT 消息时进行重绘。
下面看下控件的 Invalidate() 函数的实现:
void CControlUI::Invalidate(){ if( !IsVisible() ) return; //不可见就没有必要了 RECT invalidateRc = m_rcItem; CControlUI* pParent = this; RECT rcTemp; RECT rcParent; //循环搜索控件的交集,即需要重绘的区域 while( pParent = pParent->GetParent() ) { rcTemp = invalidateRc; rcParent = pParent->GetPos(); if( !::IntersectRect(&invalidateRc, &rcTemp, &rcParent) ) { return; } } //调用 m_pManager 的 Invalidate() 函数实现系统重绘 if( m_pManager != NULL ) m_pManager->Invalidate(invalidateRc);}
看看 m_pManager 的 Invalidate() 函数:
void CPaintManagerUI::Invalidate(RECT& rcItem){ ::InvalidateRect(m_hWndPaint, &rcItem, FALSE);}
::InvalidateRect() 系统函数会将 rcItem 区域添加无效区域中,在下次处理 WM_PAINT 消息时进行重绘。
- 6.CControlUI的大小及位置
- JS_页面大小及元素的位置
- Javascript获取窗口的大小及位置
- 改控件的大小及移动控件的位置
- 设置方格位置及大小
- dialog改变大小及位置
- STM32堆栈大小及位置
- Delphi中运行时改变panel的位置及大小
- C++Builder中保持控件的位置及大小
- HTML中图片位置及大小的控制
- 获取collectionViewcCell及tableViewCell在当前屏幕的位置大小
- Jquery中获取元素的大小及位置信息
- jQuery中的元素位置及大小的获取
- MFC窗口大小及位置设置方式
- Winform 空间位置及大小自适应
- JS控制弹窗大小及位置
- Flex TextArea自适应位置及大小
- Android自定义Dialog 及位置和大小
- PowerDesigner16.5使用总结
- Codeforces Round #367 (Div. 2) A
- 输入三个整数x,y,z,请把这三个数由小到大输出。
- Hadoop/Spark平台搭建
- 7_11_A题 Lights Against Dudely [HDU 4770] (状态压缩+暴力)
- 6.CControlUI的大小及位置
- USB device stack
- poj1236(强连通分量)
- java学习日记_16:面向对象之匿名对象。07.03
- 智能指针(一)
- Python使用paramiko进行SSH和SFTP连接
- 7_11_C题 Zhuge Liang's Password(模拟)
- shell自动备份文件或目录到本地和远程主机
- PHP中header的用法详解