Delphi Open Tools Api實例研究(二)

先行知識:Delphi/接口/DLL/COM(瞭解)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

難度:★★☆☆☆

 

    在開始之前先說一些題外話,這段時間一直很忙(馬上就要期末考試,而且最慘的是現在正在忙着準備即將到來的英語4級考試),所以自己也不知道這篇文章夠不夠份量。這篇文章的內容可能不是太多,但我還是抽時間把它寫了出來作爲我們的Delphi Open Tools Api實例研究(二)。另外我又發現了一些很不錯的關於這方面的資料和網站,一併在文後推薦給大家。

還記得上次的實例研究一嗎?我們展示了一個通過設計時組件包擴展delphi的例子。這次我們仍將做一個實際意義的delphi插件,菜單仍向上次一樣不變,不過這次的不是上次的向源文件插入一行代碼,而是向當前工程中添加一份開發文檔,並顯示在delphi的代碼編輯器中提供給開發者修改。(同時也保存在工程文件所在的目錄下)。然而這次與上次有一個很大的不同,也是這次最重點要說的地方是:我們將把這次的插件編譯成dll,而不是上次的組件包,這給創建自己更人性話的插件安裝程序(而不是叫用戶打開一個組件包來自己安裝)提供了機會。

先來看看這次的重點,我們建立了一個動態連接庫項目,並在加入的第一個單元文件內實現了我們的插件類。與上次不同的是,我們並不採用傳統的組件註冊過程Register,而是在單元類定義了一個類型爲TwizardInitProc的全局函數,並在項目文件中以WizardEntryPoint名稱導出(注意:必須使用這個名稱。)

exports

 InitNewMenu Name WizardEntryPoint;

 

下面是單元中的這個函數的原形和實現:

function InitNewMenu(const BorlandIDEServices:IBorlandIDEServices;

    RegisterProc:TWizardRegisterProc;var Terminate:TWizardTerminateProc):boolean;stdcall;

//RegisterProc:TWizardRegisterProc;參數用來創建嚮導,實際上這個初始化函數是用來創建一個dll

//形式的傳統Wizard這種時候就可以向RegisterProc參數傳遞一個實現了IOTAWizard的類實例,用以

//註冊嚮導,如同這樣RegisterProc(xxx.Create)。這裏我們只是使用這個函數作爲初始化dll的入口點

//所以並沒有使用這個函數,而是直接MyNTATest:=TNTATest.Create; 另外var Terminate參數用來釋放

//你在嚮導中使用的資源,你可以賦給它一個普通的過程類型如Terminate:=xxx; xxx爲一個procedure

//這樣ide在退出時,便會調用這個過程來釋放資源。注意這個函數必須以stdcall指示。

var

 svcs:IOTAServices;

begin

 result:=BorlandIDEServices <> nil;

 if result then

 begin

  svcs:=BorlandIDEServices as IOTAServices;

  //保存BorlandIDEServices指針

  ToolsAPI.BorlandIDEServices:=BorlandIDEServices;

  //設置dllhost application句柄

  Application.Handle:=svcs.GetParentHandle;

  MyNTATest:=TNTATest.Create;

 end;

end;

 

另外這次也使用了一個新的OTA接口,主要體現在菜單項的第一個事件內(我們完成了向當前工程中添加一份開發文檔的工作):IOTAActionServices,這是個相當有用的接口,在ide運行時由BorlandIDEServices實現,可以用來完成對IDE各種功能的調用。如:CloseFileOpenFileOpenProjectReloadFileSaveFile。這些功能的作用根據它們的名稱就能猜測出來。本來我還想使用IOTAProjectOptions接口來得到當前工程的相關信息和配置選項一併寫在文檔文件裏,但並沒有得到理想的結果,最多只得到了關於工程有哪些Options的字符串列表。我們有可能將在下次的文章中研究和IOTAProject相關的一系列接口。下面是產生文檔部分的代碼(對應於菜單項的第一個菜單事件):

 

procedure TNTATest.AddDocumentToPro(sender:TObject);

var

 templen,i,temppos:integer;

 DocumentFile:TextFile;

 ModuleCount: Integer;

 TempString,MoudleFilePath:String;

