在完全此系列的一之后,我一直在想第二篇究竟应该如何组织,首先我想接着上篇的话题把框架的问题说完,首先我还是这句话在本系列当中会兼顾C/C++开发与.NET开发,其实不管用不用框架,WINDOWS都是基于消息的,只要这点不变,我就希望大家能通过我的系列博客当中能体会二者的联系。
在第一篇博客当中UI框架的实现与MFC或者NET都有一个本质的区别那就是子控件是不基于窗体句柄的,那么这其中的好处是灵活,还有的好处这是一个支持实现透明控件的框架,圆角边界等在。NET或者MFC UI框架当中非常难实现的效果。
我也就是我什么在上一篇博客当中的拿那个类似于LIST的控件举例子,因为他的ITEM风格是一致的。如果在一个大的父控件也就是容器当中要存在多种不同风格的子控件(ITEM)需要怎么做呢。首先要记得抽象。把子控件需要的方法抽象出来,由于只是框架的讲解还是用伪代码来实现。
控件
{
RECT Rect;//大小,位置
bool IsFocused;
容器 父控件;
//控件[] 子控件s;
//Int 层级;
Onpaint(DC 画图,Rect rect);
OnClick(Point point);
OnKeyDown(KeyChar keychar);
}
如果你的开发环境是C++或者C#这些支持面向对象编程的语言那么你的自定义控件就需要继续一下这个控件类。
比如
CLASS OWNERDRAWLIST:PUBLIC 控件
{
//私有方法列表
.....
//私有变量列表
.....
}
如果你的开发环境是纯C的那需要用拥有的办法来模拟一下继承
STRUCT OWNDERDRAWLIST
{
控件 实例;
//私有变量及方法
}
那么在父控件也就是容器当中我们应该这样实现
容器
{
控件[] 子控件s;
容器
{
//设置某个子控件的取得焦点
}
OnPaint(DC dc)
{
for(i=0;i<子控件s个数;i++)
{
子控件[i]->OnPaint(dc,子控件->Rect);//如果加入层的概念此处需要优化
}
}
OnClick(Point point)
{
for(i=0;i<子控件s个数;i++)
{
if(子控件[i]->Rect->Contains(point))
{
子控件[i]->Onlick(point);
子控件[i]->IsFocused=true;
//若无特殊机制其它控件的焦点设为FALSE
}
}
}
OnKeyDown(Keychar keychar)
{
for(i=0;i<子控件s个数;i++)
{
if(子控件[i]->IsFocused)
{
子控件[i]->OnKeyDown(keychar);
}
}
}
}
那么我们一个相对来说完整的框架就已经实现了。下面我们就纯把WINDOWS下的UI框架与这个UI框架做一下对比。首先他们的实现思路是一致的,都是容器再嵌套各个子控件,并将消息分发。那么不同呢,WINDOWS的下的UI框架是基于窗体句柄的,而这个简易的框架并不需要句柄。只是通过容器的句柄和DC来完成绘图与消息传递的机制。
WM下如何。NET MFC框架的好处,肯定就是容易管理。不过缺点就是难以实现特效。为什么?原因很简单,在WINDOWS框架下在上层存在窗体的情况下下层的窗体在刷新时是不会重绘的。很多人问WM下怎么透明,这个简单ALPHABLEND就可以,不过实现透明控件就麻烦了,简单的说只要一刷新,由于下层窗体并不刷新会造成上层窗体的背景错误。还有的用户比较喜欢一些异形窗体的效果,不过由于WINDOWS下控件是HWND的,他占用的空间必须是正规的矩形。
当然上面的框架还有两大难点遗留首先是控件层级的问题(当中也牵扯焦点),还有一个就是在不拥有句柄的伪控件当中添加子控件。但是由于不想就框架的问题再加以赘述,所以在后面会有两个专题专门来说,WINDOWS下的焦点控制及子控件管理的专题.
接下来的就为一个比较热门的话题也是此系列下一篇的主题小做讨论,如何在WM下高效的实现透明控件的效果,我相信统计一下相关的贴子的总数就能看出来大家对于这个问题的关心程度,为什么在WM上实现透明很麻烦,除了下层窗体不绘制之外这个框架上的问题之外,ALPHABLEND效率就不高,能够支持@通道的IIMAGE只能用十分低下来形容,咱们下篇就对此问题来一个专门的讨论!