前言
小弟從大學裡開始接觸編程也有6年了,工作4年也是干編程的活,見過不少程序,自己也編過不少,在學校編程自己覺得是搞藝術品,其實玩一些游戲,比如文明法老王星際等從某些角度看也是搞藝術品,看著自己苦心經營的建築物和人員由少變多,由簡單變復雜,心中有些成就感。編程也一樣,程序從幾十行寫到上萬行,功能由HellowWord到相當復雜而強大,心中也有不少成就感。
畢業後工作,才漸漸感悟軟件開發本質上是做一個工具,這個工具給別人或者自己用。有了工具,很多問題就迎刃可解了。如此開來偶們程序員和石匠鐵匠木匠是同一類人了。不過沒什麼,程序員本來就沒高人一等,人在社會,認認真真的工作就行了。
問題
廢話不多說了,現在談談標題提出的問題,如何用C#編寫文本編輯器。本人有幸開發過一個比較復雜的文本編輯器,因此也算有點經驗吧,在此來分享一下。這裡所指的文本編輯器不是簡單的像Windows自帶的單行或多行文本編輯框,而是類似於Word的文本編輯器。
粗看起來,一個編輯器有什麼好難的,其實很難的,因為我們認為容易的事對計算機來說確實天大的問題。比如大家經常上網,可以發現最近幾年很多網站登錄時除了輸入用戶名和密碼後還要輸入所謂的驗證碼,而驗證碼則在輸入框旁邊歪歪扭扭的畫了出來,就像小學一年紀的學生在一張髒紙上寫的一樣,這樣做只是為了防止程序來模擬登錄,因為歪歪扭扭的文字人類可以很容易的辨認,而計算機則很不容易辨認。
例子:注冊hotmail使用的驗證碼,其顯示的字符為 8UV9BKYR 。
一個文本編輯器主要處理的問題有
◆文件保存格式的定義,文檔保存為文本格式還是二進制格式的,文檔中各個信息單元保存什麼信息。文檔格式很重要。
◆和文檔存儲系統的交流,也就是保存和加載文檔的功能,這裡的文檔存儲系統可以是操作系統文件子系統,數據庫,網絡,其實文件格式定下了,各種文檔存儲系統差別不大。
◆文檔加載後的文檔對象維護,面對比較復雜的文檔處理,需要使用面向對象的編程思想,認真分析文檔結構,將加載的文檔數據一點點肢解掉,每一個最小的不可分割的文檔數據轉換為一個對象,然後使用一個對象樹來保存文檔內容的層次關系,這樣構造一個文檔對象樹。文檔編輯工作就是維護這個文檔對象樹了。
◆文檔對象的排版,文檔加載後需要處理整個文檔對象樹,計算每個對象的顯示大小,然後在視圖區中排列要顯示的對象,包括段落和文檔行的計算,然後計算對象在視圖區域中的直角坐標參數。
◆文檔的繪制,這裡的繪制包括在計算機屏幕上繪制文檔內容和在打印機上繪制。程序根據計算好的對象在視圖區中的坐標,進行一些坐標轉換,在圖形輸出對象上繪制對象,比如繪制一個文字或圖片。由於.Net框架中,操作屏幕和打印機都是基於GDI+的,兩者沒有本質差別,因此一些處理的繪制代碼可以繪制屏幕,也可以繪制打印機。在屏幕上繪制文檔還特別需要優化,盡量減少閃爍。
◆環境消息的處理,環境消息指一些Windows消息,這些消息應該改變文檔內容,比如鼠標鍵盤消息,系統粘貼板的相關消息。程序處理這些消息,修改文檔對象樹,向對象樹插入刪除或修改文檔元素對象。文檔對象樹發生改變後需要重新對文檔進行排版,處理進行段落計算和文檔行計算,重新計算對象在視圖區中的位置,然後根據需要刷新屏幕顯示。此外還有用戶選擇文檔內容時也要處理。
◆文檔的保存,程序根據文檔對象樹生成一些數據,然後保存到文檔存儲系統,這一步可以看作對象序列化。
◆應用程序的開放性,提供二次開發的能力,提供類似VBA的功能
一個完整的功能不弱的文本編輯器結構是很復雜的,涉及到的問題非常廣泛,沒有數萬行的代碼是搞不定的,這些問題在本文是不可能一一列出來並進行討論,在此只好挑一些重點來說說。