Delphi使用VB編寫的ActiveX控件全攻略
翻譯|其它|編輯:郝浩|2004-01-12 21:18:00.000|閱讀
1117 次
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
前言
在最近幾周的工作里,始終被一個(gè)頭疼的問(wèn)題所困擾,那就是VB6編寫的ActiveX控件在Delphi環(huán)境下存在著諸多稀奇古怪的問(wèn)題,幾經(jīng)周折,終于在搜索了幾乎全部的論壇、資料后,找到了針對(duì)不同Delphi版本發(fā)生的問(wèn)題的解決辦法。
Delphi 5 莫名其妙的致命異常之一
首先,我們來(lái)看看VB寫的ActiveX控件在Delphi 5下面的奇怪表現(xiàn)。
例如:我們用VB編寫了一個(gè)控件UserTest(為簡(jiǎn)單起見,我們只導(dǎo)出一個(gè)類即用戶控件),一個(gè)屬性TestName,一個(gè)方法TestMethod。然后將其編譯成一個(gè)ActiveX控件,注冊(cè)并導(dǎo)入Delphi5的開發(fā)環(huán)境(以上步驟如有未清楚之處,請(qǐng)查閱各類參考資料,肯定有標(biāo)準(zhǔn)答案),到目前為止,看來(lái)一切正常。
然后,我們習(xí)慣的把控件拖放到窗體上,調(diào)整大小,在屬性窗口中為屬性賦值,或者在代碼中也是一樣,非常正常,好用的很。但是,下面問(wèn)題來(lái)了,如果您興致勃勃的去調(diào)用了那個(gè)TestMethod,那么您將得到一個(gè)古怪的異常 “Ole Error 800a01a9”,然后程序退出,而且非常不幸的是,您將無(wú)法跟蹤到這個(gè)異常,在Delphi中或是VB中都是,當(dāng)然如果您對(duì)匯編很在行的話,您可以跟著Delphi的調(diào)試窗口一步一步往下……
當(dāng)我第一次碰到這個(gè)問(wèn)題的時(shí)候,我?guī)缀跏菓嵟模驗(yàn)闊o(wú)論是MicroSoft或是Borland,對(duì)該錯(cuò)誤都沒有任何解釋,也沒有任何可以查找的資料。我只好跑到常去的幾個(gè)論壇,當(dāng)然最主要的還是CSDN,在VB版和Delphi版中四處搜索類似的問(wèn)題,然后非常遺憾的是,只有類似的問(wèn)題,而沒有答案,一個(gè)大客戶就用的這個(gè)開發(fā)工具,我在測(cè)試了幾乎所有Windows上的開發(fā)工具和開發(fā)環(huán)境(包括桌面和WEB)后,惟獨(dú)將Delphi忘記了。
剩下的兩天里,我?guī)缀跏菨M世界亂跑,給所有的朋友打電話,詢問(wèn)Delphi方面的高手是否知道這個(gè)情況,最后,我從Google上搜到了一個(gè)鏈接,可惜的是現(xiàn)在我忘記了那個(gè)鏈接的具體位置,但是我得到了一個(gè)近乎Magic的方法(發(fā)現(xiàn)者是這么稱呼它的):
一個(gè)手工修改Delphi導(dǎo)入VB ActiveX控件后產(chǎn)生的代理類型庫(kù)XXX_TLB.PAS(這里XXX指的是控件的類名)文件的方法可以解決這一問(wèn)題。舉例說(shuō)明:
有一個(gè)VB 寫的控件 UserControl1 ,在Delphi中導(dǎo)入后產(chǎn)生兩個(gè)文件,其中一個(gè)UserControl1_TLB.PAS 就是我們所要修改的文件。
在文件中查找 類似
FintF: _UserControl1;
Function GetControlInterface:_UserControl1;
和
property ControlInterface: _UserControl1 read GetControlInterface;
GetControlInterface;
以及
procedure TUserControl1.CreateControl;
procedure DoCreate;
begin
Finf:=IUnknown(OleObject) as _UserControl1;
End;
Begin
If Finf=nil then DoCreate;
End;
Function TUserControl1.GetControl1Interface: _UserControl1;
Begin
CreateControl;
Result:=Finfl;
End;
請(qǐng)注意:這里紅色標(biāo)出的 _UserControl1 要 全部換成 _ UserControl1Disp,如果編譯不成功的話,請(qǐng)將編譯警告中報(bào)出的_UserControl1 全部換成 _UserControl1Disp,編譯即可,這樣在調(diào)用控件的方法時(shí)便不會(huì)出現(xiàn)上述的致命錯(cuò)誤。
感謝這個(gè)偉大的發(fā)現(xiàn),我只能這么形容它,否則可能到現(xiàn)在我還要在這個(gè)圈子里套不出來(lái),或者就是使用另外的工具重新開發(fā)這個(gè)控件(我難以想象這個(gè)工作量會(huì)有多大,又或者它可能還會(huì)存在其他的兼容性問(wèn)題)。
Delphi 5 莫名其妙的致命異常之二
但是,Delphi并沒有在我繞開這個(gè)限制之后而放過(guò)我,很快,客戶那邊發(fā)現(xiàn)另一個(gè)麻煩的問(wèn)題,在開發(fā)環(huán)境下,每次運(yùn)行時(shí)關(guān)閉載有控件的窗體都會(huì)跳出一個(gè)異常錯(cuò)誤,但是在編譯后的應(yīng)用程序中則不會(huì),雖然不會(huì)影響最終用戶的使用,但是這對(duì)開發(fā)人員來(lái)說(shuō)是個(gè)不小的困擾,然后我用了上述例子去試,發(fā)現(xiàn)并不會(huì)發(fā)生這個(gè)問(wèn)題。(我當(dāng)時(shí)就瘋了,這很可能是代碼中一些不兼容的用法所致,在一天時(shí)間里查找上萬(wàn)行代碼是不是很正規(guī)是件極其恐怖的事情)我一氣之下,屏蔽了我的控件中所有的代碼,只留下用戶界面本身,然后奇怪的事情發(fā)生了,我什么代碼都沒寫,但是加載我的控件還是會(huì)發(fā)生這個(gè)錯(cuò)誤,這使我又喜又驚,喜的是這個(gè)問(wèn)題和我的代碼無(wú)關(guān),這樣查找起來(lái)會(huì)方便的多;驚的是只是拖放幾個(gè)VB中的標(biāo)準(zhǔn)控件居然也會(huì)造成這種恐怖的錯(cuò)誤,Delphi5和VB6之間的矛盾還真不是一般的深。接下來(lái)的2個(gè)小時(shí)里,我不斷地刪除界面上的控件來(lái)測(cè)試到底是誰(shuí)造成了這個(gè)致命的異常。
2個(gè)小時(shí)后,我舒了一口氣,問(wèn)題找到了, 其根本問(wèn)題是:
如果你在VB的用戶控件中使用類似Frame和PictureBox這樣的容器控件(其內(nèi)部可以包含其他控件)時(shí),那么您將不可以在這些控件中添加Label、Line、Image這樣的windowLess控件(也就是無(wú)窗口控件,它們?cè)谶\(yùn)行時(shí)是VB實(shí)時(shí)畫出來(lái)的),否則您就會(huì)得到上面這樣的錯(cuò)誤報(bào)告。
Delphi 6、7 隱蔽的ActiveX控件
正是因?yàn)橛辛薉elphi5下面的恐怖經(jīng)歷,我發(fā)現(xiàn)還是很有必要在Delphi6和7下面測(cè)試是不是也存在同樣的問(wèn)題(之前的版本因?yàn)橛脩魳O少已無(wú)必要,Delphi8還沒正式出,也暫不在考慮之列)。結(jié)果是:……無(wú)論我加載多少次,我在ActiveX欄上始終沒有發(fā)現(xiàn)那個(gè)期待已久的小圖標(biāo)。這樣的結(jié)果當(dāng)然很滑稽,我連加載都做不到,更不要談什么測(cè)試正常不正常了。
同樣的,我搜索各類論壇和網(wǎng)站,CSDN里我也發(fā)現(xiàn)了更多的類似問(wèn)題的提出者,但答案還是零,無(wú)奈之下,我只好對(duì)每個(gè)Delphi6、7中的選項(xiàng)進(jìn)行調(diào)整……
歷時(shí)3小時(shí)15分54秒后,我找到了這個(gè)該死的問(wèn)題(請(qǐng)?jiān)徫疫@么稱呼它,我實(shí)在是忍無(wú)可忍)的原因,或者說(shuō)是解決辦法,說(shuō)起來(lái)其實(shí)很簡(jiǎn)單。
現(xiàn)在請(qǐng)跟著我做:點(diǎn)擊Tools菜單->Environment Options->Type Library頁(yè),我們應(yīng)該發(fā)現(xiàn)一項(xiàng):Ignore special CoClass Flags When Importing,選中它,然后再選中Can Create那一項(xiàng),那么現(xiàn)在,我們?cè)賴L試去導(dǎo)入那個(gè)可憐的ActiveX控件吧(這里要注意,如果你已經(jīng)導(dǎo)入過(guò)一次,那么請(qǐng)把產(chǎn)生的那兩個(gè)文件 .dcr 和 .pas文件刪除,否則將不會(huì)刷新)。這次如果還是不能在ActiveX欄中發(fā)現(xiàn)那個(gè)控件的話,那么只有致電Microsoft或是Borland,問(wèn)問(wèn)看什么時(shí)候它們能結(jié)成親家,呵呵!
(另,在Delphi6和7中倒是沒有發(fā)現(xiàn)Delphi5中出現(xiàn)的上述錯(cuò)誤)
我的測(cè)試環(huán)境是:
Win2K
Delphi 5 Update1
Delphi 6 Update2
Delphi 7
標(biāo)簽:
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn