.Net開發筆記(十七) 應用程式擴充套件

周見智發表於2013-09-30

在很多場合,我們需要在已有軟體程式上增加一些新的功能,幾乎所有原因是因為原有軟體功能不能滿足我們的需要,我們平時做的外掛就屬於這種情況,最常見的是VS IDE的外掛開發,網上老外寫的一篇關於外掛開發的文章,很詳細(網址)。如果我們要給一個已有軟體擴充套件新的功能,一般我們必須知道原有軟體提供給二次開發人員的介面,也就是說,如果原有軟體在設計的時候,壓根兒就沒有考慮到後續可能存在的二次開發,也不提供任何介面,那麼通常情況下,是很難在它的基礎上擴充套件出新功能的(除非是原有軟體開發者)。

還有一種可以擴充套件已有程式功能的方式,網址,利用windows訊息、windows hook技術,理論上可以給任何一個桌面應用程式擴充套件出新功能,而不需要任何介面,但是,這種方式很有侷限性,擴充套件出來的功能幾乎停留在作業系統級別上,比如UI外觀樣式等,並不能真正的去與已有軟體程式進行互動。老外這篇文章其實重點是在講Windows hooks和Windows Message。

這篇文章不是講怎麼去開發VS外掛,更不是談哪個具體軟體比如CAD、PROE的二次開發,我只是想將看似複雜的東西簡單化地解釋一下,看看“給已有軟體擴充套件新功能”到底是怎麼回事。以外掛為例:

首先,宿主程式和外掛之間一定要有互動的,不然的話,外掛是不會知道什麼時候該幹什麼事情;其次,宿主程式一定會傳遞某些資料資訊給外掛,否則你叫外掛拿什麼原材料幹活?最後,宿主程式一定是要有所準備的,什麼叫有所準備?也就是說,在開發宿主程式的時候,一定要為以後的功能擴充套件留有介面,所有外掛必須遵守這個介面給出的規範,知道應該在什麼時候跟外掛通訊,瞭解外掛的任何一個行為將會導致什麼樣的結果,並且作出相應的反應。綜上所述,給已有程式擴充套件新功能,關鍵還是在這個“已有程式”身上,如果一個程式出生的時候就沒想著將來別人要給自己增加功能,那你不用再想著去給它擴充套件功能了。也就是我文章剛開始說到的,並不是你可以在任何一個程式基礎上擴充套件新功能。

圖1

如上圖所示,宿主程式與外掛之間透過某一協議進行通訊,這個跟上一篇最後講到的“框架和客戶端程式碼之間的關係”很相似,你可以把宿主程式看做是框架,而外掛則是客戶端程式碼(參見上一篇文章圖6)。

圖2

如上圖,在宿主程式中應該提前設計好該在什麼時候與外掛通訊,以及給它傳遞對應資料資訊,接著返回互動結果。宿主程式應該考慮所有與外掛互動的地方和時間,然而外掛不一定處處都會有所反應,也就是說,一個宿主程式設計好100個與外掛互動的地方(外掛最多可以在這100個地方大做文章),但是你開發一個外掛時,根據具體需要,完全可以只響應其中的某幾個。

圖3

文章後面我附上一個簡單的畫圖Demo,實現簡單的畫板、儲存(預設可以儲存JPG圖片格式和PIC可編輯格式)等功能,然後自己又做了一個外掛,外掛主要新增了以下功能:

  • 增加一個“關於”選單,點選彈出關於對話方塊;
  • 已有畫板程式只能繪製圓形和正方形,增加了一個三角形圖形;
  • 將畫圖儲存成JPG格式時,在圖片上新增水印;
  • 增加一種全新的檔案格式(newpic格式),可以將畫圖儲存為newpic格式的檔案,這個有點類似photoshop的ico外掛,安裝後,PS可以將圖片儲存為ico格式。

整個專案原始碼分為以下三個部分:

  1. PluginDemo:宿主程式,在它的基礎上擴充套件新的功能;
  2. PluginHelper:擴充套件功能時必須遵守的規範(介面),隨宿主程式一起開發,通常就是我們常說的“二次開發包”,理論上應該還有二次開發說明文件之類的東西;
  3. Plugin:我自己開發的一個外掛。

正常情況下,1和2由已有軟體開發商提供,3由二次開發人員開發。

下面主要說明一下PluginHelper中的兩個介面,其餘的原始碼諸位可以自己下下來看看。

IPlugin介面:

 1     /// <summary>
 2     /// 外掛介面 所有外掛必須實現該介面
 3     /// </summary>
 4     public interface IPlugin
 5     {
 6         void ApplicationLoaded(PluginApplication pluginApplication); //應用載入後
 7         void FileSavingAsJPG(Bitmap bitmap,string filepath); //檔案儲存為JPG
 8         void FileSavingAsPIC(PluginApplication pluginApplication); //檔案儲存為PIC
 9         void BeforeSave(Dictionary<string,SaveFileHandler> extensions); //儲存檔案之前
10         void BeforeOpen(Dictionary<string,OpenFileHandler> extensions); //開啟檔案之前
11         void ApplicationExiting(); //應用退出時
12 }
View Code

如介面程式碼所示,在固定時候固定地方,宿主程式都會呼叫對應方法與外掛通訊。

IObject介面:

 1    /// <summary>
 2     /// 圖形介面 所有的圖形都必須實現該介面
 3     /// </summary>
 4     public interface IObject
 5     {
 6         int X
 7         {
 8             get;
 9             set;
10         }
11         int Y
12         {
13             get;
14             set;
15         }
16         void Draw(Graphics g);
17 }
View Code

所有新擴充套件圖形都必須實現該介面。

如果想要開發自己的外掛,只需要知道二次開發包(PluginHelper.dll),定義一個類實現IPlugin介面就行。

圖4

最後上幾張效果圖,沒外掛之前的宿主程式:

圖5

安裝外掛後的宿主程式:

圖6

如上圖所示,安裝外掛後,選單多了“關於”選單項,工具欄多了“三角形”按鈕,可以儲存另外一種“newpic”格式的檔案,另外,在儲存為JPG格式圖片時,已有軟體儲存圖片為:

圖7

安裝外掛後,儲存為JPG格式檔案如下:

圖8

如上圖,安裝外掛後,儲存的JPG圖有水印。

下載原始碼:https://files.cnblogs.com/xiaozhi_5638/PluginDemo.rar

將開發的外掛放在宿主程式的plugins目錄下,重啟宿主程式就可以。希望對各位有幫助!

相關文章