离上次发博文过去了好久,先是要忙一个机器人的项目,然后就是部门的事情和考试周复习,然后就到了考试周,趁着复习的间隙,拾起了寒假时候抄的界面库,修掉了从前的bug。

bug1 控件显示问题

当初抄这个库的时候就对排版部分的代码一头雾水,借着这次调bug,稍微理清了排版部分代码的意图。界面的排版是动态进行的,用户用placement命名空间的各种排版元素构造出整个排版的结构布局,然后调用WinForm对象的ApplyPlacement成员,把前面构造好的布局传给它,函数内部递归地读取结构对象的大小和它的子对象,一层一层的计算并应用排版布局。

如此应用排版

ApplyPlacement(
HorzScale(10, 100, 0.5,
Control(txtRegex),
Control(txtRegex2)
)
);

ApplyPlacement里面是单纯的调用的排版对象的ApplyTo函数

inline
void WinContainer::ApplyPlacement(placement::Base::Pointer Placement)
{
Placement->ApplyTo(GetPlacement());
}

ApplyTo函数是个虚函数,根据不同的排版元素,有不同的效果,基本原理上都是计算空间,设定当前布局在窗口大小变化时的行为,递归应用子元素的排版,然后设定子元素的位置。

feature2 修改了Event的定义

这个库原版的事件是用宏来批量生成的,代码没有高亮,夹杂着各种连接token的##,显得十分晦涩难懂,不过考虑到这个库是vczh大学时期的作品,那时候还没有C++11,不能愉快的使用变长模板参数来写一个Event,选择用宏来替代也是一个不错的选择,阅读代码的人面对着这一大片宏,肯定会先感叹编写者的牛b吧。

这一次把Event替换成了vlpp里面的Event,并且由于连带的包含关系,我把智能指针类Ptr和函数对象类Func也一并抄了过来。综合对比这个库之前的Event和vlpp里的Event,两者在代码的组织上并没有太大的区别,只是vlpp条理更加清晰,把EventHandler的部分独立出来成了一个Func,并且添加了lambda等可调用对象的封装支持。

Event内部含有一个Func数组,存放,本身重载了operator()(TArgs… args),当Event本身被调用时,Func数组内的可调用对象一个一个地被调用,同时变长参数表TArgs…一个一个被完美转发进Func的调用参数内,达成了callback的目的。

void operator()(TArgs... args) const
{
for (auto&& handler : handlers)
{
handler(PerfectForward<TArgs>(args)...);
}
}

下面说收Func的设计,std::function相比于Func,其最大的弱点就是——不能封装成员函数指针,众所周知,成员函数指针在调用的时候是需要一个对应的对象指针的存在的,而function并不能做到这个,为此,C++还提供了std::mem_fn函数,接受对象指针和成员函数指针,返回一个可调用对象,这本身是可以的,问题是在这个对象本身和std::function并无任何关联,类型名称也是奇观的下划线开头,平常只能用auto自动推断,如果我想把std::function和这个东西生硬的结合起来,还不如自己写一个。

Func本身包含一个可调用对象的智能指针,利用operator()的重载调用智能指针中的可调用对象,而这个可调用对象是该重点说的东西:

C++有三种不同的可调用对象——普通函数指针、成员函数指针、仿函数,这三种东西可以分别封装成三个可调用对象,然后重点来了——让他们共同继承自一个相同的基类,并且这个积累有一个纯虚的operator()成员,这个时候就能解释为什么Func内是一个只能指针而不是一个对象副本了,因为没办法愉快的利用多态调用不同的可调用对象。

有了Func,有了Event,这个事件回调机制就齐了。

p.s.前几天无意中看到了boost::signal,这是一个加强版的Event-EventHandler设计,可以给事件回调进行分组管理,临时禁用某些回调,或者批量解绑回调等,之后的时间,写完了自己用的Map和List,要尝试实现一下这个。

p.p.s.顺便感叹写boost的大牛们在没有变长模板存在的时代硬生生的用模板参数堆出了最高支持9个参数的boost::signal,真是太厉害了

feature3 合并Destroy和析构函数,使用智能指针代替手动析构资源

这里又要吐槽Win32API的三个消息WM_QUIT, WM_CLOSE, WM_DESTROY了,虽然从设计角度,这三个消息并没有冲突,但是对于使用者来说,相似的事件名称的确会产生混淆。也许是为了照顾上古时期C语言不支持过长标识符的设计,我想把他们分别命名成WM_APPLICATIONQUIT, WM_ASKWINDOWCLOSE, WM_WINDOWDESTROYED会好很多,这样也能一目了然地明白三个消息的意义——程序退出,请求关闭窗口,窗口摧毁完毕

原本这个程序的消息机制是这样的,窗口接受WM_CLOSE消息,关闭自身的同时如果发现自己是主窗口,那么呼叫Application退出(此时还未从主窗口消息处理函数中退出),Application管理着程序所有的窗口和控件,Application对窗口一个一个调用Destroy函数,然后再用delete析构调他们,Destroy函数会一层一层地销毁掉对象实际占有的资源,到基类WinControl的Destroy内调用DestroyWindow时,WM_DESTROY会生成然后立即发送给消息处理函数处理,这时候,窗口还没有从Application的列表里删除,Application的消息处理函数找到列表里的窗口对象,将WM_DESTROY消息传递给他处理,这时候窗口释放掉所有的附带对象包括Timer,反注册快捷键,最后调用PostQuitMessage,程序正常退出。

