ICommand接口是插件協議之一,繼承該接口的類都可以成爲命令。即點擊一下執行,不主動與宿主發生鼠標和鍵盤交互。該接口包含的重要成員如下表所示。
序號 |
名稱 |
類型 |
描述 |
1 |
Bitmap |
Int |
命令上顯示的圖標 |
2 |
Caption |
String |
命令上顯示的文字 |
3 |
Checked |
Bool |
命令是否處於選中狀態 |
4 |
Enabled |
Bool |
命令當前是否可用 |
5 |
OnClick |
函數 |
點擊命令時,觸發執行的函數 |
6 |
OnCreate |
函數 |
創建該命令時,調用的函數 |
7 |
Tooltip |
String |
鼠標放到命令上要顯示的文字 |
這些屬性和函數的名字都比較容易理解,一看就知道其作用。如果我們自己繼承ICommand實現一個彈出當前地圖包含幾個圖層的命令,命名爲LayerCountCommand。那麼只要在OnClick函數中,獲取OnCreate函數傳進來的宿主對象,從宿主對象中獲取當前加載的地圖,進而獲取其包含的幾個圖層,使用消息對話框彈出即可。
我們實現命令時候,只需要關注宿主對象就可以了,和其他Command不會發生直接關聯。如果需要和其他Command關聯,那麼這些關聯都通過宿主進行。例如我們剛纔實現的LayerCountCommand在地圖圖層爲0的時候,其處於不可用的狀態,也就是 Enabled屬性等於False。按照正常思維的話,我們會在OpenMapCommand裏面,判斷一下當前圖層個數是否爲0,從而設置設置LayerCountCommand實例的Enabled屬性。那RemoveLayerCommand、AddLayerCommand、NewMapCommand等怎麼辦呢?難道每個命令裏面都要判斷LayerCountCommand是都可用?
當然不會是這樣,我們會爲宿主添加MapChanged和LayersChanged事件,無論用OpenMapCommand還是其他地方,在系統中打開一個新地圖後,宿主對象就會觸發MapChanged事件。而我們實現的LayerCountCommand會監測該事件,當該事件觸發後,LayerCountCommand會判斷當前地圖有幾個圖層,從而設置自己是否是可用。
這樣LayerCountCommand只關係宿主的信息,間接的和OpenMapCommand產生了關聯。而LayerCountCommand自己可以決定自己是否可用,這就形成了高內聚,低耦合的設計。
ITool接口也是插件協議之一,實現該接口的類我們成爲工具,這些工具是可以和地圖顯示控件進行鼠標、鍵盤交互的。該接口包含的重要成員如下表所示。
序號 |
名稱 |
類型 |
描述 |
1 |
Cursor |
Int |
鼠標在地圖顯示控件上的樣式 |
2 |
Deactivate |
函數 |
工具失活的時候觸發的函數 |
3 |
OnMouseDown |
函數 |
鼠標按下執行的函數 |
4 |
OnMouseMove |
函數 |
鼠標移動執行的函數 |
5 |
OnMouseUp |
函數 |
鼠標彈起執行的函數 |
6 |
OnDblClick |
函數 |
鼠標雙擊地圖顯示控件執行的函數 |
7 |
OnKeyDown |
函數 |
鍵盤按鍵按下執行的函數 |
8 |
OnKeyUp |
函數 |
鍵盤按鍵彈起執行的函數 |
每個宿主對象都有CurrentTool屬性,如果點擊MapZoomInTool工具,那麼該宿主的CurrentTool就是該工具了。當鼠標在宿主對象上按下的時候,會自動調用宿主對象CurrentTool屬性值的OnMouseDown,也就是MapZoomInTool工具的OnMouseDown函數。當鼠標在宿主對象上移動的時候,會自動調用MapZoomInTool的OnMouseMove函數。其他動作一次類推,並且宿主對象讀取CurrentTool的Cursor作爲當前的鼠標樣式。
要做一個放大工具,需要考慮拉框放大、點擊放大等。但有了宿主程序,就可以把這些代碼完整的封裝到MapZoomInTool類中。而實現地圖縮小功能MapZoomOutTool以及地圖平移的MapPanTool,完全不需要知道其他工具的存在,也不關心其他Tool都做了什麼。
在ArcMap中,地圖放大、地圖縮小、地圖平移、地圖全圖地圖即放大、地方即縮小、上一視圖和下一視圖這幾個Tool和Command關係非常密切。如下圖所示。
但通過這種插件式架構,他們不光代碼之間無直接聯繫,而且還可以做到隨意組合使用。例如我們開發的系統可以使用放大、縮小和平移三個工具,也可以加上全圖,或者再加上其他工具,都可以正常運行。這種模式非常值得我們思考和借鑑。
3、ArcObjects SDK已經實現了哪些Command和Tool
AO中實現了二三百個命令和工具,我們常用的大概有幾十個。可以在幫助中通過查看ICommand接口,查看到底有哪些實現。
也可以通過ArcMap查找,出現在ArcMap工具條上的按鈕,大部分都能在此找到對應的類。
ArcMap就是通過這種插件式架構把各種Command和Tool組合起來的,而這些Comamnd和Tool的背後是一個個功能點。不光使得ArcMap可以持續集成那麼多功能,甚至可以開放接口,讓開發人員直接在ArcMap上擴展。
那這種模式是不是可以借鑑到我們的軟件開發中?答案是肯定的,下面我們就來設計自己的App-Command框架。