Win32API界面库 - Project wheels 工程基础部分完成

离上次发博文过去了好久,先是要忙一个机器人的项目,然后就是部门的事情和考试周复习,然后就到了考试周,趁着复习的间隙,拾起了寒假时候抄的界面库,修掉了从前的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,就能正确的结束消息循环,关闭程序。

就先说到这里吧。

时间: 2024-10-11 06:33:33

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

[转载]前端工程——基础篇

特别声明:本文转载@云龙的<前端工程——基础篇>,感谢@云龙的分享. 喂喂喂,那个切图的,把页面写好就发给研发工程师套模板吧. 你好,切图仔. 不知道你的团队如何定义前端开发,据我所知,时至今日仍然有很多团队会把前端开发归类为产品或者设计岗位,虽然身份之争多少有些无谓,但我对这种偏见还是心存芥蒂,酝酿了许久,决定写一个系列的文章,试着从工程的角度系统的介绍一下我对前端,尤其是Web前端的理解. 只要我们还把自己的工作看作为一项软件开发活动,那么我相信读过下面的内容你也一定会有所共鸣. 前端,是

前端工程——基础篇

# 前端工程--基础篇 > 喂喂喂,那个切图的,把页面写好就发给研发工程师套模板吧. 你好,切图仔. 不知道你的团队如何定义前端开发,据我所知,时至今日仍然有很多团队会把前端开发归类为产品或者设计岗位,虽然身份之争多少有些无谓,但我对这种偏见还是心存芥蒂,酝酿了许久,决定写一个系列的文章,试着从工程的角度系统的介绍一下我对前端,尤其是Web前端的理解. 只要我们还把自己的工作看作为一项软件开发活动,那么我相信读过下面的内容你也一定会有所共鸣. ## 前端,是一种GUI软件 现如今前端可谓包罗万象

常见MFC UI界面库[转]

Xtrme toolkit,BCGControlBar,SkinMagic,AppFace,Skin++,Uskin++,SYGUI,LibUIDK,GuiToolkit,GardenUI等等,除了后两种一个是开源,一个是免费的外,其余的都是收费的. The Ultimate Toolbox http://www.codeproject.com/KB/MFC/UltimateToolbox.aspx GuiToolkit(开源,mfc扩展框架,类似Visual Studio 2003风格)htt

C++界面库(十几种,很全),当然Delphier有FMX

刚开始用C++做界面的时候,根本不知道怎么用简陋的MFC控件做出比较美观的界面,后来就开始逐渐接触到BCG  Xtreme ToolkitPro v15.0.1,Skin++,等界面库,以及一些网友自己写的界面库,开始对于C++软件界面美化有了一点点的心得.不敢藏私,希望和一些新手朋友们分享交流. 一.  开源C++界面库 1.RingSdk Ringsdk是CSDN上一个前辈自己写的界面库,这个界面库很轻而易举实现QQ2009的界面效果.链接见 http://blog.csdn.net/rin

MFC BCGCBProInc.h : No such s file or dictionary. 解决方案:安装BGB界面库

BCGCBProInc.h : No such s file or dictionary. 解决方案:安装BGB界面库 一.   关于BCGControlBar. BCGControlBar是一个基于MFC的扩展库,您可以通过完全的用户化操作构成一些类似于Microsoft Office 2000/XP/2003和Microsoft Visual Studio.NET的应用程序(用户工具栏.菜单.键盘等等).BCGControlBar库包含了大约150多个经过精心设计,测试和具有完备文档的MFC

MFC界面库

http://blog.csdn.net/cddchina/article/details/38759485 刚开始用C++做界面的时候,根本不知道怎么用简陋的MFC控件做出比较美观的界面,后来就开始逐渐接触到BCG  Xtreme ToolkitPro v15.0.1,Skin++,等界面库,以及一些网友自己写的界面库,开始对于C++软件界面美化有了一点点的心得.不敢藏私,希望和一些新手朋友们分享交流. 一.  开源C++界面库 1.RingSdk Ringsdk是CSDN上一个前辈自己写的界

各种界面库介绍及比較

具体界面库列表见http://home.pacbell.net/atai/guitool/ 怎样选择界面库 产品易用性 是否easy整合到现有应用程序中?是否easy在新的应用程序项目中应用? 开发者是否能及时掌握并使用 产品稳定性 是否有足够多的演示样例演示控件库各个方面的功能特性 是否有众多的成功案例 是否一直有持续更新 界面库高效性 拖拽窗体,观察是否有明显的停顿感. 可在一个系统下,找一些知名软件比較,如QQ/MSN等.假设有明显差异 拖拽窗体,观察界面控件是否有明显闪烁 . 软件启动速

在VC6.0中能不能使用Duilib界面库呢?

Duilib库的源代码是在vs2010下编译的,一般适用于vs2008及以上的版本开发使用,那么duilib能不能在vc6.0的工程中使用呢?如何在vc6.0中使用duilib库呢? 今天,由于工作要求,需要在vc6.0下使用duilib库,百度了很久,未果,所以自己来尝试了一下! 1.在vc6.0中,新建一个MFC对话框工程,我用的是mfc对话框,习惯这么用. 2.将Duilib头文件及lib引用库拷贝到工程目录,引用进去. 3.新建duidlg类,这个类是自己定义的,对应这duilib里的窗

C++界面库

刚开始用C++做界面的时候,根本不知道怎么用简陋的MFC控件做出比较美观的界面,后来就开始逐渐接触到BCG  Xtreme ToolkitPro v15.0.1,Skin++,等界面库,以及一些网友自己写的界面库,开始对于C++软件界面美化有了一点点的心得.不敢藏私,希望和一些新手朋友们分享交流. 一.  开源C++界面库 1.RingSdk Ringsdk是CSDN上一个前辈自己写的界面库,这个界面库很轻而易举实现QQ2009的界面效果.链接见 http://blog.csdn.net/rin