摘要
本文討論了如何使用C#(C#培訓 )編寫一個所見即所得的設計器,分析了設計器的基本原理,可能遇到的技術問題,以及如何調用.Net框架來實現一個設計器。
版權聲明
本文是XDesigner軟件工作室撰寫,XDesigner軟件工作室擁有本文版權,轉載請注明出處,並保留本版權聲明。 http://www.mscto.com
前言
隨著計算機信息系統不斷深入發展,其系統結構要求越來越靈活,這種靈活性就是表現為程序的高度可配置性,可能應用程序的工作流程可以隨便改變,用戶界面也可以隨便改變,面對這種不斷增強的靈活,是不可能通過修改程序代碼來實現的,應用系統本身需要發生深刻變化,需要實現很強的擴展性和靈活性。此外z專門用於修改系統配置的外圍工具也是非常重要的。這些系統外圍定制工具很大一部分就是一些所見即所得的設計器。比如工作流編制工具,WinForm或WebForm界面設計器,而報表設計器也是典型的外圍定制工具。
總所周知,所見即所得的設計器是個相當復雜的程序,首先它需要復雜的圖形化用戶界面編程,包括圖形的繪制,鼠標鍵盤事件的處理,還要抗屏幕閃爍。其次還有它後台的數據維護處理,包括用戶界面和數據的同步,數據的組織安排,以及加載和保存文檔的處理。而且這些處理過程可以算是糾纏在一起,需要非常認真小心的分析設計,仔細編碼。
本文就是探討如何實現一個所見即所得的設計器。 關於本文,可以參考作者的另一篇文章-如何使用C#編寫文本編輯器。
設計器類型
設計器按照用戶界面和使用體驗,可以分為兩種模式,一種是基於直角坐標方式,另一種是基於流式排版方式。微軟的Visio就是典型的直角坐標方式,而Word則是流式排版方式,而VS.Net的WebForm窗體設計器就是這兩者的結合。
在直角坐標方式的設計器中,設計元素是使用XY坐標來在設計視圖中定位的,對於矩形元素一般指定它的左上角的位置來定位,設計者需要指定設計元素的位置,有時還要設置它的大小。對於線段需要指定兩個端點的XY坐標。設計者只要設置好了各個元素的位置大小就完成了設計文檔的基本結構,剩下的就是設置各個元素各自的內容了。
在流式排版設計器中,設計元素是不需要指定位置的,是根據一般根據從左到右,從上到下的排列原則填充到設計視圖中(但有時會變成其他排列原則)。設計元素的位置是動態計算的。流式設計器可能還要使用鍵盤直接輸入文本,需要顯示光標。流式排版設計器可以看作文字處理器。
這兩種設計器用戶界面和使用體驗不一樣,因此其程序處理的方式也不一樣,直角坐標設計器存在設計元素間相互覆蓋,這影響繪圖,此外還需要大量的鼠標拖拽操作,需要認真處理鼠標事件,但鍵盤事件處理得不多。而流式排版設計器中元素不會相互覆蓋,因此繪制起來方便點,鼠標事件處理不多,但鍵盤事件處理的多,此外還需要處理光標。但這兩種設計器它的文檔對象模型有比較大的類似性。 http://www.mscto.com
在本文中,以下只討論直角坐標方式的設計器。
設計器的功能
個人認為一個設計器應當實現的功能有
設計文檔的加載和保存,設計器可以將當前設計的內容保存到一個文檔中,這個文檔可以保存到文件中,也可保存到數據庫或某個服務器中。設計器可以加載文檔來完全重現上次的設計結果。
設計器可以快速准確的繪制文檔視圖,當視圖大小超過設計區域時,用戶界面應當出現滾動條來進行滾動操作。
當前有互換式設計體驗,用戶可以使用鼠標拖拽操作來改變元素的位置大小等布局設置,用戶改變了元素的布局或某些屬性時,必須立即更新文檔視圖,而且更新區域應當盡量小。
支持所見即所得的設計體驗,當設計器需要進行圖形輸出,例如輸出圖片或打印時,用戶在設計器中的設計視圖應當和輸出的圖形保持一致。
盡量減少屏幕閃爍。這需要繪制圖形或更新視圖時需要進行優化,盡快完成繪制操作。
若設計器需要進行擴展時,設計器應當提供足夠的擴展能力,開發人員可以在這個設計器的基礎上添加新的特性,使得設計器能顯示新樣式的文檔視圖。並且加載和保存文檔時也能處理新的文檔結構。
若需要可以支持VBA腳本,用戶可以編寫VBA腳本來控制設計器,包括其設計的文檔內容。
文檔對象模型
對於計算機程序,後台決定前台,而設計器的後台就是文檔對象模型。相信大家對文檔對象模型有所了解,我們在WEB頁面中使用JavaSCRIPT腳本時就是訪問了Html文檔對象模型,我們操作XML文檔就是訪問XML文檔對象模型。
W3C國際組織對文檔對象模型是這樣定義的(摘自 http://www.w3.org/DOM/ )
The Document Object Model is a platform- and language-neutral interface that will allow programs and scripts to dynamically Access and update the content, structure and style of documents. The document can be further processed and the results of that processing can be incorporated back into the presented page. This is an overvIEw of DOM-related materials here at W3C and around the web.
以我個人的英文水平翻譯如下
文檔對象模型是一種語言中立的接口或平台,程序或腳本能利用它來訪問和更新結構化的文檔。這些文檔可以被進一步的處理,處理結果可以組成一個有效頁面。這是W3C對web上的對文檔對象模型原理的一般看法。
我個人認為,對於編程,文檔對象模型其主要內容就是,面對比較復雜的文檔,使用面向對象的編程思想,使用一個個程序世界中的對象來映射文檔中的每一個特定的部分。加載文檔時,可以解析文檔,並把其表示的內容映射為一個個對象,此時應用程序可以修改這些對象的數據,當保存文檔時,可以將這些對象數據組織起來按照特定的格式保存到文檔中。這樣程序就通過訪問文檔對象來訪問文檔,也可以修改文檔對象來修改文檔,如此實現了對復雜文檔的處理。文檔對象模型是處理復雜文檔的標准操作模式。
設計器處理的是復雜的文檔,因此也需要使用文檔對象模型。文檔對象模型可分為三大部分:文檔基本元素,文檔對象和各種類型的從文檔基本元素派生出的文檔元素。
文檔基本元素是整個文檔對象模型的最基礎的對象(就像Object類型是.Net對象集團的基礎一樣),它定義了文檔元素的通用接口,一般定義為抽象類,類型名稱可以為DesignElement 。 http://www.mscto.com
文檔對象是文檔對象模型的頂級對象,它包含了整個文檔的內容,其類型名稱可以為 DesignDocument 。
各種類型的文檔元素,它是派生自文檔基本元素類型,用於描述文檔中各種實際存在的元素。其中可以定義一種文檔元素,它們可以容納其他的文檔元素,這些元素就是容器元素。實際上文檔對象就是最大的容器元素。由於文檔對象模型中存在容器元素,因此所有的對象都組成一個樹狀結構,稱為文檔對象樹,其中根節點就是文檔對象。各種文檔元素是文檔對象模型的活躍分子,擴展文檔對象模型大部分工作就是擴展這些文檔元素,擴展文檔元素需要擴展它們的兩個功能,一個是文檔的加載和保存,一個就是文檔本身保存的數據。
文檔對象模型可以和用戶界面相關,也可以不相關,例如XML文檔對象模型是無用戶界面的。設計器的文檔對象模型是和用戶界面相關的,對此,擴展設計文檔對象模型的文檔元素時還需要擴展它們的繪制圖形的能力以便設計器能繪制新型的文檔元素圖形。
對於設計文檔對象模型,其文檔基礎元素可以定義的內容有三個方面,文檔的加載和保存,用戶界面相關的接口,維護文檔對象樹的接口。
文檔的加載和保存
設計文檔可以保存為二進制文檔,純文本文檔和其他格式,在此推薦使用XML文檔格式。其好處是 http://www.mscto.com
設計文檔對象模型和XML文檔對象模型都屬於文檔對象模型,兩者原理和結構上都有著很大的相似性,設計文檔元素和XML文檔元素可以存在一一對應的關系。因此使用XML文檔加載和保存設計文檔對象是很自然的,實現起來比較簡單。
XML文檔是國際標准的文檔格式,非常開方,其他應用程序很容易利用設計器生成的文件,簡化了設計器和其他應用系統的數據接口。
已經存在標准的XML文檔解析器和XML文檔對象模型,因此不需自己處理XML文檔,只需調用標准庫加載XML文檔對象模型,然後按照一一對應的關系來生成設計文檔對象模型。
使用XML文檔有利於保持設計器的各個版本間的兼容性。只要XML文檔結構不發生大變化,低版本的設計器可以加載高版本的設計器生成的文檔,同樣高版本的設計器也很容易加載低版本的設計器生成的文檔。若使用二進制文件格式,則設計器需要編寫對於不同版本的設計文檔的預處理器,比較麻煩而且很難做到向上兼容。
在保存對象數據到XML文檔時,保存方式有兩種,保存到XML屬性和保存到XML元素。當指定某個XML元素用於保存對象數據時,若使用保存到XML屬性時,會對對象每一個屬性,將其數據保存到指定名稱的XML屬性中,而保存到XML元素時,會在當前的XML節點下新增一個指定名稱的XML子元素。然後將屬性值保存到XML子元素中。這兩種方式生成的XML片斷為
和
value1
value2
面對這兩種方式,我建議選擇第二種,其原因有
若保存到XML屬性,則當對象屬性比較多是,使用縮進方式輸出的XML文檔將比較寬,在查看是會出現橫向滾動條,不利於閱讀。而保存到XML元素時,XML文檔不會很寬,便於閱讀。
若多行文本保存到XML屬性,則一般不會以多行文本的方式保存,不利於閱讀。而保存到XML元素時,則保存的文本和實際的文本比較接近,便於閱讀。
若保存到XML屬性,則保存方式只能是一個屬性字符串,而保存到XML元素時則保存的方式很容易進行擴展。
雖然保存到XML屬性方式生成的XML文檔比保存為XML元素的方式要小,但XML文檔格式的設計目標是方便保存數據和交換數據,而不在乎文檔是否冗余,因此我們選擇保存方式時不必在乎XML文檔的大小。而且一般設計文檔的內容不很多,以目前計算機硬件條件無須在意XML文檔大小。
當設計器從XML文檔加載設計文檔時, 首先生成XML文檔對象樹, 然後根據一一對應的關系來生成設計文檔對象樹,此時需要從XML元素保存的信息來判斷該XML元素是對應於那種設計文檔元素,設計器可以從XML元素名稱來判斷,也可以從某個XML屬性來判斷,在此我使用XML元素名稱來判斷,首先是針對一個XML元素,獲得其名稱比獲得某個屬性值要方便,其次是XML名稱是必然存在的,肯定不為空,而XML屬性則可能由於某種原因而缺失,XML名稱比XML屬性要穩定。
基於上述的認識,當采用XML文檔作為保存方式時,設計基礎元素需要定義兩個虛函數,一個用於從XML文檔加載對象屬性數據,另一個要向XML文檔保存對象數據。而其他文檔元素對象則根據需要重載這兩個函數來實現自己的加載和保存對象屬性的操作,對於容器元素,還需要保存子元素數據到XML文檔和從XML文檔加載子元素。當然在實際應用中還要根據需要定義一些輔助成員來幫助加載和保存XML文檔。
設計器生成的XML文檔一般保存為文件形式,當然可以根據需要來保存的數據庫裡或者上傳到各種服務器中。若直接保存到數據庫中,則整個應用系統中所有的設計器編輯的都是同一個文檔版本,而且一旦保存便可立即應用。
用戶界面相關的接口
設計器需要繪制文檔視圖,則需要設計文檔對象模型提供支持。因此文檔基本元素需要定義兩類通用接口,一個是和繪制文檔相關的接口,一個是處理鼠標鍵盤事件相關的接口。 http://www.mscto.com
繪制文檔相關接口
大部分文檔元素需要在文檔視圖中繪制內容,因此它們需要重載繪制文檔的接口,這類接口主要有兩個函數,一個是計算元素大小的函數,一般命名為 RefreshSize , 一個是繪制元素的函數,一般命名為RefreshVIEw。
一般設計者指定元素的大小,元素本身不需要計算其大小,但某些元素可能是根據其內容自動設置大小,因此需要重載計算元素大小的函數RefreshSize來自動設置大小。自動設置大小可能只是設置元素的寬度或高度,也可能是同時設置其寬度和高度。同一個元素,可能在一種狀態下不會自動設置大小,而在另外一種狀態下需要自動設置大小。所有的這些操作都需要在RefreshSize函數中完成。
一般的設計元素都需要在文檔視圖中繪制內容,這時需要重載RefreshVIEw函數,這個函數參數包含了一個System.Drawing.Graphics對象,元素需要使用這個Graphics對象來繪制自己特定的內容,可能是繪制文本,圖片或其他圖形。 http://www.mscto.com
當所有的文檔元素都實現了繪制文檔相當的接口,則在設計器的調度下,一個完整的設計文檔視圖就繪制出來了。而擴展設計器時,若需要指定新顯示樣式的元素時,需要重載RefreshVIEw和RefreshSize函數來實現新的顯示樣式,此時擴展的設計器就能顯示新樣式的文檔視圖。
處理鼠標鍵盤事件相關接口
設計器中主要處理鼠標事件,文檔基礎元素可以定義一些處理鼠標事件的虛函數,名稱可以為 HandleMouseDown , HandleMouseMove 和 HandleMouseUp 。
為了方便文檔元素處理鼠標坐標,設計器在調用文檔元素的HandleMouse函數時,首先將鼠標光標坐標進行轉換,要將鼠標光標在視圖區域中的坐標轉換為文檔元素內部的相對坐標,即相對於元素左上角的相對坐標。
設計器要依靠鼠標事件來實現設計元素的拖拽操作以實現互換式設計體驗。關於鼠標拖拽操作典型的應用就是使用8個控制點來編輯元素邊界。當一個元素邊界是矩形時,會在元素的邊界矩形的四個角和四個邊的中點上分布8個控制點,當鼠標移動到這8個點時會修改鼠標光標樣式,當鼠標光標在某個控制點上時,用戶按下鼠標按鍵則開始進行鼠標拖拽操作,拖拽時會顯示一個虛線繪制的邊框,當松開鼠標按鍵則拖拽操作結束,此時設計器修改拖拽的元素的矩形邊界。 http://www.mscto.com
某些文檔元素並不進行標准的鼠標拖拽操作,例如對於容器元素,其內部的鼠標拖拽不移動對象而是畫出一個選擇矩形來選擇若干個子對象;對於表格元素,它的表格線上的鼠標拖拽操作是修改表格行的高度和表格列的寬度;而對於線段則是修改端點位置。
當用戶不小心按下鼠標按鍵,或只是選擇某個元素而並不想進行鼠標拖拽操作,此時可以使用一個參數 System.Windows.Forms.SystemInformation.DragSize 來判斷是否進行鼠標拖拽。當鼠標按鍵按下時,設計器就鎖定鼠標,若鼠標按鍵按下後鼠標移動距離超出了 DragSize 的范圍時,則表示用戶是想進行鼠標拖拽操作的,此時開始真正的鼠標拖拽操作。若鼠標按鍵從按下到松開時鼠標移動距離始終沒超出 DragSize 的范圍,則表示用戶沒有進行鼠標拖拽操作的意圖。這樣的判斷可以讓設計器容忍用戶的一些誤操作。
設計器還要處理鼠標雙擊事件處理,對於某些包含文本的元素,用戶雙擊該元素,則在設計視圖中顯示個文本輸入框來直接編輯對象的文本內容。可以定義一個接口 ILabelEditable , 當用戶雙擊某個元素,設計器發現該元素實現了 ILabelEditable 接口,則在設計視圖中動態的顯示一個文本輸入框,然後調用該接口的成員來直接編輯對象文本內容。
維護文檔對象樹
文檔基礎元素要定義不少接口來用於維護文檔對象樹。要定義 OwnerDocument 屬性來指定元素所在的文檔對象,要定義 Parent 屬性來指明元素的父節點,定義 Items 屬性來指明該元素的子元素列表。對於容器元素,還要維護它的子元素列表。
http://www.mscto.com
設計文檔對象作為文檔樹的根節點,擔負著維護整個對象樹的重任,包括文檔整體的加載保存,文檔整體的繪制,遍歷整個對象樹結構入口,還要為腳本提供接口。它是訪問文檔對象樹的入口點。
一些比較基礎的文檔元素類型
可以從文檔基礎元素上派生一些比較基礎的文檔元素類型。這些比較基礎的文檔元素類型可以包括
矩形元素基礎類型,類型名稱為DesignRectangleElement , 設計文檔中大部分元素的邊界是矩形,因此定義矩形元素基礎類型作為這些矩形類型的元素的共同基礎。矩形元素基礎類型實現了使用8個點的控制點來修改元素位置和大小的能力,鼠標在對象邊界只那的鼠標拖拽操作就可移動元素位置。此外還定義了內容和邊界之間的邊距信息。
線段類型,類型名稱為DesignLineElement, 設計文檔某些元素是以線段方式顯示的,因此定義線段類型作為這些元素類型的基礎類,線段類型定義了兩個端點的位置,線段的顯示樣式,標簽文檔等信息。此外還重載了鼠標事件,使得用戶可以使用鼠標拖拽線段的兩個端點來修改線段端點的坐標。此外還要重載命中操作,用於判斷某個坐標是否命中線段對象,若指定點距離線段的垂直距離小於某個參數,和點在線段某個端點上的拖拽點中則命中線段,否則沒命中。
容器元素類型,類型名稱為DesignElementContainer , 該元素可以包含若干個子元素,它是從DesignRectangleElement 派生的,因此它的邊界是矩形。鼠標在容器中的拖拽操作不是移動容器,而是動態繪制一個選擇矩形,當完成拖拽操作時,就根據這個選擇矩形來設置子元素的選中狀態。根據選擇矩形來選擇子元素有兩種方式,一種是,若子元素邊界和選擇矩形粘邊就被選中,另一種是,若子元素完全在選擇矩形內部時才被選中。容器元素在繪制子元素時就執行矩形覆蓋操作後再調用子元素的RefreshVIEw成員。
帶標題容器元素,類型名稱為 DesignCaptionContainer , 該元素派生自容器元素,可以包含若干個子元素,但它頂端有個標題欄,可以顯示文本,用戶使用鼠標拖拽這個標題欄可以修改元素的位置。此外它還實現了 ILabelEditable 接口,當用戶雙擊標題欄時可以直接編輯標題欄文本。
文本元素,類型名稱為DesignTextElement,很多文檔元素只是簡單的顯示文本內容,則定義文本元素作為這些簡單顯示文本內容的元素的共同基礎。它派生自DesignRectangleElement , 此外還實現了 ILabelEditable 接口用於直接編輯文本內容。此外還支持文本輸出角度控制,此時繪制文本時將以元素中心為原點旋轉任意角度進行繪制。文本元素繪制帶角度的文本時需要臨時修改圖形繪制對象Graphics的轉換矩陣來設置繪制角度。
增強文本元素,類型名稱為DesignTextElementExt , 該元素派生自DesignTextElement, 對文本輸出格式進行了強化,它支持行間距和字符間距,此外還進行了文本右邊緣的對齊操作。顯示對於大段文本時,尤其包含中文字符和英文字符,某些程序沒有進行文本右邊緣對齊操作。例如IE,記事本等,這是因為中文字符和英文字符寬度不一樣。每一行文本的內容寬度由於中英字符的個數不一樣,很容易導致文本寬度不一樣,因此當文本左邊緣對齊時,其右邊緣很可能是參差不齊的。但MS Word顯示大段文本時它的文本左右邊緣都是對齊的,它通過在顯示文本時插入額外的用戶難以察覺字符間距來修正文本顯示寬度。增強型文本元素就利用了這個原理來實現文本右邊緣對齊。
表格元素,類型名稱為DesignTableElement,表格元素是一種復雜的容器元素,它包含表格行(DesignTableRowElement),表格列(DesignTableColumnElemetn)和單元格(DesignTableCellElement)對象,其中單元格可以進行橫向合並和縱向合並。而表格包含的表格行和單元格也是容器元素,用戶不能直接修改單元格的大小位置,而只能調解表格行的高度和表格列的寬度來修改單元格的大小位置。單元格也是容器元素,因此單元格內可以放置若干個子元素。在很多情況下單元格只是顯示簡單的文本內容,因此單元格定義了一些用於顯示文本內容的屬性,此外實現了 ILabelEditable 接口來方便直接編輯單元格文本內容。
圖片元素,類型名稱為 DesignImageElement , 它是從DesignRectangleElement 派生的,用於簡單的顯示一個圖片。由於圖片對象(System.Drawing.Image)使用了未托管資源,因此圖片元素實現了 System.IDisposable 接口。
此外還定義了一些元素,這些元素可以模擬繪制Windows基礎控件,包括文本標簽,按鈕,單選框,復選框,文本框,列表,下列列表,組合框,進度條和窗體。可以根據這些元素來很容易的模擬出一個窗體設計器。
繪制文檔視圖
設計器的主要工作之一就是繪制文檔視圖。其繪制過程一般是 http://www.mscto.com
設計器控件重載它的OnPaint成員或綁定Paint事件。
當操作系統需要重新繪制設計器控件時會觸發它的Paint事件。
設計器獲得繪制圖形使用的System.Drawing.Graphics對象和一個表示繪制區域的剪切矩形ClipRectangle,然後將其作為參數調用文檔對象的RefreshVIEw函數。
文檔對象進行一個初始化工作,然後遍歷對象樹結構,找到所有和剪切矩形粘邊的文檔元素,調用它們的RefreshVIEw函數,讓各個元素繪制各自內容。 http://www.mscto.com
當所有工作完畢,則文檔視圖繪制完畢。
設計器繪制文檔是遇到一個難題就是閃爍,當用戶滾動視圖和更新視圖時,用戶界面很容易出現閃爍,過多的閃爍會比較嚴重的影響使用者的使用。關於閃爍的原理我曾經寫過一篇文章討論了一下(點擊查看)。由於設計文檔是比較復雜的文檔,繪制整個文檔視圖工作量大,繪制時間長,因此需要采用各種優化來減少繪制時間,減少閃爍。
對於閃爍有一個算是一勞永逸的辦法就是使用雙緩沖技術。在繪制圖形時,首先將圖形繪制到一個內存中的BMP圖片上,然後將這個BMP圖片繪制到用戶界面上。這種方法可以最大程度的減少閃爍,而且在.Net中使用雙緩沖也比較簡單。但我不大使用雙緩沖技術,有兩個原因
雙緩沖實際上增加了整個繪制文檔的工作量,延長了繪圖時間。當用戶滾動視圖時,會造成視圖很“沉重”的感覺,用戶界面響應遲鈍。
雙緩沖掩蓋了程序的不足之處。開發人員可以根據閃爍程度來判斷繪圖操作是否需要優化,以及優化效果。但雙緩沖消滅了閃爍,開發人員也就沒有優化繪圖操作的迫切需求,助長了開發人員的懶惰。程序繪制圖形時緩慢不堪,而很難從表面看出問題的可能原因。
其實可以這樣,設計器在開發時不使用雙緩沖,但發布時則使用雙緩沖。
由於設計器采用直角坐標方式,因此各個元素間存在相互覆蓋的關系,當存在大面積的覆蓋時,繪制文檔時必需要針對這種情況進行優化處理來提高繪制文檔的速度,減少計算機屏幕閃爍。針對覆蓋現象而進行優化時可以進行矩形覆蓋操作,對於矩形覆蓋操作,本人有另一篇文章對此進行了說明(點擊查看)。設計器繪制某個元素時,首先針對這個元素進行矩形覆蓋運算,將運算結果作為RefreshVIEw函數的某個參數來傳入,當文檔元素內容比較多時,可以根據這個矩形覆蓋運算結果來減少繪制量,提高繪制速度。
設計視圖還應提供縮放顯示功能,可以放大設計視圖來更清楚的顯示細節,可以縮小設計視圖來總體的把握整個文檔。GDI 有個轉換矩陣,可以很容易的實現設計視圖的縮放顯示。但此時所有的鼠標坐標數據都得進行相應的縮放處理。
設計視圖控件
設計視圖控件是設計器在用戶界面上的展示接口。它是一個標准的Windows控件,該控件派生自System.Windows.Form.UserControl。用戶使用鼠標和鍵盤在這個控件裡面編輯文檔,它重載了OnMouseDown , OnMouseMove 和 OnMouseUp 成員,對鼠標消息進行了一下包裝後供設計文檔對象使用。重載了OnPaint 成員來更新文檔視圖。重載了 OnDoubleClick 來進行試圖直接編輯文檔元素的文本內容。
當用戶設置某個元素為當前元素,則設計視圖控件將根據需要來進行滾動以便當前元素出現在可視區域中。若當前元素大小小於可視區域大小,則處理比較簡單,只要根據可視區域大小和元素在視圖中的位置就可計算滾動位置。若元素寬度或高度大於可視區域的寬度和高度,則需要進行額外的判斷,以避免滾動時發生跳躍。
鷹眼技術
一個好的設計器應當支持鷹眼技術,所謂鷹眼,通俗的講就是小地圖,它一般放置在程序界面的某個角落,它的面積不大,主要功能是讓人瞥上一眼就能大體了解整個文檔的結構,並能通過鼠標點擊快速的滾動文檔。關於鷹眼,本人寫過一個文章專門討論了它(點擊查看).
總結
使用方便的所見即所得的設計器是一個復雜的程序,需要豐富的相關開發經驗,它涉及到圖形化,文檔對象模型以及其他各種編程技術,是一個多種編程技術的有機混合,通常需要編寫數萬行的代碼才能實現。因此其技術門檻比較高,一般的小公司沒有能力完成,即使有些公司有實力開發,那也要花數月的時間,有可能影響公司正常的項目開發。但隨著各種信息系統越來越靈活,它們必須配備良好的設計器,若有一個使用方便功能強大的設計器,則處理這種系統配置是事半功倍的,因此很多開發人員都不得不面對開發設計器這個技術難題。