|
29.1 關於桌面
IBM PC 在 1995 年正式進入視窗多工作業系統的時代,即 MS. WINDOWS 95,
而之前的視窗系統是 DOS 環境下的 WINDOS 3.1。
工作站的視窗系統比 IBM PC 早很多年,這是因為 CPU 的效能和硬體比較高階,讓工作站率先進入視窗多工作業系統的時代。
蘋果電腦的視窗多工作業系統雖然也出現得早,卻因為 CPU 效能的關係,效率並不是很好。
INTEL PENTIUM 的出現以及記憶體的價格下滑,讓廉價的 IBM PC 的執行效能逐漸逼近工作站,也因此更適合視窗作業系統的運作。
視窗作業系統的桌面提供一個可以讓作業系統和使用者互動的人機介面。
UNIX、LINUX、APPLE 和 MS.WINDOWS 都有提供風格不同的桌面,讓使用者操作作業系統。
筆者模仿 MS. WINDOWS 95 的桌面風格,寫了一個簡單的視窗系統。
雖然說簡單,卻有相當多的內容要去了解。
讀者如果跟不上的話,可能會陷入十里霧中,摸不著頭緒,也無法學到想學的東西。
所以請讀者務必跟上筆者的文字筆觸與程式思路。
|
|
|
29.2 桌面的構成
桌面的基本構成是工作區、工作列和滑鼠游標。
桌面畫面:
|
|
|
29.2.1 桌面工作區
工作區是視窗顯示的地方,所有的工作視窗都會顯示在工作區上,一個一個地疊在一起。
當沒有工作視窗的時候,工作區還是有一個山水風景的桌布,即工作區視窗。
工作區視窗可以發展成活動桌面,如 MS. WINDOWS 的活動桌面那樣,目前筆者只實現桌布的功能。
|
|
|
29.2.2 桌面工作列
工作列有開始按鍵、視窗列和時間顯示欄位。開始按鍵會啟動開始目錄,讓使用者選擇想要啟動的功能。
視窗列可以安置許多小視窗格,在工作區的每一個視窗都有一個相對應的視窗格,供使用者選取視窗。
|
|
|
29.2.3 桌面滑鼠
滑鼠是桌面上的重要的操作工具,透過滑鼠游標的移動,可以迅速且方便的使用桌面的功能。
滑鼠游標可以對桌面的任一物件發出左鍵事件,中鍵事件和右鍵事件。
有的事件可以由桌面任務直接處理,有的事件則是轉換成事件號碼並傳遞到視窗的事件緩衝區,讓視窗的任務處理。
|
|
|
29.3 桌面的視窗管理
視窗管理器將視窗分成四種視窗,工作區視窗、工作列視窗、目錄視窗和一般視窗。
依視窗佇列分,桌面的視窗管理器有二個視窗佇列,即目錄視窗佇列和一般視窗佇列,分別用來管理目錄視窗和一般視窗。
一般視窗又分系統視窗和應用程式視窗。
系統視窗包括控制台視窗群和時間顯示視窗,是桌面系統自己的視窗。
應用程式視窗則來自於應用程式任務的視窗結構。
這裡有一張桌面畫面,畫面中有 2 個視窗佇列,目錄視窗佇列和一般視窗佇列。
一般視窗佇列有 4 個視窗,目錄視窗佇列有 2 個視窗。有看出來嗎!
|
|
|
29.3.1 目錄視窗
目錄視窗比較特別,行為和其他視窗不一樣,滑鼠按到目錄視窗時就顯示,滑鼠沒有按到目錄視窗時就消失。
為了這樣的特性,筆者給目錄視窗一個獨立的佇列,方便管理。
當繪製桌面的時候,目錄視窗佇列的層次高於一般視窗佇列,最後才被繪製到桌面上。
目錄視窗佇列:
當滑鼠按了開始按鍵,啟動開始目錄,桌面上就會出現目錄視窗。
當滑鼠按了開始目錄的程式集,就會出現程式集的目錄視窗。
當滑鼠按了程式集視窗的應用程式的按鍵,該應用程式的視窗就會出現在工作區。
桌面開始目錄畫面:
|
|
|
29.3.2 一般視窗
在一般視窗佇列中,工作列視窗、工作區視窗和一般視窗是以佇列的方式鏈結在一起。
以工作列視窗為佇列頭,以工作區視窗為佇列尾,將所有一般視窗依層次的先後秩序放在佇列中間,這樣的排列方式是為了繪製桌面而有的安排。
繪置桌面時,從佇列尾的工作區開始繪製桌面,一直繪製到佇列頭的工作列為止,從底部往上畫。
桌面的視窗佇列:
當作業系統執行多個視窗應用程式,所有的視窗都會顯示在工作區上,同時工作列上也會出現對應的視窗格。
活動視窗的視窗外框標頭和視窗格都會呈現藍色,其餘非活動視窗的視窗外框標頭和視窗格都是呈現灰色。
桌面的工作視窗畫面:
畫面中有 4 個視窗,分別是 命令提示字元、計算機、拆炸彈和小蜜蜂。
|
|
|
29.4 視窗元件化
視窗必須元件化的目的是要讓視窗中的每一個物件都有專屬的元件面積和事件號碼。
當滑鼠移動的時候,桌面任務就會依照滑鼠移動後的位置,鎖定滑鼠目前所在的視窗、視窗元件表和視窗元件。
透過這樣的方式,視窗的管理就變得簡單而有系統。
SHELL 視窗:
一個視窗會有多少個元件呢?這個問題取決於使用者對視窗的設計。
一個視窗最少有三個元件表,外框元件表、標頭元件表、使用者元件表。
|
|
|
29.4.1 外框元件表
外框元件表有 8 個邊元件(EDGE),分別是上邊、下邊、下左邊、下右邊、右上邊、右邊、左上邊和左邊。
這 8 個邊構成一個完整的視窗外框。讀者可能會問,為什麼是這8個邊呢?
這是因為筆者用滑鼠去測試 WINDOWS XP 的視窗外框,發現滑鼠會改變屬性的地方有 8 個。
如圖所示,SHELL 視窗中,當滑鼠跑到上邊時,滑鼠游標就會改變成垂直游標。
|
|
|
29.4.2 標頭元件表
標頭元件表通常有 3 個元件,分別是最小化按鈕、最大化按鈕和視窗關閉按紐。
當按了最小化按鈕時,視窗就會從桌面上消失,只能工作列上的視窗格。
當按了視窗關閉按鈕時,視窗連同視窗格都就會消失。
|
|
|
29.4.3 使用者元件表
視窗內容可以安置使用者元件表。目前的設計只允許一個使用者元件表存在,
可以在使用者元件表中擺放字幕(CAPTION)、畫板(BOARD)、按鈕、文字盒等元件。
筆者把這些元件通稱為 FFC 元件。FFC 是 FORMOSA FOUNDATION CLASS 的簡寫。
|
|
|
29.4.3.1 命令提示字元
以 SHELL 視窗為例,在使用者元件表中,只有一個字幕元件。
|
|
|
29.4.3.2 計算機
以計算機視窗為例,使用者元件表中,有 17 個按鈕元件和 1 個文字盒元件。
|
|
|
29.4.3.3 拆炸彈
以拆炸彈視窗為例,使用者元件表中,有 27 個按鈕元件。
|
|
|
29.4.3.4 小蜜蜂
以小蜜蜂視窗為例,使用者元件表中,有 2 個按鈕元件和 1 個畫板元件。
視窗元件化是一個很重要的動作,透過元件表和元件的使用,我們可以實現很多視窗應用程式。
FFC 目前只支援這幾個元件,這些元件會在桌面視窗與元件一章中說明。
|
|
|
29.5 視窗訊息
視窗接受使用者的鍵盤輸入,也接收滑鼠訊息。整個桌面中只有一個視窗是活動視窗
,也只有這個活動視窗可以接受使用者的鍵盤和滑鼠訊息。視窗在建立時,也會建立鍵
盤資料和滑鼠資料的緩衝區,而視窗的任務就會讀取並處理視窗緩衝區資料。
視窗訊息傳遞流程圖:
|
|
|
29.5.1 鍵盤緩衝區的範例
命令提示字元是使用鍵盤緩衝區的應用程式。當鍵盤的按鍵信號由鍵盤驅動程式接收後,
就會存在於鍵盤驅動程式的緩衝區。桌面任務會檢查鍵盤緩衝區的狀況,讀取鍵
盤緩衝區資料,再將鍵盤資料送往活動視窗的鍵盤緩衝區,完成鍵盤資料的傳送。
SHELLTASK 會檢查視窗的鍵盤緩衝區,讀取並處理鍵盤緩衝區的資料,並顯示於字幕上。
於是,我們就可以看到 SHELL 視窗上資料的顯示。
|
|
|
29.5.2 事件緩衝區的範例
計算機是使用事件緩衝區的應用程式。當滑鼠的按鍵信號由滑鼠驅動程式接收後,
就會存在於滑鼠驅動程式的緩衝區。桌面任務會檢查滑鼠緩衝區的狀況,讀取滑鼠緩衝區資料,
再將滑鼠資料轉換成位置和按鍵資訊。滑鼠位置可以用來判斷目前滑鼠游標是在哪一個視窗的哪一個元件上面。
滑鼠按鍵則用來對該視窗或元件做動作。對視窗的動作是搬移視窗或改變視窗大小。
對元件的動作是將元件的事件號碼存入視窗的事件緩衝區,完成事件的傳遞工作。
計算機任務會檢查視窗的事件緩衝區,讀取並處理事件緩衝區的資料,並顯示於文字盒上。
於是,我們就可以看到計算機視窗上數字資料的顯示。
|
|
|
29.6 桌面任務
桌面任務接受滑鼠與鍵盤的訊息,繪製桌面視窗。
整個桌面都是由桌面任務繪製,所有的事件也都是由桌面任務傳遞,桌面任務是視窗作業系統最重要的任務。
|
|
|
29.6.1 桌面任務的建立
桌面任務是由根任務建立。
行號 | 說明 |
02 | 呼叫根任務的初始化函式。 |
03 | 建立桌面任務。桌面任務負責視窗系統的運作。 |
04~07 | 根任務的任務執行迴圈。 |
|
|
|
29.6.2 桌面任務的執行
桌面任務的有一個任務執行迴圈,執行桌面服務函式。
行號 | 說明 |
01 | 宣告任務的名稱字串。 |
03~05 | 桌面任務的初始化函式。 |
07~14 | 桌面任務的任務執行函式。 |
10~13 | 桌面任務的任務執行迴圈。 |
11 | 呼叫桌面服務函式,執行桌面的視窗系統。 |
12 | 呼叫任務切換。每當桌面服務函式執行過一次,就會呼叫任務切換函式,將 CPU 資源讓給別的任務使用。 |
|
|
|
29.6.3 桌面任務的工作
桌面任務的工作是由桌面任務服務函式執行。
桌面任務服務函式分成二個狀態機,桌面初始化狀態和桌面執行狀態。
|
|
|
29.6.3.1 桌面初始化狀態
桌面初始化狀態會啟動鍵盤滑鼠並繪製桌面。初始化完成後的桌面只有工作區視窗和工作列視窗,連滑鼠都還沒有。
行號 | 說明 |
06 | 呼叫鍵盤致能函式,打開鍵盤中斷與滑鼠中斷。 |
07 | 呼叫滑鼠致能函式,打開滑鼠資料。 |
08 | 繪製工作區視窗。 |
09 | 將工作區視窗記憶體更新到桌面工作區的顯示記憶體。 |
10 | 繪製工作列視窗。 |
11 | 取得一小塊桌面顯示記憶體,用來繪製滑鼠游標。 |
12 | 設定桌面服務函式狀態機為桌面執行狀態。 |
|
|
|
29.6.3.2 桌面執行狀態
桌面執行狀態要處理的工作很多,主要包括傳遞鍵盤資料、處理滑鼠訊號與事件、繪製桌面。
另外,桌面的偵錯視窗和時間視窗也都是在桌面執行狀態中執行並繪製。
|
|
|
29.6.3.2.1 傳遞鍵盤資料
當鍵盤控制器緩衝區不為空緩衝區,將緩衝區資料讀出,並寫入活動視窗的鍵盤緩衝區。
行號 | 說明 |
06~08 | 當鍵盤緩衝區不為空緩衝區,將鍵盤資料讀出,並寫入活動視窗的鍵盤緩衝區。 |
07~08 | 呼叫視窗鍵盤緩衝區加入函式,將鍵盤資料寫入視窗緩衝區。 |
|
|
|
29.6.3.2.2 執行偵錯視窗
桌面有一個偵錯視窗,用來顯示偵錯訊息。
所有的任務都可以將字串訊息寫到偵錯視窗,用來偵錯任務本身。
偵錯視窗使用操控台,由桌面任務執行操控台,就是執行偵錯視窗。
行號 | 說明 |
07 | 呼叫操控台服務函式,執行偵錯視窗的操控台。 |
|
|
|
29.6.3.2.3 處理滑鼠資訊
桌面滑鼠服務函式會讀取滑鼠控制器緩衝區,並設定滑鼠資訊旗號為真,表示有收到滑鼠資訊。
從滑鼠訊息中取得滑鼠按鍵狀態和滑鼠移動資訊。
滑鼠移動資訊可以用來計算新的滑鼠位置,並鎖定滑鼠所在的視窗和視窗元件。
行號 | 說明 |
07 | 呼叫滑鼠服務函式,取得滑鼠資訊,包括滑鼠位置訊息和按鍵資訊。 |
08~09 | 當滑鼠存在旗號為真,且滑鼠髒旗號為真時,執行滑鼠鎖定程序。 |
10~17 | 將滑鼠資訊組合成 U32,並寫入視窗的滑鼠緩衝區。 |
18 | 呼叫滑鼠位置資訊取得函式,取得滑鼠所在的視窗、元件表、元件。 |
19~20 | 更新滑鼠目前視窗變數。 |
21~22 | 更新滑鼠目前元件表變數。 |
23~24 | 更新滑鼠目前元件變數。 |
25 | 更新滑鼠游標。這會使滑鼠產生滑動的效果。 |
26 | 清除滑鼠髒旗號。 |
|
|
|
29.6.3.2.4 處理滑鼠事件
當滑鼠按鍵按下,經過滑鼠資訊處理,會進入滑鼠事件處理程序。
有三種滑鼠事件處理程序,即滑鼠左鍵、滑鼠右鍵、滑鼠中鍵事件處理程序。
其中,滑鼠左鍵事件處理程序更是用來操作桌面和各種桌面視窗的應用,包括目錄視窗、工作列視窗、工作區視窗、一般視窗。
行號 | 說明 |
07~13 | 當滑鼠左鍵按下,進入滑鼠左鍵事件處理程序。 |
09 | 當滑鼠點到的視窗是開始目錄視窗,進入目錄視窗的滑鼠事件處理程序。 |
10 | 當滑鼠點到的視窗是工作列視窗,進入工作列視窗的滑鼠事件處理程序。 |
11 | 當滑鼠點到的視窗是工作區視窗,進入工作區視窗的滑鼠事件處理程序。 |
12 | 當滑鼠點到的視窗是一般視窗,進入一般視窗的滑鼠事件處理程序。 |
14 | 當滑鼠右鍵按下,進入滑鼠右鍵事件處理程序。 |
15 | 當滑鼠中鍵按下,進入滑鼠中鍵事件處理程序。 |
|
|
|
29.6.3.2.5 更新時間視窗
以每秒鐘的速度更新工作列的時間欄位和時間顯示視窗。
時間欄位的更新速度是每分鐘更新一次,時間顯示視窗則是每秒鐘更新一次。
行號 | 說明 |
07 | 當工作列的時間監視計時器的時間記數值為 0,執行工作列時間欄位與時間視窗的更新程序。 |
08 | 清除滑鼠游標,這是為了避免繪製新的時間值會破壞滑鼠游標。 |
09 | 取得根任務的時間值。 |
10 | 呼叫工作列時間更新函式,將取得的根任務時間值更新到工作列目前時間值。 |
11 | 呼叫工作列時間繪製函式,重新繪製時間欄位。 |
12 | 呼叫工作列時間視窗繪製函式,將新的時間值繪製到時間視窗的畫板元件。 |
13 | 從桌面上抓取一塊位元圖像,用來繪製新的滑鼠游標。 |
14 | 將滑鼠游標繪製到該位元圖像上。 |
15 | 將繪有滑鼠的位元圖像更新到桌面上,這時滑鼠游標就會出現在桌面上。 |
16 | 重新設定時間監視計時器的時間記數值為 1000 毫秒,就是下一次執行時間更新程序的時間間隔。 |
|
|
|
29.6.3.2.6 更新桌面工作區
以每秒鐘的速度更新桌面工作區。
什麼時候需要更新工作區呢?
答案是當視窗佇列變更或視窗佇列的非活動視窗內容變動時,就要啟動工作區視窗更新程序。
更新桌面工作區就是更新工作區視窗,做法是重新繪製工作區視窗和所有非活動視窗,並將工作區視窗記憶體更新到桌面顯示記憶體。
行號 | 說明 |
03~23 | 當桌面工作區的更新時間到,檢查並重繪工作區。 |
04~13 | 當視窗佇列改變旗號為真,執行工作區的重繪。 |
05 | 清除視窗佇列改變其號為否。 |
06 | 清除滑鼠游標。 |
07 | 繪製所有非活動視窗。 |
08 | 更新桌面工作區。 |
09 | 呼叫工作列的視窗列繪製函式,重繪視窗列。 |
10~12 | 繪製滑鼠。 |
14~21 | 當非活動視窗的內容有變化,執行工作區的重繪。 |
15 | 清除滑鼠游標。 |
16 | 繪製所有非活動視窗。 |
17 | 更新桌面工作區。 |
18~20 | 繪製滑鼠。 |
22 | 設定下一次更新桌面工作區的時間間隔。 |
|
|
|
29.6.3.2.7 更新活動視窗
活動視窗的更新速度是隨時更新,越快越好。
什麼時候需要活動視窗呢?
答案是當活動視窗的內容變動時,就要執行活動視窗的更新程序。
當活動視窗是工作列視窗或工作區視窗時,不處理更新活動視窗的動作,由別的地方處理。
如果活動視窗是第一次更新,必須經過二道手續,繪製活動視窗和更新活動視窗。
所謂的繪製活動視窗是在活動視窗記憶體上繪製活動視窗,更新活動視窗是將活動視窗的記憶體更新到桌面顯示記憶體,以顯示於桌面上。
如果活動視窗不是第一次更新,可以將有變更的元件,直接重繪在桌面顯示記憶體上,這樣的方式比較快速。
行號 | 說明 |
03 | 取得活動視窗。 |
04 | 當活動視窗為工作列視窗,直接略過。 |
05 | 當活動視窗為工作區視窗,直接略過。 |
06~23 | 當活動視窗不為工作列視窗或工作區視窗,執行活動視窗的檢查與更新程序。 |
07 | 進入核心關鍵區,因為更新活動視窗的過程不允許打岔。 |
08~22 | 當活動視窗內容有變更,執行活動視窗更新。 |
09 | 當活動視窗與滑鼠的面積區域重疊,清除滑鼠游標。 |
10~14 | 當活動視窗的直接繪製旗號為否,執行活動視窗繪製程序。 |
11 | 繪製活動視窗,這個動作是在活動視窗的計憶體上繪製視窗。 |
12 | 更新活動視窗,將活動視窗記憶體更新到桌面。 |
13 | 設定活動視窗的直接繪製旗號為真,表示允許在桌面上繪製活動視窗的內容,不需要再重繪整個視窗。 |
15 | 當活動視窗的直接繪製旗號為真,呼叫活動視窗內容桌面更新函式,直接在桌面上繪製活動視窗的內容。 |
16~20 | 當活動視窗與滑鼠的面積區域重疊,繪製滑鼠游標。 |
22 | 離開核心關鍵區。 |
|
|
|