如何用c#编写文本编辑器_c#应用

2008-02-23 05:45:10来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

南京XDesigner2006版权任何,不限转载,请保留版权声明

摘要

本文探讨了使用C#从底层研发一个带格式的文本编辑器的任务,深入探讨了其中的文档对象模型的设计,图像化用户界面的处理和用户操作的响应,说明了其中的某些技术问题和解决之道。

前言

小弟从大学里开始接触编程也有6年了,工作4年也是干编程的活,见过不少程式,自己也编过不少,在学校编程自己觉得是搞艺术品,其实玩一些游戏,比如文明法老王星际等从某些角度看也是搞艺术品,看着自己苦心经营的建筑物和人员由少变多,由简单变复杂,心中有些成就感。编程也相同,程式从几十行写到上万行,功能由HellowWord到相当复杂而强大,心中也有不少成就感。

毕业后工作,才渐渐感悟软件研发本质上是做一个工具,这个工具给别人或自己用。有了工具,很多问题就迎刃可解了。如此开来偶们程式员和石匠铁匠木匠是同一类人了。但是没什么,程式员本来就没高人一等,人在社会,认认真真的工作就行了。

问题

废话不多说了,现在谈谈标题提出的问题,如何用C#编写文本编辑器。本人有幸研发过一个比较复杂的文本编辑器,因此也算有点经验吧,在此来分享一下。这里所指的文本编辑器不是简单的像Windows自带的单行或多行文本编辑框,而是类似于Word的文本编辑器。

粗看起来,一个编辑器有什么好难的,其实很难的,因为我们认为容易的事对电脑来说确实天大的问题。比如大家经常上网,能够发现最近几年很多网站登录时除了输入用户名和密码后还要输入所谓的验证码,而验证码则在输入框旁边歪歪扭扭的画了出来,就像小学一年纪的学生在一张脏纸上写的相同,这样做只是为了防止程式来模拟登录,因为歪歪扭扭的文字人类能够很容易的辨认,而电脑则很不容易辨认。
例子:注册hotmail使用的验证码,其显示的字符为 8UV9BKYR 。

一个文本编辑器主要处理的问题有

文档保存格式的定义,文档保存为文本格式还是二进制格式的,文档中各个信息单元保存什么信息。文档格式很重要。
和文档存储系统的交流,也就是保存和加载文档的功能,这里的文档存储系统能够是操作系统文档子系统,数据库,网络,其实文档格式定下了,各种文档存储系统差别不大。
文档加载后的文档对象维护,面对比较复杂的文档处理,需要使用面向对象的编程思想,认真分析文档结构,将加载的文档数据一点点肢解掉,每一个最小的不可分割的文档数据转换为一个对象,然后使用一个对象树来保存文档内容的层次关系,这样构造一个文档对象树。文档编辑工作就是维护这个文档对象树了。
文档对象的排版,文档加载后需要处理整个文档对象树,计算每个对象的显示大小,然后在视图区中排列要显示的对象,包括段落和文档行的计算,然后计算对象在视图区域中的直角坐标参数。
文档的绘制,这里的绘制包括在电脑屏幕上绘制文档内容和在打印机上绘制。程式根据计算好的对象在视图区中的坐标,进行一些坐标转换,在图像输出对象上绘制对象,比如绘制一个文字或图片。由于.NET框架中,操作屏幕和打印机都是基于GDI+的,两者没有本质差别,因此一些处理的绘制代码能够绘制屏幕,也能够绘制打印机。在屏幕上绘制文档还特别需要优化,尽量减少闪烁。
环境消息的处理,环境消息指一些Windows消息,这些消息应该改变文档内容,比如鼠标键盘消息,系统粘贴板的相关消息。程式处理这些消息,修改文档对象树,向对象树插入删除或修改文档元素对象。文档对象树发生改变后需要重新对文档进行排版,处理进行段落计算和文档行计算,重新计算对象在视图区中的位置,然后根据需要刷新屏幕显示。此外更有用户选择文档内容时也要处理。
文档的保存,程式根据文档对象树生成一些数据,然后保存到文档存储系统,这一步能够看作对象序列化。
应用程式的开放性,提供二次研发的能力,提供类似VBA的功能
一个完整的功能不弱的文本编辑器结构是很复杂的,涉及到的问题很广泛,没有数万行的代码是搞不定的,这些问题在本文是不可能一一列出来并进行讨论,在此只好挑一些重点来说说。

文档对象模型

在实际研发时不必挨个解决问题,我是首先确定文档对象树的结构,这里使用了文档对象模型的概念,其实我们已碰到很多种文档对象模型,最多的莫过于HTML文档对象模型,我们用JavaScript来控制HTML页面内容时就是使用HTML文档对象模型,此外更有XML文档对象模型,VBA操作的是Word或Excel文档对象模型。使用文档对象模型,可将文档中任何的内容和内存中的某个对象联系起来,当应用程式修改了内存的对象的数据,则相应的文档内容就修改了。删除了内存中的对象也就删除了相应的文档内容。一些文档对象模型的思想能够参考http://www.w3.org。

文档对象模型中有很常见的是对象的继承和重载。大家能够看看.NET类库的System.XML名称空间下定义的XML文档对象模型,您能够发现无论是XML文档对象(XMLDocument),XML节点(XMLElement)还是属性(XMLAttribute),甚至注释(XMLComment)纯文本数据(XMLText)都是从抽象类XMLNode继承过来的。这样设计的好处是能够很方便的遍历XML文档对象树,各种对象都是从XMLNode派生的,都根据各自需要重载一些成员方法,其他程式都可把这些对象都看作XMLNode来使用,利用对象方法的重载和多态性来实现各自不同的处理。

基础对象

在这种指导思想下,我也定义了一个抽象类TextElement,任何的文档对象都是从该对象派生的。该类定义了以下虚成员

Left,Top,Width,Height属性,用于表示对象在的位置和显示大小
RealLeft , RealTop 只读属性,表示对象在视图区域中的显示位置
RefreshSize 方法,用于重新计算对象的显示大小
RefreshView 方法,重新绘制对象
HandleMouseDown 方法,处理鼠标按键按下事件
HandleMouseMove 方法,处理鼠标移动事件
HandleMouseUp 方法,处理鼠标按键松开事件
FromXML 方法,从一个XML节点加载对象数据
ToXML 方法,向一个XML节点保存对象的任何的数据
由于文档内容是分层次的,因此还定义一个容器类型TextContainer,该类型从TextElement派生的,其中进行扩展来能够保存若干个子对象,他定义了以下虚成员

MaxWidth 属性,对象内容的最大宽度,一个文档显示宽度就是纸张宽度减去左右页边距的距离,文档任何的内容被限制在这个显示宽度中间,该属性和显示宽度有关

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 漫谈c#编程中的多态和new关键字_c#教程

下一篇: c# 正确读取存储中文,连同如何获取字节流编码_c#应用