信息交流、传播、提炼

nice to meet you

博客园 首页 新随笔 联系 订阅 管理

很多人会以为写组件是件容易的事,也许某些方面是这样的,比如你可以很简单地实现一个自定义的功能。但是写出来的组件好象跟专业厂家开发的组件程序是不是有些差距呢?那么如何写一个专业组件呢,写专业组件要掌握哪些知识呢,它们的内部机理是什么呢?如果你对此感兴趣的话,那么这个系列实在是很值得你来看一看的。

本篇是要介绍如何扩展一个已有的组件功能。比如用户提出来要在TextBox控件上实现一个取得焦点后实现背景色变成蓝色,前景色变成黄色的功能。如果按我们一般的想法,很简单,我只要写一个从TextBox继承下来的AutoColorTextBox类,然后重载OnGotFocus就好了。的确,这是一种好方法,在很多场景里。好,下面我们的客户又提出一个要求Combox也要是这样子,因为他们的录入人员眼睛不是很好,于是你又写了一个AutoColorCombox。这时候你的心情很好,正打算去晚饭犒赏一下自已辛苦的一天,不过你的ProjectManager打电话给你,说用户提出来ListBox也要改一改,还有原来的TextBox要加上只充许录入数字的功能。现在你想说什么,我猜是Fuck you!当你看着这么多乱七糟的扩展类是不是很头痛呢?嗯,MS也考虑到这个问题了,他们提出了一种新的方法或许可以减轻你的痛苦。

我们先来看一个我们常用到的组件,但也许并没有引起你的注意,它就是ToolTip,我们先来看它的效果,左边的图是没有在窗体上放ToolTip时,TextBox所显示的属性,右边就是放了之后的属性,很容易我们知道右边的图多了一个toolTip1上ToolTip属性,不过你想过其中的机制是什么?为什么可以动态地影响一个控件的属性呢?

如果学过设计模式,我们很容易想到Decorate(装饰模式)。实际上CLR就提供了一些辅助类可以让你实现这个目的。那么如何来创立象这样的功能呢?

A)创建一个实现IextenderProvider的类,它实际上只需要有一个CanExtend的函数,你判断是否可以扩展的类型就好了。

B)用ProviderPropertyAttribute修饰该类,它需要两个东东,一个是增加的属性名称,另一个是修饰的对象类型,比如我们要给TextBox增加一个取得焦点时的背景颜色功能,其属性为AutoBackColor。那么这个特性修饰符应该是[ProviderProperty(AutoBackColor,typeof(TextBox))]

C)创建两个方法,以GetXXX和SetXXX来命名,里面就是你的处理过程,其中XXX是你的扩展属性名,比如这个类就应该是GetAutoBackColor。这两个方法有两个功能,一方面是取得对应的属性值,另一方面是注册事件,我的例子中是注册的是MouseEnter和MouseLeave两个事件,这样当鼠标移到控件上时,背景色就会改变。因为每个控件可以设置不同的背景色,因此,你需要在类里包括一个哈希表,这样以保存每个控件不同的用户背景色。

D)如果你想要在工具箱上显示你的这个扩展功能控件,你还需要使这个类从Component继承,如果你从Control继承,会有一点问题,因为VS会认为是一个可显示的控件,当你拖到窗体上时,它不会显示在下面额外的一栏里。

E)还有一点小问题,如何将属性归类到“外观”这个归类里。也很简单,你只要在GetXXX里加上[Category(“Appearance”)]这一句就好了。

最后我们来看一下我写的代码的效果图

好了,也许你要问,这一切是如何实现的,背后的原理是什么,请等下一篇,我将告诉你MS是如何处理这一切的。

参考资 料:MSDN上的文章《Custom Provider Controls》(http://msdn.microsoft.com/msdnmag/issues/03/11/CuttingEdge/),虽然是英文的,不过蛮好懂,也就懒得翻了。

    文中源码请参考:
https://files.cnblogs.com/mywebname/改变控件颜色的扩展控件.rar

posted on 2007-11-15 00:01  seeyou  阅读(966)  评论(2编辑  收藏  举报