Delphi使用VB編寫的ActiveX控制元件全攻略 (轉)

gugu99發表於2007-08-17
Delphi使用VB編寫的ActiveX控制元件全攻略 (轉)[@more@]

使用VB全攻略

前言

  在最近幾周的工作裡,始終被一個頭疼的問題所困擾,那就是編寫的控制元件在Delphi環境下存在著諸多稀奇古怪的問題,幾經周折,終於在搜尋了幾乎全部的論壇、資料後,找到了針對不同Delphi版本發生的問題的解決辦法。

:namespace prefix = o ns = "urn:schemas--com::office" />

Delphi 5 莫名其妙的致命異常之一

  首先,我們來看看VB寫的ActiveX控制元件在Delphi 5下面的奇怪表現。

例如:我們用VB編寫了一個控制元件UserTest(為簡單起見,我們只匯出一個類即控制元件),一個屬性TestName,一個方法TestMethod。然後將其編譯成一個ActiveX控制元件,註冊並匯入Delphi5的開發環境(以上步驟如有未清楚之處,請查閱各類參考資料,肯定有標準答案),到目前為止,看來一切正常。

然後,我們習慣的把控制元件拖放到窗體上,調整大小,在屬性視窗中為屬性賦值,或者在程式碼中也是一樣,非常正常,好用的很。但是,下面問題來了,如果您興致勃勃的去了那個TestMethod,那麼您將得到一個古怪的異常 “Ole Error 800a01a9”,然後退出,而且非常不幸的是,您將無法跟蹤到這個異常,在Delphi中或是VB中都是,當然如果您對很在行的話,您可以跟著Delphi的視窗一步一步往下……

當我第一次碰到這個問題的時候,我幾乎是憤怒的,因為無論是MicroSoft或是Borland,對該錯誤都沒有任何解釋,也沒有任何可以查詢的資料。我只好跑到常去的幾個論壇,當然最主要的還是CSDN,在VB版和Delphi版中四處搜尋類似的問題,然後非常遺憾的是,只有類似的問題,而沒有答案,一個大客戶就用的這個開發工具,我在測試了幾乎所有上的開發工具和開發環境(包括桌面和)後,惟獨將Delphi忘記了。

剩下的兩天裡,我幾乎是滿世界亂跑,給所有的朋友打電話,詢問Delphi方面的高手是否知道這個情況,最後,我從上搜到了一個連結,可惜的是現在我忘記了那個連結的具體位置,但是我得到了一個近乎Magic的方法(發現者是這麼稱呼它的):

一個手工修改Delphi匯入ActiveX控制元件後產生的型別庫XXX_TLB.PAS(這裡XXX指的是控制元件的類名)的方法可以解決這一問題。舉例說明:

 

  有一個VB 寫的控制元件 UserControl1 ,在Delphi中匯入後產生兩個檔案,其中一個UserControl1_TLB.PAS 就是我們所要修改的檔案。

  在檔案中查詢 類似

 

FintF: _UserControl1;

Function GetControlInterface:_UserControl1;

property ControlInterface: _UserControl1 read GetControlInterface;

GetControlInterface;

以及

procedure TUserControl1.CreateControl;

  procedure  DoCreate;

  begin

  Finf:=IUnknown(Ole) as _UserControl1;

  End;

Begin

  If Finf=nil then DoCreate;

End;

Function TUserControl1.GetControl1Interface: _UserControl1;

Begin

  CreateControl;

  Result:=Finfl;

End;

請注意:這裡紅色標出的 _UserControl1 要 全部換成 _ UserControl1Disp,如果編譯不成功的話,請將編譯警告中報出的_UserControl1 全部換成 _UserControl1Disp,編譯即可,這樣在呼叫控制元件的方法時便不會出現上述的致命錯誤。

感謝這個偉大的發現,我只能這麼形容它,否則可能到現在我還要在這個圈子裡套不出來,或者就是使用另外的工具重新開發這個控制元件(我難以想象這個工作量會有多大,又或者它可能還會存在其他的相容性問題)。

Delphi 5 莫名其妙的致命異常之二

但是,Delphi並沒有在我繞開這個限制之後而放過我,很快,客戶那邊發現另一個麻煩的問題,在開發環境下,每次執行時關閉載有控制元件的窗體都會跳出一個異常錯誤,但是在編譯後的應用程式中則不會,雖然不會影響終端使用者的使用,但是這對開發人員來說是個不小的困擾,然後我用了上述例子去試,發現並不會發生這個問題。(我當時就瘋了,這很可能是程式碼中一些不相容的用法所致,在一天時間裡查詢上萬行程式碼是不是很正規是件極其恐怖的事情)我一氣之下,遮蔽了我的控制元件中所有的程式碼,只留下使用者介面本身,然後奇怪的事情發生了,我什麼程式碼都沒寫,但是載入我的控制元件還是會發生這個錯誤,這使我又喜又驚,喜的是這個問題和我的程式碼無關,這樣查詢起來會方便的多;驚的是隻是拖放幾個VB中的標準控制元件居然也會造成這種恐怖的錯誤,Delphi5和VB6之間的矛盾還真不是一般的深。接下來的2個小時裡,我不斷地刪除介面上的控制元件來測試到底是誰造成了這個致命的異常。

2個小時後,我舒了一口氣,問題找到了, 其根本問題是:

如果你在VB的使用者控制元件中使用類似Frame和PictureBox這樣的容器控制元件(其內部可以包含其他控制元件)時,那麼您將不可以在這些控制元件中新增Label、Line、Image這樣的windowLess控制元件(也就是無視窗控制元件,它們在執行時是VB實時畫出來的),否則您就會得到上面這樣的錯誤報告。

Delphi 6、7 隱蔽的ActiveX控制元件

  正是因為有了Delphi5下面的恐怖經歷,我發現還是很有必要在Delphi6和7下面測試是不是也存在同樣的問題(之前的版本因為使用者極少已無必要,Delphi8還沒正式出,也暫不在考慮之列)。結果是:……無論我載入多少次,我在ActiveX欄上始終沒有發現那個期待已久的小圖示。這樣的結果當然很滑稽,我連載入都做不到,更不要談什麼測試正常不正常了。

  同樣的,我搜尋各類論壇和網站,CSDN裡我也發現了更多的類似問題的提出者,但答案還是零,無奈之下,我只好對每個Delphi6、7中的選項進行調整……

  歷時3小時15分54秒後,我找到了這個該死的問題(請原諒我這麼稱呼它,我實在是忍無可忍)的原因,或者說是解決辦法,說起來其實很簡單。

現在請跟著我做:點選Tools選單->Environment Options->Type Library頁,我們應該發現一項:Ignore special CoClass Flags When Importing,選中它,然後再選中Can Create那一項,那麼現在,我們再嘗試去匯入那個可憐的ActiveX控制元件吧(這裡要注意,如果你已經匯入過一次,那麼請把產生的那兩個檔案 .dcr 和 .pas檔案刪除,否則將不會重新整理)。這次如果還是不能在ActiveX欄中發現那個控制元件的話,那麼只有致電Microsoft或是Borland,問問看什麼時候它們能結成親家,呵呵!

 

(另,在Delphi6和7中倒是沒有發現Delphi5中出現的上述錯誤)

 

我的測試環境是:

Delphi 5 Update1

Delphi 6 Update2

Delphi 7


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-963696/,如需轉載,請註明出處,否則將追究法律責任。

相關文章