適用于移動終端的GUI設(shè)計與實(shí)現(xiàn)
在常見的移動終端等小型手持式設(shè)備上,由于硬件條件等的限制,我們看到的用戶界面都非常簡單,幾乎看不到PC機(jī)上華麗美觀的GUI 支持。隨著硬件條件的提高,移動終端的嵌入式系統(tǒng)對輕量級GUI的需求會越來越迫切。
用戶界面是指計算機(jī)與其使用者之間的對話接口[1],它為用戶提供與應(yīng)用系統(tǒng)交互的可視化通道,同時為程序員提供了一種編程模式,即GUI負(fù)責(zé)系統(tǒng)的可視化界面的生成、管理以及系統(tǒng)與用戶之間的信息交互[2-3],而程序員只需專注于對實(shí)際應(yīng)用的分析。
1. GUI在移動終端中的作用
圖1顯示大部分移動終端軟件的系統(tǒng)架構(gòu),由圖可以清晰看出,GUI在移動終端系統(tǒng)中扮演著很重要的角色,它運(yùn)行在操作系統(tǒng)抽象層(OSAL)之上,為應(yīng)用程序提供基于消息機(jī)制的圖形用戶界面編程接口。GUI與其它一些應(yīng)用引擎一起為實(shí)現(xiàn)豐富的移動終端應(yīng)用而提供支持,從而將應(yīng)用程序的計算部分與界面分離開來,這樣就充分保證了根據(jù)不同需求快速定制出功能強(qiáng)大界面豐富的應(yīng)用程序界面。
圖1 移動終端軟件架構(gòu)
2. GUI層次結(jié)構(gòu)
從整體結(jié)構(gòu)上看GUI是分層設(shè)計的,其主要成分為層次結(jié)構(gòu)見圖2,它的主要組成部分是 :顯示驅(qū)動、GDI接口、消息隊(duì)列和窗口管理四部分。
圖2. GUI層次結(jié)構(gòu)
2.1 顯示驅(qū)動
顯示設(shè)備和打印設(shè)備一同組成圖形設(shè)備,圖形設(shè)備抽象層(GAL)定義了一組不依賴于任何特殊硬件的抽象接口,所有頂層的圖形操作都建立在抽象接口之上。而用于實(shí)現(xiàn)這一抽象接口的底層代碼類似操作系統(tǒng)中的驅(qū)動程序。
顯示設(shè)備驅(qū)動作為GUI最底層驅(qū)動,通過顯示設(shè)備驅(qū)動程序接口(DDI)給上層GDI函數(shù)一些基礎(chǔ)的功能和設(shè)施。可以看成是GDI的圖形驅(qū)動程序,并將底層圖形設(shè)備和上層接口分離開來。
DDI用GAL中的函數(shù)標(biāo)準(zhǔn)結(jié)構(gòu)表示,統(tǒng)一成標(biāo)準(zhǔn)的驅(qū)動接口結(jié)構(gòu),保證顯示對窗口透明。主要DDI函數(shù)包括:對顯示設(shè)備進(jìn)行初始化,管理顯示內(nèi)存使用和為上層GDI提供映射到物理地址空間以及諸如調(diào)色板等物理地址上的相關(guān)處理。
2.2 GDI接口
GUI系統(tǒng)的一個重要組成部分就是GDI,即圖形設(shè)備接口(Graphics Device Interface)。通過GDI,GUI程序就可以在計算機(jī)屏幕上,或者其他的顯示設(shè)備上進(jìn)行圖形輸出,包括基本繪圖和文本輸出。
GDI重要函數(shù)包括:圖形設(shè)備上下文管理、繪圖函數(shù)和使用GDI對象的函數(shù)
2.2.1圖形設(shè)備上下文管理函數(shù)[!--empirenews.page--]
要在圖形輸出設(shè)備上繪制圖形,在調(diào)用圖形輸出函數(shù)時,均要求指定經(jīng)初始化的圖形設(shè)備上下文(Device Context,DC),也稱作"設(shè)備環(huán)境"。設(shè)備上下文是連接應(yīng)用程序、設(shè)備驅(qū)動程序以及輸出設(shè)備的紐帶,見圖3。設(shè)備上下文包含許多屬性,當(dāng)需要修改這些屬性時,只需調(diào)用一個GDI函數(shù)修改設(shè)備上下文中屬性的參數(shù)。
圖3. 設(shè)備上下文
一個圖形設(shè)備上下文所代表的含義很復(fù)雜,它起碼應(yīng)該包含如下內(nèi)容[5]:
· 該設(shè)備上下文本所在設(shè)備信息(顯示模式、色彩深度、顯存布局等等);
· 該設(shè)備上下文所代表的窗口以及該窗口被其他窗口剪切的信息
· 該設(shè)備上下文的基本操作對象(筆、刷子、字體、位圖、區(qū)域等),及其上下文信息;
· 由程序設(shè)定的局部信息(繪圖屬性、映射關(guān)系和局部剪切域等)。
2.2.2 繪圖函數(shù)
設(shè)備上下文的屬性決定了有關(guān)繪圖函數(shù)如何工作的細(xì)節(jié)。通過繪圖函數(shù)應(yīng)用程序能夠方便地畫出直線、矩形、圓、橢圓和其它復(fù)雜圖形,而不需直接與具體的輸出設(shè)備打交道。
2.2.3使用GDI對象的函數(shù)
當(dāng)調(diào)用繪圖函數(shù)時,使用當(dāng)前設(shè)備上下文中選擇的GDI對象來進(jìn)行繪圖。GDI共有筆、刷子、字體、位圖、區(qū)域和邏輯調(diào)色板六個對象。
例如可以通過在CreatePen、 CreatePenIndirect或ExtCreatePen函數(shù)中指定這些特征來建立一個邏輯畫筆,這些函數(shù)傳回一個邏輯畫筆的句柄。要使用這個畫筆,就要用SelectObject將畫筆句柄選進(jìn)設(shè)備內(nèi)容。這樣,畫任何線都使用這個畫筆,然后可以取消設(shè)備內(nèi)容中的畫筆選擇,并清除畫筆對象。清除畫筆對象是必要的,因?yàn)楫嫻P定義占用了分配的內(nèi)存空間。
除了畫筆以外,GDI對象還用于建立填入封閉區(qū)域的畫刷、字體、位圖以及GDI的其它一些方面。
2.3 消息隊(duì)列
移動終端產(chǎn)生的消息主要包括:按鍵事件消息、協(xié)議棧消息及自定義消息等。按鍵一般有12個標(biāo)準(zhǔn)電話按鍵、左右2個軟鍵、5個導(dǎo)航鍵(上、下、左、右、中) 、撥號鍵和掛機(jī)鍵,由此可產(chǎn)生對應(yīng)的短按鍵及長按鍵消息。按鍵的按下及釋放產(chǎn)生按鍵事件,對比鍵碼表對按鍵事件進(jìn)行解碼,獲取正確的按鍵消息。按鍵消息經(jīng)消息過濾后送往當(dāng)前焦點(diǎn)窗口。GSM 協(xié)議棧消息是由手機(jī)平臺產(chǎn)生的送往消息隊(duì)列的協(xié)議棧消息,主要是網(wǎng)絡(luò)事件及手機(jī)狀態(tài)的響應(yīng)消息,包括所有對SIM卡、網(wǎng)絡(luò)狀態(tài)、通話、短消息等的響應(yīng)消息。協(xié)議棧消息需傳送到賦于系統(tǒng)窗口屬性的窗口,但窗口并不需要對每一項(xiàng)協(xié)議棧消息進(jìn)行處理,只依據(jù)窗口函數(shù)的具體屬性定義進(jìn)行消息響應(yīng)。
GUI采用消息驅(qū)動機(jī)制,把上面這些消息收集在一個消息隊(duì)列中,然后將這些消息連同定時器和重畫消息一起放入應(yīng)用程序消息隊(duì)列中。應(yīng)用程序消息隊(duì)列是屬于各個應(yīng)用程序所有的先進(jìn)先出隊(duì)列。但是定時器消息和重畫消息保留在隊(duì)列中直到應(yīng)用程序處理完所有其它消息后才予以處理。GUI將屬于一個特定應(yīng)用程序的消息放入該應(yīng)用程序的消息隊(duì)列中,然后應(yīng)用程序讀取這些消息,并將它們發(fā)送給相應(yīng)的窗口函數(shù)。[!--empirenews.page--]
GUI將某些消息直接發(fā)送給應(yīng)用程序的窗口函數(shù),而不是將它們放入到應(yīng)用程序隊(duì)列中,這樣的消息稱為非排隊(duì)消息。通常,非排隊(duì)消息是那些僅影響該窗口的消息。雖然大多數(shù)消息都由GUI產(chǎn)生,但應(yīng)用程序也可以產(chǎn)生自己的消息并將其加入到應(yīng)用程序隊(duì)列中。
一旦應(yīng)用程序的主函數(shù)從隊(duì)列中獲取了消息,就可以將消息傳送給相關(guān)窗口的窗口函數(shù),并把消息的內(nèi)容作為參數(shù)傳遞過去,這樣,窗口函數(shù)就可以處理這個消息,完成相應(yīng)的工作。當(dāng)窗口函數(shù)返回后,GUI將控制權(quán)返回給主函數(shù)。主函數(shù)可以再從隊(duì)列中取出下一消息進(jìn)行處理。
2.4 窗口管理
窗口是終端應(yīng)用程序的主要輸入輸出設(shè)備。應(yīng)用程序只有通過窗口才能訪問顯示設(shè)備。窗口由標(biāo)題條、菜單條、滾動條、邊框以及在顯示設(shè)備上的矩形框里出現(xiàn)的其它特性組成。當(dāng)創(chuàng)建窗口時,可為窗口指定所要求的特性,然后GUI畫出此窗口并管理它。
雖然應(yīng)用程序創(chuàng)建了某一窗口,并且從技術(shù)上來說可以獨(dú)占它,但該窗口的管理實(shí)際上是由應(yīng)用程序與GUI相互協(xié)作來實(shí)現(xiàn)的。GUI管理窗口的位置和顯示方式,并管理窗口的標(biāo)準(zhǔn)特性,如邊框、標(biāo)題等,同時完成許多由用戶初始化并直接影響窗口的任務(wù)。而應(yīng)用程序則管理窗口的其它所有工作,特別是負(fù)責(zé)管理窗口的“客戶區(qū)”(窗口邊框以內(nèi)的區(qū)域)。應(yīng)用程序可完全控制屬于自己的窗口客戶區(qū)的顯示。
為管理這一協(xié)作任務(wù),GUI告知每個窗口其變化可能要受到影響。因此,每個窗口必須具有相應(yīng)的“窗口函數(shù)”,用于接收窗口管理消息。窗口管理消息既可指定該函數(shù)要執(zhí)行的動作,也可請求該窗口函數(shù)返回信息。
窗口函數(shù)作為窗口最重要的基本屬性,處理所有傳送到本窗口的消息。窗口的表現(xiàn)及行為特征是由窗口函數(shù)定義的對消息的處理所決定的。在正常情況下,具體的窗口函數(shù)只處理部分指定的消息,而正是這部分特定消息的處理決定了各個窗口的不同特性。通過調(diào)用窗口函數(shù),將消息參數(shù)傳遞到所指定的窗口函數(shù),由窗口函數(shù)依據(jù)消息所攜帶的消息參數(shù)進(jìn)行判斷處理。對絕大部分消息只需將其送往缺省窗口函數(shù)進(jìn)行處理。缺省窗口函數(shù)集成了標(biāo)準(zhǔn)窗口函數(shù)對消息的標(biāo)準(zhǔn)處理,是對所有窗口函數(shù)的一個共性集合窗口管理收集所有的輸入信息,然后把這些輸入信息以消息的形式送往合適的窗口。這些消息的執(zhí)行結(jié)果又可能產(chǎn)生新的消息,新消息的傳送仍由窗口管理負(fù)責(zé)。窗口管理通過調(diào)用窗口函數(shù),向窗口函數(shù)傳遞消息參數(shù),把消息送到目的窗口。在移動終端中,采用消息分派技術(shù)將協(xié)議棧消息依次發(fā)往所有具有系統(tǒng)屬性的窗口。通過窗口樹表將非協(xié)議棧消息送往所獲取的當(dāng)前焦點(diǎn)窗口。
3. GUI調(diào)用流程
下面通過一個具體例子分析GUI函數(shù)調(diào)用流程:移動終端的窗口系統(tǒng)初始化時首先要創(chuàng)建一個菜單,在注冊菜單窗口類時將菜單序號圖片全部按順序讀入內(nèi)存,這就需要GDI用畫刷對象來進(jìn)行矩形填充,下圖清晰的顯示了GUI在注冊這個窗口類時各層調(diào)用的流程。
圖4. GUI調(diào)用流程
4. 結(jié)語
GUI系統(tǒng)是一項(xiàng)復(fù)雜的軟件工程,本文設(shè)計和實(shí)現(xiàn)的GUI占用資源少、可配置,特別適用于移動終端。它給終端上層應(yīng)用提供了一個清晰的圖形界面。同時,在將它用于多種終端平臺時還要盡可能考慮它的可擴(kuò)展性、兼容性、可移植性等屬性。