第四個需求 更好的顯示測試項
最后寫的那一段測試代碼在哪里運行?這要記住放在那個主菜單項下,然后點擊這個主菜單才能看到。最好能直接顯示出來最后那個菜單項。
這個需求MainMenu就無法做到了,因為沒有地方記錄那個是最后插入的菜單項。
ActionList可以記錄最后插入的Action,讓菜單項關聯Action,應該就可以顯示最后插入的菜單項。獲得最后的Action,找到與之關聯的菜單項都不難,但怎么才能顯示這個菜單項?
看看MainMenu的幫助,沒有成員方法可以顯示子菜單。但運行程序的時候,鼠標點擊一下主菜單,會顯示子菜單。追蹤一下這段代碼,應該有所發現。
很遺憾,TMenu很多行為是Windows控制的,沒能找到顯示子菜單的代碼。上網搜了搜,大富翁論壇的離線數據中也搜了搜,果然也沒有發現什么可行方法。
不過既然是Windows控制的,也許可以通過發送消息觸發顯示子菜單的代碼。打開Spy++,看一下鼠標點擊菜單時的消息,就是一個左鍵點擊的消息。這個消息要帶鼠標的坐標,也就是說要知道菜單項的位置信息。想想就覺得麻煩,還是知難而退,另辟蹊徑吧。
有的軟件有功能樹,用來顯示全部功能,用TreeView結合ActionList也許可以滿足需求。TreeView不能在設計時與Action關聯,需要在運行時遍歷ActionList,把每個Action加入到TreeView中,Category作為一級節點,Action作為二級節點,Caption作為節點的Text,指針作為節點的Data。然后在Click事件中把Data轉成Action執行。
現在測試代碼的步驟變為:打開測試工程,打開相關窗體,打開ActionList編輯器,新建一個Action,雙擊Action,在Execute事件中添加代碼,然后編譯運行程序,點擊TreeView節點,觀看代碼的作用。
需求解決了!
索性走的更遠一些。1、類似ActionList轉TreeView,MainMenu也根據ActionList在運行時自動建立。2、測試窗體顯示的時候遍歷TreeView,找到最后Action對應的節點,突出顯示出來,讓測試工作更簡化。3、節點樣式都一樣,看著不方便,根據節點的Index顯示過渡色。4、給TreeView增加一個排序功能,方便人工檢索。
完美!?
這里還可以總結出一些解決疑問方法:1、看幫助。2、看組件的源代碼。3、上網或者在離線數據中搜索解決方案。4、參考類似軟件。
第五個需求 代碼復用
按照最新的方案改好了一個窗體,再改另一個窗體時又出現了新問題:顯示測試項的那些代碼是每個窗體都需要,復制到每個窗體中肯定不是好方法。初學Delphi的時候有過慘痛的教訓,同樣的代碼用一次復制一次,占用空間不說,以后要改進代碼的時候,工作量那叫大!
公共函數!
把相同的代碼做成公共函數,放在公共的單元中,在每個窗體中引用這個單元,調用公共函數。是一種解決方法,但不夠好,調用公共函數的代碼也是重復的,添加MainMenu和TreeView的工作同樣是重復的。
類繼承!
把重復使用的代碼和組件提取到一個父窗體中,其他實際寫測試代碼的子窗體都從父窗體繼承。窗體也是類,只不過附加了資源文件,也可以使用繼承機制。
創建子窗體時節省了大量工作,只需從父窗體繼承,上面的組件就放置好了,父窗體的成員方法也可以直接調用。優化或者添加公共功能時只需修改父窗體。編譯后的程序尺寸也減少了。真是好處多多!
有一點需要注意,父窗體的imageList中不要放圖片,否則子窗體會復制一份圖片資源,讓子窗體的體積變大。看來繼承機制不是那么徹底。解決方法也簡單,運行時加載圖片就好。
只是,以前創建的窗體不易改造,走捷徑就要修改dfm文件。
重復輸入代碼,重復放置組件,重復設置屬性,只要是重復的工作都應該仔細考慮效率問題。重復輸入代碼,可以考慮公共函數和類繼承。重復放置組件可以考慮窗體繼承和DataModule、Frame。重復設置屬性可以考慮存儲到ini文件和注冊表。整個程序的復用可以考慮動態鏈接庫、COM+等。代碼復用不僅可以一次做功多處使用,還方便日后升級和替換。
還不夠?!
這里有一點需要注意:父窗體不用實例化,更不要放在第一個實例化,否則父窗體會成為主窗體。
第六個需求 窗體之間導航
窗體不止一個時,就要考慮窗體之間如何導航。一般程序開始只顯示主窗體,需要顯示其他的窗體時,再通過一個Action顯示該窗體。
在采用繼承方式前,每個窗體都要增加顯示其他窗體的Action。采用了繼承方式后,可以在父窗體中統一添加Action,新增一個窗體就新增一個Action,這樣每個子窗體之間都可以相互導航。
工作量不大,可以滿足需求。但實際測試過程中,多數情況下需要多次修改代碼、編譯、測試。每次都先顯示主窗體,再打開子窗體,再測試代碼,然后再關閉子窗體,再關閉主窗體,才完成一次測試,測試步驟有點繁瑣!
當然可以在測試代碼后,在IDE中用Ctrl+F2重置程序,但這樣會忽略之后的異常,也無法保存窗體信息,還節省不了多少工作。不好!
在每次編譯前,在工程選項中把要測試的窗體放在第一位,運行的時候就直接顯示該窗體。這實際就是把這個窗體變成主窗體,也有點繁瑣,不好,但指明了方向!
每次運行時,直接顯示最后修改的窗體,效率最高。這就是目標!
看了看MainForm的幫助,Application對象創建的第一個窗體就是主窗體。根據窗體文件的保存時間,時間最靠后的就是最后修改的窗體,第一個創建這個窗體就能完成任務。但所有窗體創建前是無法遍歷的,顯然行不通。
主窗體不能改,但是可以不自動顯示,而顯示其他窗體。Screen對象中保存著所有自動創建的窗體,遍歷所有窗體,通過運行時信息(RTTI)獲得窗體文件名,找到最后修改的窗體,顯示。完成!
等等,高興早了。關閉窗體的時候無法關閉程序!
再看看MainForm的幫助,關閉主窗體才能結束程序。而現在主窗體并沒有顯示,無法關閉。所以要在關閉其他窗體的時候,再顯示主窗體,然后關閉主窗體。
當然,代碼只要寫到父窗體中就可以。
完成!
在寫遍歷所有窗體代碼時,聯想到也可以通過遍歷窗體自動創建顯示窗體的Action,這樣又省了些工作。刪除一個窗體或增加一個窗體,都不用增加工作量。
完美!
浙公網安備 33010602011771號