一步一步实现自己的模拟控件(6)——控件树及控件区域
控件树
一步一步实现自己的模拟控件(1)中的图上我们可以看到,我们的控件体系其实就是一个控件树。每一个窗口关联一个根控件,所有控件都在这个根控件之下,父控件包容并管理子控件,那么我们的Widget就应该是一个树结点。一个树结点至少有对Parent和Chilren的设置和访问接口:
Widget* GetParent() const;
bool InsertChild(Widget* const pChild);
bool RemoveChild(Widget* const pChild);
在父控件销毁的时候它要负责销毁其下所有的子控件(类似窗口销毁也会销毁其子窗口):
{
// 销毁所有子控件
WidgetSet temp(std::move(pImpl_->children_));
std::for_each(temp.begin(), temp.end(), std::mem_fn(&Widget::Destroy));
if (IsRoot())
{
// 作为根控件,同时销毁驱动
delete pImpl_->pDriver_;
}
else
{
// 不是根控件,则脱离父控件
SetParent(0);
}
delete pImpl_;
}
实现中我们使用std::set来保存子控件,这样便于防止子控件重复设置,也便于移除子控件,缺点就是不能对子控件进行排序。如果以后我们提供控件的z-order概念,那么我们就会使用能够进行排序的容器来容纳子控件。
控件区域:
windows下,我们使用RECT结构来保存控件自身相对于窗口客户区的区域,那么窗口客户区尺寸改变时也就是我们控件进行布局的时机,那我们就要在消息过滤中处理WM_SIZE消息了。
{
RECT clientRect;
::GetClientRect(param.hWnd, &clientRect);
pRootWidget->SetAbsoluteRect(clientRect, false);
}
break;
我们将控件的布局交由父控件管理,也就是说我们只需要更新根控件区域便可。根控件负责对其子控件进行布局,如此递归。
控件更新:
当控件区域改变了,那么相应的其显示也应相应的进行更新,所以我们的SetAbsoluteRect接口有一个update参数用于控制是否让窗口产生无效区域激活绘制。
// 因为模拟控件只是窗口客户区的一个区域,当区域改变时应该产生原区域和新区域or运算后区域的脏矩形
// 以使得窗口去重绘这部分区域。
// 可能有些批量性质的操作会在操作多个控件后进行整体更新,所以在对单个控件设置新区域的时候可能不会想要更新。
// 所以才加上这个是否立即更新的开关。
void SetAbsoluteRect(const RECT& rect, bool update = true);
既然提到了绘制,那么我们也应该让我们的控件展示在窗口上了。
控件绘制:
通常我们的窗口程序都是在WM_PAINT消息中进行绘制,我们的控件系统当然也需要处理此消息。
{
// 使用内存DC来缓冲绘制
// 目前没有计算脏矩形区域
wnd_msg_assistant::OnPaint opAssistant(param.hWnd);
pRootWidget->Draw(opAssistant.GetMemDC());
}
return S_OK;
这里引入了一个辅助对象帮助我们产生内存DC,优化我们的绘制效率。我们直接return了这个消息,也就是说我们将这个消息过滤掉了。前面WM_SIZE和WM_DESTROY我们都没有过滤,只是在这个时机对控件进行了通知或者操作。之所以要过滤WM_PAINT消息是因为外部的绘制和控件的绘制难以协调,那么我们干脆就接管了窗口客户区的绘制了。
当然,控件也需要负责绘制其子控件,那么Draw接口中便会调用子控件的Draw,如此递归使得每个控件都能够得以绘制。
首次直观的看到我们的控件:
我们在调试版本中,为每个控件生成了一个随机的颜色,根据控件的区域绘制了其边框,这样我们就第一次直观的在窗口中看到了我们的控件。
迫不及待,具有了区域的控件,我们已经急切的想要对其布局进行控制,绘制进行定制了。布局控制和绘制定制当然属于扩展部分,那么下面就将要引入我们的扩展体系了,尽请期待。
下载测试工程源码
转载于:https://www.cnblogs.com/EvilGhost/archive/2011/04/09/Abstract_Widget_6.html
一步一步实现自己的模拟控件(6)——控件树及控件区域相关推荐
- 一步一步学WF系列(四)——工作流模拟登陆
1. 摘要 我们之前已经熟悉了关于WF的基本概念,相信各位也都跃跃欲试.想步入真正的WF开发. 从本文开始,我们就先来熟悉在WF中的活动. 2. 活动 WF的核心就是一系列的活动. 而工作流就是多个活 ...
- 一步一步实现自己的模拟控件(9)——消息处理
这次我们将要给Widget增加一些状态,并使其能够接受出消息处理扩展,测试工程中实现了一个按钮的消息处理扩展. Widget状态: 之前的控件只是绘制了一个边框,并且总是会在窗口中显示.实际上我们往往 ...
- 【深度学习基础】一步一步讲解卷积神经网络
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送 本文转自:一步一步讲解卷积神经网络 卷积神经网络(Convoluti ...
- SQL Server 2008 Analysis Services 多维数据库一步一步从入门到精通
SQL Server 2008 Analysis Services 多维数据库一步一步从入门到精通(一) 创建 Analysis Services 项目(图) 在开始之前,我的电脑上已经完整的安装了S ...
- 手挽手带你学React:四档(上)一步一步学会react-redux (自己写个Redux)
手挽手带你学React入门四档,用人话教你react-redux,理解redux架构,以及运用在react中.学完这一章,你就可以开始自己的react项目了. 之前在思否看到过某个大神的redux搭建 ...
- 一步一步学Silverlight 2系列(12):数据与通信之WebClient
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://terrylee.blog.51cto.com/342737/67249 ...
- 【Linux】一步一步学Linux——ld命令(256)
00. 目录 文章目录 00. 目录 01. 命令概述 02. 命令格式 03. 常用选项 04. 参考示例 05. 附录 01. 命令概述 ld命令是GNU的连接器,将目标文件连接为可执行程序. 0 ...
- 【Linux】一步一步学Linux——mtools命令(244)
00. 目录 文章目录 00. 目录 01. 命令概述 02. 命令格式 03. 常用选项 04. 参考示例 05. 附录 01. 命令概述 mtools命令显示mtools支持的指令,mtools为 ...
- 【Linux】一步一步学Linux——reboot命令(197)
00. 目录 文章目录 00. 目录 01. 命令概述 02. 命令格式 03. 常用选项 04. 参考示例 05. 附录 01. 命令概述 reboot命令用于用来重新启动计算机.但是机器重启必须要 ...
最新文章
- Last-Modified、If-Modified-Since 实现缓存和 OutputCache 的区别
- 实现Nginx https
- 类与类之间关系的表示方式
- python批量给文件命名为001,002,...【亲测有效】
- php 循环链表,PHP实现循环链表功能
- Hadoop生态hive(三)Hive QL介绍
- 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 16丨报告的记录 II【难度中等】
- vue监听字符串长度_Vue 的 computed 和 watch 的区别
- linux下的dns服务器
- Hadoop HIVE 聚合查询
- 彩色静电植绒印花工艺的五个方法
- 经典!史上最全免费收录网站搜索引擎登录口
- matlab运行时间特别长,Matlab运行时间过长
- 题解 P1894 【[USACO4.2]完美的牛栏The Perfect Stall】
- 偶遇RandomAccessFile
- (赴日流程)家属滞在签证
- 最简洁的Git的基本操作
- 基于神经网络的文字识别,神经网络如何识别图像
- SpringSecurity之SecurityContext和Authentication对象
- 文本匹配相似度计算---多种距离算法 ,多种相似度计算算法,一看就懂
热门文章
- oracle中check约束性别,关于Oracle Check类型约束的导入与启用
- oracle10官网下载安装,oracle11g安装(win10)下载安装
- dos命令行设置网络优先级_计算机网络故障及其维修方法
- wchar_t*和string相互转换
- pytorch无法下载或下载缓慢问题
- 通过开始关键字和结束关键字,查找所有的邮箱名称记录
- java图形界面设计 swing之JTable表格的创建使用-添加鼠标监听
- Pixhawk之姿态解算篇(3)_源码姿态解算算法分析
- C语言运算符优先级列表
- Codeforces Round #529 (Div. 3) F. Make It Connected(最小生成树)