前一段时间做一个小项目,遇到一个问题,就是要在用户输入文本时在某个位置显示带有图标的提示,如:“已输入160字”,并显示警告或OK的LOGO。
开始我采用的方案是:准备2个静态控件,前一个显示图标,后一个显示文字。后来发现这个做法很别扭,而且缺乏柔性。由于平时从事WEB开发比较多,我就自然而然地想到了超文本:)为什么不弄一个超文本的控件呢?
使用方法
最后封装出来的类是CHyperText,它继承于CStatic,大家使用的时候,只要将你的静态控件绑定成CHyperText即可,如:
当然,由于精力有限,我只能实现部分的标签,如下示出已实现的标签:
- FONT:字体的设置,包含face/size/color属性;
- face:字体名,如:黑体;
- size:对应于字体的高度,单位是em;
- color:目前只支持16进制,如:#ff0000,代表红色;
- B:粗体;
- I:斜体;
- U:下划线;
- IMG:图片,包含src属性;
- src:目前只支持位图资源和图标资源,src指定资源的ID,如:src="128";
哪位vcer有时间的话,可以继续完善其标签。
实现方案
如何解析?
在实现上,我主要采用了CMarkup类完成标签的解析。代码如下:
Visit()的内部逻辑是一个嵌套调用:
用户指定的标签文本,如:
会被加上一个<msg>外节点,这样才可以得以正确解析。
Tag接口
另外一个设计就是Tag接口,每个标签,如:<B>将会自动分派到一个实现Tag接口的类,如:TagB。参见如下逻辑部分:
就目前的情况,未知的标签都扔给了TagX,它只负责完成其中文本内容的输出。
Tag接口的定义如下:
因为标签是可能嵌套的,ITag的实现类可以指明嵌套的子节点是否由自己处理,如果是自己处理,则应该将CaptureTag()方法的返回值设置成true,这样标签的访问者将不会再进入该标签的内部。
TagContext
BeginTag()方法会接收到一个TagContext对象,这是一个环境变量,该变量在所有标签处理之前构造,并为所有的标签共享使用,其内容如下:
ITag的实现类
通过使用ITag和TagContext,完成Tag的扩展可能就非常简单,譬如:用以粗体显示的TagB的定义:
以上是主要的实现方法和思路,希望能够对你有所用处。同时也希望有兴趣的vcer能够继续标签的扩展,以支持更多的功能。你可以直接给我发邮件反馈,也可以直接在CHyperText的基础上进行修改、扩展,但请在补充你的版权信息时,保留白乔的版权信息:)
TODO
- 更多的有用的标签?
- 目前的排版功能欠佳:)对于回车换行,无法智能处理;
- 目前的图片只支持位图资源和图标资源,本想抽象出一个接口出来允许用户实现自定义图片的显示的,后来还是没弄,希望这些都是抛砖引玉:)