将Destroy写进析构函数里之后,由于调用DestroyWindow的时候,窗口已经从Application的列表中被删除,WM_DESTROY找不到处理者,被默认处理,没有PostQuitMessage被调用,所以窗口已经没了,消息循环还在跑,程序还没有完全退出,这时候只要在负责delete所有窗口的函数的最后加上PostQuitMessage,就能正确的结束消息循环,关闭程序。

就先说到这里吧。

Win32API界面库 - Project wheels 工程基础部分完成的更多相关文章

  1. 【液晶模块系列基础视频】4.5.X-GUI图形界面库-进度条等函数简介

    [液晶模块系列基础视频]4.5.X-GUI图形界面库-进度条等函数简介 ============================== 技术论坛:http://www.eeschool.org 博客地址 ...

  2. 【液晶模块系列基础视频】4.4.X-GUI图形界面库-画tab函数简介

    [液晶模块系列基础视频]4.4.X-GUI图形界面库-画tab函数简介 ============================== 技术论坛:http://www.eeschool.org 博客地址 ...

  3. 【液晶模块系列基础视频】4.3.X-GUI图形界面库-画box函数简介

    [液晶模块系列基础视频]4.3.X-GUI图形界面库-画box函数简介 ============================== 技术论坛:http://www.eeschool.org 博客地址 ...

  4. 【液晶模块系列基础视频】4.2.X-GUI图形界面库-画矩形函数简介

    [液晶模块系列基础视频]4.2.X-GUI图形界面库-画矩形函数简介 ============================== 技术论坛:http://www.eeschool.org 博客地址: ...

  5. 【液晶模块系列基础视频】4.1.X-GUI图形界面库-画线画圆等函数简介

    [液晶模块系列基础视频]4.1.X-GUI图形界面库-画线画圆等函数简介 ============================== 技术论坛:http://www.eeschool.org 博客地 ...

  6. C++ 100款开源界面库 (10)

    (声明:Alberl以后说到开源库,一般都是指著名的.或者不著名但维护至少3年以上的.那些把代码一扔就没下文的,Alberl不称之为开源库,只称为开源代码.这里并不是贬低,像Alberl前面那个系列的 ...

  7. 仿迅雷播放器教程 -- C++ 100款开源界面库 (10)

      (声明:Alberl以后说到开源库,一般都是指著名的.或者不著名但维护至少3年以上的.那些把代码一扔就没下文的,Alberl不称之为开源库,只称为开源代码.这里并不是贬低,像Alberl前面那个系 ...

  8. 开源的DirectUI界面库

    1. duilib简介 duilib是一个开源的DirectUI界面库,简洁但是功能强大.而且还是BSD的license,所以即便是在商业上,大家也可以安心使用.现在大家可以从这个网站获取到他们所有的 ...

  9. VC UI界面库大集合

    Guitoolkit http://www.beyondata.com/pwc.html The Ultimate Toolbox http://www.codeproject.com/KB/MFC/ ...

随机推荐

  1. 二分图最大权最小权完美匹配模板KM

    在网上找了一份挺好的模板,先标一下哦~链接君:http://blog.csdn.net/abcjennifer/article/details/5844579 #include <iostrea ...

  2. linux下安装nginx后开机启动篇

    众所周知nginx安装后需要手动去启动,每次开机之后都要执行nginx的启动命令很蛋疼.那么我们来让nginx开机启动吧 1.先創建一個nginx文件把 [root@localhost ~]# vi ...

  3. log4net.redis+logstash+kibana+elasticsearch+redis 实现日志系统

    前端时间写了个随笔 log4net.NoSql +ElasticSearch 实现日志记录 ,因项目原因需要把日志根java平台的同事集成采用logstash+kibana+elasticsearch ...

  4. volatile简介

    volatile简介 java语言提供了一种稍弱的内存同步机制,即volatile变量.用来确保将变量的更新操作通知到其它线程,保证了新值能立即同步到主内存,以及每次使用前立即从内存刷新.当变量声明为 ...

  5. CSS3-Media Query 基础

    一.常见的属性: device-width , device-height 屏幕宽高 width , height 渲染窗口宽高 orientation 设备方向 resolution 设备分辨率 二 ...

  6. UVa 1626 Brackets sequence (动态规划)

    题意:用最少的括号将给定的字符串匹配,输出最优解.可能有空行. 思路:dp. dp[i][j]表示将区间i,j之间的字符串匹配需要的最少括号数,那么 如果区间左边是(或[,表示可以和右边的字符串匹配, ...

  7. Python Scopes and Namespaces

    Before introducing classes, I first have to tell you something about Python's scope rules. Class def ...

  8. 图片过大导致OOM

    原文:http://www.codeceo.com/article/android-load-image-oom.html 一.分析 在加载图片过程中出现的OOM的几种情况: 1. 加载的图片过大 2 ...

  9. html之小积累-.-iframe自适应高度

    在做系统框架的时候,常常会用到iframe,当需求是iframe不能出现纵向滚动条,需要根据加载页面的高度,一致延伸,但是iframe的高度自适应问题比较麻烦,当时也是纠结了好久. 方案1:当遇到if ...

  10. sqlite入门

    SQLite官网: https://www.sqlite.org/index.html 1. 下载请到https://www.sqlite.org/download.html下载相应平台的sqlite ...