一步一步实现自己的模拟控件(8)——重构
模拟控件已经出了雏形,是应该重构一下了。
新概念:
其实说是新概念也不尽然,只是在这几步的实现中可以发现,这个模拟控件框架中有两个大的概念:容器和控件。我们一直一来都说的是容器窗口,但是其实这是个可以上升的概念。容器容纳一个控件体系,也就是关联一个根控件,那么它就有点类似于我们的根控件了。但是容器由必须实现和具体窗口和控件的交互,所以我们不能简单的将根控件作为容器。并且对于某些特殊的实现,我们还可能需要对容器的某些功能加以扩展,所以我们这次重构为容器抽象了一个基类,并实现了一个窗口容器。
class Container : public Monopolistic{
using Monopolistic::pWidget_;
using Monopolistic::GetWidget;
public:
Container();
virtual ~Container();
public:
Widget* GetRootWidget() const{return GetWidget();}
public:
virtual bool IsValid() const = 0;
public:
virtual void Invalidate(const RECT& rect){} // 无效化容器矩形区域
virtual void Invalidate(HRGN hRgn){} // 无效化容器不规则区域
virtual void Invalidate(){} // 无效化整个容器区域
};
解耦:
到目前为止,我们的容器驱动和控件之间具有十分紧密的耦合关系(生命周期耦合),这次重构打算将此解耦,使得我们的容器创建和控件体系创建互不相关,仅仅通过一次操作来使得他们关联或者解除关联。
// 建立窗口容器
ghost::widget::WindowContainer container;
container.AttachWindow(hWnd);
// 建立根控件
auto pRootWidget = ghost::Widget::Create();
// 关联容器
pRootWidget->CreateRelationship(&container);
减少类:
这次还有一个大的变化就是将原先的一些概念融合成了新的概念:驱动、消息过滤、消息映射都融合到了容器当中,因为这三个概念和具体容器关系紧密,所以将他们进行融合以减少我们的类数目。
收获:
这次重构建立了容器这个概念我们是有一定收获的:原先我们无法访问控件所关联的容器,现在可以了。原先控件的容器实现不易扩展,现在可以通过继承来扩展(例如layered窗口),甚至可以为容器实现特有的绘制机制(例如使用opengl,以后我们抽象了绘制概念便可以看到,目前还只能使用GDI)。
这次没有什么新的内容添加,但重构还是有必要的,周期性重构利于我们对整个框架的管理,在重构过程中较容易发现和修改BUG。
By Evil.Ghost