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