begin

 //請求IOTAModuleServices t接口

 Supports(BorlandIDEServices,IOTAModuleServices,MoudleService);

 ModuleCount:=MoudleService.ModuleCount;

 if ModuleCount<>0 then //沒有任何文件打開

 begin

  CurentMoudle:=MoudleService.CurrentModule;

  //獲得當前的文件名,我們可以用它得到項目路徑

  TempString:=CurentMoudle.FileName;

  //下面的部分用來分析字符串並取出項目的路徑//

  i:=pos('/',TempString);templen:=length(TempString);temppos:=i;

  while i<>0 do

  begin

   TempString:=RightStr(TempString,templen-i);

   i:=pos('/',TempString);templen:=length(TempString);temppos:=temppos+i;

  end;

  MoudleFilePath:=leftstr(CurentMoudle.FileName,temppos);

  ////////////////////////////////////////////

  if Supports(BorlandIDEServices,IOTAActionServices,ActionServices) then

  begin

   AssignFile(DocumentFile,MoudleFilePath+'DocumentFile.txt');

   Rewrite(DocumentFile);

   try

    writeln(DocumentFile,'項目名稱:');

    writeln(DocumentFile,'項目主程序名:');

    writeln(DocumentFile,'項目版本號:');

    writeln(DocumentFile,'項目描述:');

    writeln(DocumentFile,'項目組成員:');

    writeln(DocumentFile,'文檔建立時間:'+DateTimeToStr(now));

   finally

    CloseFile(DocumentFile);

   end;

   //注意,我們用到了IOTAActionServicesOpenFile方法來打開剛纔保存的文檔

   ActionServices.OpenFile(MoudleFilePath+'DocumentFile.txt');

  end;

 end

 else

  messagebox(IDEHandle,'There isn''''t Active Project.','DocCreator',MB_ICONWARNING);

end;

 

其餘的代碼(如向IDE添加菜單等和上次的類似),在這裏我們就省略不寫出來了,你可以參看上一篇文章(連接: http://www.csdn.net/develop/read_article.asp?id=21725 ),也可以給我來信得到代碼(地址和上一次的一樣)。最後當我們完成代碼編寫時,我們就可以將它編譯成dll文件。現在來看看我們怎麼來安裝我們的插件:首先退出delphi,打開註冊表,在HKEY_CURRENT_USER/Software/Borland/Delphi/7.0/Experts鍵下新建立一個字符串類型的值,名稱爲我們的插件的名稱,值爲我們編譯得到的dll的路徑。現在重新啓動delphi,怎麼樣,插件開始工作了吧。有了這個辦法後相信我們可以很容易的爲我們的插件創建安裝程序和反安裝程序(無非就是簡單的操作註冊表而已,當你再次推出delphi,並在註冊表中刪除剛纔建立的值,重啓delphi會發現插件已經卸載了),使其變的對用戶更友好,也可以更加方便我們的發佈。最後再做一點說明:關於調試dll插件的說明,我建議不要在編碼過程中返太多的錯誤(指運行時的),你會發現你會爲調式插件而不得不一次次的啓動、關閉delphi,這是一件相當煩人的事情(把我害慘了),我建議你可以先把插件作爲上一次的組件包形式進行測試和調式,這樣不用重啓delphi,當調式成功後再改爲dll形式的。另外這次的插件依然以delphi7爲基礎,在低版本的delphi中可能會有錯誤。最後說明的是,這個插件可能會使delphi在退出的時候產生一個AV錯誤,我暫時還沒有解決這個問題(希望高人指教),雖然我使用了string類型,但我也的確引用了sharemem單元。我也嘗試在Terminate參數中向其賦一個退出釋放資源的函數,但問題依舊。

在文章的最後我向大家推薦一些我最近發現的一些關於OTA的相當不錯的網站和資料:

http://www.gexperts.org/opentools/  在這裏你將會得到一份OTAFAQ,相當不錯。

http://www.tempest-sw.com/opentools/  一些老版本的OTA資料

http://home.quicknet.nl/qn/prive/rapp/delphi/delphi.html  OTA部分接口的相關資料和例子

http://www.frasersoft.net/program/  delphiOTA幫助補丁(非官方),但相當不全

發佈了42 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章