應用程序擴展


應用程序擴展

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

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

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

     首先,宿主程序和插件之間一定要有交互的,不然的話,插件是不會知道什么時候該干什么事情;其次,宿主程序一定會傳遞某些數據信息給插件,否則你叫插件拿什么原材料干活?最后,宿主程序一定是要有所准備的,什么叫有所准備?也就是說,在開發宿主程序的時候,一定要為以后的功能擴展留有接口,所有插件必須遵守這個接口給出的規范,知道應該在什么時候跟插件通訊,了解插件的任何一個行為將會導致什么樣的結果,並且作出相應的反應。綜上所述,給已有程序擴展新功能,關鍵還是在這個“已有程序”身上,如果一個程序出生的時候就沒想着將來別人要給自己增加功能,那你不用再想着去給它擴展功能了。也就是我文章剛開始說到的,並不是你可以在任何一個程序基礎上擴展新功能。

圖1

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

圖2

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

圖3

     文章后面我附上一個簡單的畫圖Demo,實現簡單的畫板、保存(默認可以保存JPG圖片格式和PIC可編輯格式)等功能,然后自己又做了一個插件,插件主要新增了以下功能:

1)增加一個“關於”菜單,點擊彈出關於對話框;

2)已有畫板程序只能繪制圓形和正方形,增加了一個三角形圖形;

3)將畫圖保存成JPG格式時,在圖片上添加水印;

4)增加一種全新的文件格式(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 }
復制代碼

如接口代碼所示,在固定時候固定地方,宿主程序都會調用對應方法與插件通信。

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 }
復制代碼

所有新擴展圖形都必須實現該接口。

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

圖4

最后上幾張效果圖,沒插件之前的宿主程序:

圖5

安裝插件后的宿主程序:

圖6

如上圖所示,安裝插件后,菜單多了“關於”菜單項,工具欄多了“三角形”按鈕,可以保存另外一種“newpic”格式的文件,另外,在保存為JPG格式圖片時,已有軟件保存圖片為:

圖7

安裝插件后,保存為JPG格式文件如下:

圖8

如上圖,安裝插件后,保存的JPG圖有水印。

下載源碼:http://files.cnblogs.com/xiaozhi_5638/PluginDemo.rar

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

 
 
 
標簽:  c#Winform


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM