com的復(fù)雜性,有點超出我的想象。 與其說Freebasic與vb的互動,不如說Freebasic與com的關(guān)系。 Freebasic如何調(diào)用com呢?Freebasic如何編寫com呢? Freebasic編譯com,一個很明顯的意義,就是在64位中,為VBA提供類庫。 基礎(chǔ)知識: 1、數(shù)據(jù)類型的轉(zhuǎn)換:VBA的string全稱是BSTR。這是VBA獨有。VBA的數(shù)組,全稱safeArray。vba的variant,是一個復(fù)合型的數(shù)據(jù)結(jié)構(gòu)。 2、COM組件 com(Component Object Model組件對象模型)是開發(fā)軟件組件的一種方法。 com組件實際上是一些小的二進(jìn)制可執(zhí)行程序,它們可以給應(yīng)用程序,操作系統(tǒng)以及其他組件提供服務(wù)。 在COM構(gòu)架下,人們可以開發(fā)出各種各樣的功能專一的組件,然后將它們按照需要組合起來,構(gòu)成復(fù)雜的應(yīng)用系統(tǒng)。 可以在多個應(yīng)用系統(tǒng)中重復(fù)利用同一個組件;可以方便的將應(yīng)用系統(tǒng)擴展到網(wǎng)絡(luò)環(huán)境下;COM具有與語言,平臺無關(guān)的特性。 CLSID與ProgID 每個COM接口和組件類都有一個全球唯一的標(biāo)識符GUID,接口的標(biāo)識符叫做IID,組件類的標(biāo)識符叫CLSID(其實都是GUID),組件類還可以用一個別名ProgID來標(biāo)識, ProgID由類名+工程名組成,例如flash控件的ProgID: "ShockwaveFlash.ShockwaveFlash" 動態(tài)接口、靜態(tài)接口 com有兩種類型的接口,一種是動態(tài)語言用到的IDispatch接口,一種是靜態(tài)語言用到的靜態(tài)接口. 我們將IDispatch接口稱為動態(tài)接口,而非IDispatch類接口稱為靜態(tài)接口. 動態(tài)接口:IDispatch接口對象。vba中使用createobject創(chuàng)建對象(俗稱晚期綁定)用的就是Idispatch接口。 靜態(tài)接口:基于IUnknown指針實現(xiàn)的非IDispatch接口。vba并不支持指針,所以vba通過引用tlb進(jìn)行轉(zhuǎn)換(俗稱前期綁定)。vba中無法直接使用iunkown。 Vtable方式:這是性能最好的訪問com的方式,不過必須對指針和com有著相當(dāng)深的了解,才能用好它。否則很容易出錯。 Freebasic提供了全部的三種訪問com的方式。一般情況下,最好使用Idispatch和Iunknown方式。 接下來我要介紹的axsuite3庫,很重要,對于使用freebasi訪問com組件有很大的便利。(記住,訪問com組件和編寫com組件難度是很不一樣的,后者要難得多了) 如果和aauto的com庫比較起來,坦白地說,axsutite3封裝得不太好,起碼不夠直觀和不夠OOP。略表遺憾。 當(dāng)你使用ocx的控件時,axsuite要求你的系統(tǒng)上要有ATL.dll(或Atl71.DLL),換句話說,axsuite是以ATL方式實現(xiàn)對com的使用。 函數(shù): Sub AxInit(ByVal Host As Integer=False) 說明:初始化axsuite。如果要調(diào)用的ocx等窗體控件,則host=true,如果是普通的非窗體的com組件,則host為false 如:Axinit(True) Function AxCreateObject overload(strProgID1 AS string, strIID1 AS string = "") as any ptr 說明:創(chuàng)建對象。Progid或IID都是string 如:excelApp=AxCreateObject("excel.applicaiton") excelApp=AxCreateObject("{8E27C92B-1264-101C-8A2F-040224009C02}",{8E27C92C-1264-101C-8A2F-040224009C02}") Function AxCreateObject overload( hwnd_control as hwnd) as any ptr 說明:直接通過系統(tǒng)分配的hwnd,來創(chuàng)建窗體類的com對象。 如: ocxPtr=axCreateobject(hwnd) Sub AxReleaseObject(byVal Objptr as any ptr) 說明:釋放對象。相當(dāng)于vba中的set object=nothing (即引用數(shù)-1) Function AxCreateControlLic (ByVal strProgID AS lpOLEStr, byval hWndControl AS hwnd, byval strLicKey AS lpwstr) AS Long 說明:用于帶有License Key的com對象。這在天朝中,估計用得很少了。 Function AxCreateUnreg(ByVal hdll As HMODULE, byval CLSIDS As string, byval IIDS As string,ByVal hWndControl AS hwnd = 0) as any ptr 說明:創(chuàng)建一個免注冊的com對象或ocx對象。 Sub setObj(byval pxface as uinteger ptr,ByVal pThis as uinteger) Sub setVObj(byval pxface as uinteger ptr,ByVal vThis as variant) Function ToBSTR(cnv_string As String) As BSTR 說明:將Freebasic的string轉(zhuǎn)換成VB的Bstr字符串 如: dim myBstr as bstr=ToBstr("Test string") Function FromBSTR(ByVal szW As BSTR) As String 說明:將vb的bstr轉(zhuǎn)換成freebasic的string。 Function VariantS(ByRef v As variant)As String 說明:將variant中的bstr轉(zhuǎn)換成freebasic的string。 Function VariantB(ByRef v As variant)As bstr 說明:將variant中的bsctr轉(zhuǎn)換成單純的bstr。相當(dāng)于vba中的cstr(variant) Function VariantV(ByRef v As variant)As Double 說明:將variant中的數(shù)字轉(zhuǎn)換成double。?不知道會不會帶來什么不可預(yù)測的后果。數(shù)字類型那么多種。 Function Vptr(Byval x As Any Type*) As Variant Ptr 說明:將Freebasic的任何一種數(shù)據(jù)類型轉(zhuǎn)換成variant的指針。 如:Dim vVar As Variant vVar=*vptr(20) : vVar=*vptr(20.5) : vVar=*vptr(“Hello there”) VLet (As variant, x As Any Type*) 說明: 這是一個 宏macro 等價 Vptr 函數(shù),可以直接使用。編譯器會自動轉(zhuǎn)成vptr 用這個宏函數(shù),會顯得更直觀。 如:Dim vVar As Variant : Vlet(vVar, 12.75) : Vlet(vVar, “Test String”) 類似這樣的有用宏函數(shù)還有: toVariant(x) :這里的x as any type Ax_FreeStr(bs) :為Bstr字符串分配內(nèi)存 Kill_Bstr(bs):將Bstr字符串從內(nèi)存中刪除。 以上宏函數(shù)都可以在代碼中直接使用。 *any type 是指下面這些數(shù)據(jù)類型: (variant/string/byte/short/Integer/Longint/single/Double/BSTR/Ubyte/Uinteger/Ulongint/Ushort/Ubyte) ************************************** 接下來這部分,是有點悲催的封裝 *************************************** axsuite3中使用Idispatch訪問com組件的函數(shù): Sub AxCall (ByRef pmember as tmember,...) 說明:寫或設(shè)置Idispatch的屬性值。(注:這樣的封裝方式有點怪) Function AxGet (ByRef pmember as tmember,...)as variant 說明:獲取Idispatch的方法的返回值,或獲取Idispatch的屬性值 Vtable方式訪問com組件: Obj-lpVtbl-Method(Obj,…) RetValue=Obj-lpVtbl-Method(Obj,…) 如: scode=dx-lpvtbl-Direct3DCreate(dx,@d3d) '獲取Direct3D的接口 d3d-lpvtbl-GetAdapterDisplayMode(d3d,D3DADAPTER_DEFAULT,@DispMode) ************************************** Axsuite中使用Ocx控件的一些輔助手段: Function AxWinFull(byVal h_parent as hwnd, name1 as string, progid as string, _ x as integer, y as integer, w as integer, h as integer, style as integer = WS_visible or WS_OVERLAPPEDWINDOW, exstyle as integer = 0) as hwnd 說明:在vb中使用Ocx,我們都知道ocx必須放在form中才能使用,ocx無法單獨使用。 這說明ocx必須要有一個窗口容器。 本函數(shù)就是用于創(chuàng)建一個普通窗體,作為ocx控件的容器。并返加一個窗口句柄 Function AxWinTool(byVal h_parent as hwnd, name1 as string, progid as string, _ x as integer, y as integer, w as integer, h as integer, style as integer = WS_visible, exstyle as integer = WS_EX_TOOLWINDOW ) as hwnd 說明:創(chuàng)建一個工具條,作為ocx控件的窗口容器。 Function AxWinChild(byVal h_parent as hwnd, name1 as string, progid as string, _ x as integer, y as integer, w as integer, h as integer,style as integer = WS_visible or WS_child or WS_border, exstyle as integer = 0 ) as hwnd 說明:創(chuàng)建一個子窗體,作為ocx控件的容器 注:h_parent指窗體的句柄,name1是指窗體的名稱,progid指ocx的progid, x,y指窗體的左上角的坐標(biāo)位置,w,y分別是窗體的寬度和高度。style,exstyle詳見api教程。 Sub AxWinKill(byVal h_Control as hwnd) 說明:銷毀窗體。關(guān)閉窗口時,必須銷毀窗體 Sub AxWinHide(byVal h_Control as hwnd, byVal h_Parent as hwnd = 0) 隱藏控件和窗體 Sub AxWinShow(byVal h_Control as hwnd, byVal h_Parent as hwnd = 0) 顯示控件和窗體 Function AxWinUnreg(byVal h_parent as hwnd, x as integer, y as integer, w as integer, h as integer, style as integer = WS_visible or WS_child or WS_border, exstyle as integer = 0) as hwnd 說明:免注冊使用ocx控件時,創(chuàng)建一個普通窗體作為Ocx的容器。