注册 登录
Office中国论坛/Access中国论坛 返回首页

ganlinlao的个人空间 http://www.office-cn.net/?230471 [收藏] [复制] [分享] [RSS]

日志

FreeBasic调用COM组件

热度 1已有 3676 次阅读2015-5-28 12:56 |个人分类:FreeBasic| Freebasic与com

com的复杂性,有点超出我的想象。

与其说Freebasic与vb的互动,不如说Freebasic与com的关系。
Freebasic如何调用com呢?Freebasic如何编写com呢?
Freebasic编译com,一个很明显的意义,就是在64位中,为VBA提供类库。
基础知识:
1、数据类型的转换:VBA的string全称是BSTR。这是VBA独有。VBA的数组,全称safeArray。vba的variant,是一个复合型的数据结构。
2、COM组件
com(Component Object Model组件对象模型)是开发软件组件的一种方法。
com组件实际上是一些小的二进制可执行程序,它们可以给应用程序,操作系统以及其他组件提供服务。
在COM构架下,人们可以开发出各种各样的功能专一的组件,然后将它们按照需要组合起来,构成复杂的应用系统。
可以在多个应用系统中重复利用同一个组件;可以方便的将应用系统扩展到网络环境下;COM具有与语言,平台无关的特性。

CLSID与ProgID
每个COM接口和组件类都有一个全球唯一的标识符GUID,接口的标识符叫做IID,组件类的标识符叫CLSID(其实都是GUID),组件类还可以用一个别名ProgID来标识,
ProgID由类名+工程名组成,例如flash控件的ProgID: "ShockwaveFlash.ShockwaveFlash"

动态接口、静态接口
com有两种类型的接口,一种是动态语言用到的IDispatch接口,一种是静态语言用到的静态接口.
我们将IDispatch接口称为动态接口,而非IDispatch类接口称为静态接口.

动态接口:IDispatch接口对象。vba中使用createobject创建对象(俗称晚期绑定)用的就是Idispatch接口。

静态接口:基于IUnknown指针实现的非IDispatch接口。vba并不支持指针,所以vba通过引用tlb进行转换(俗称前期绑定)。vba中无法直接使用iunkown。

Vtable方式:这是性能最好的访问com的方式,不过必须对指针和com有着相当深的了解,才能用好它。否则很容易出错。

Freebasic提供了全部的三种访问com的方式。一般情况下,最好使用Idispatch和Iunknown方式。


接下来我要介绍的axsuite3库,很重要,对于使用freebasi访问com组件有很大的便利。(记住,访问com组件和编写com组件难度是很不一样的,后者要难得多了)
如果和aauto的com库比较起来,坦白地说,axsutite3封装得不太好,起码不够直观和不够OOP。略表遗憾。
当你使用ocx的控件时,axsuite要求你的系统上要有ATL.dll(或Atl71.DLL),换句话说,axsuite是以ATL方式实现对com的使用。

函数:
Sub AxInit(ByVal Host As Integer=False)
说明:初始化axsuite。如果要调用的ocx等窗体控件,则host=true,如果是普通的非窗体的com组件,则host为false
如:Axinit(True)

Function AxCreateObject overload(strProgID1 AS string, strIID1 AS string = "") as any ptr
说明:创建对象。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
说明:直接通过系统分配的hwnd,来创建窗体类的com对象。
如: ocxPtr=axCreateobject(hwnd)

Sub AxReleaseObject(byVal Objptr as any ptr)
说明:释放对象。相当于vba中的set object=nothing (即引用数-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
说明:创建一个免注册的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转换成VB的Bstr字符串
如: dim myBstr as bstr=ToBstr("Test string")

Function FromBSTR(ByVal szW As BSTR) As String
说明:将vb的bstr转换成freebasic的string。

Function VariantS(ByRef v As variant)As String
说明:将variant中的bstr转换成freebasic的string。

Function VariantB(ByRef v As variant)As bstr
 说明:将variant中的bsctr转换成单纯的bstr。相当于vba中的cstr(variant)

Function VariantV(ByRef v As variant)As Double
说明:将variant中的数字转换成double。?不知道会不会带来什么不可预测的后果。数字类型那么多种。

Function Vptr(Byval x As Any Type*) As Variant Ptr
说明:将Freebasic的任何一种数据类型转换成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 函数,可以直接使用。编译器会自动转成vptr
用这个宏函数,会显得更直观。
如:Dim vVar As Variant : Vlet(vVar, 12.75) : Vlet(vVar, “Test String”)
类似这样的有用宏函数还有:
toVariant(x) :这里的x as any  type
Ax_FreeStr(bs) :为Bstr字符串分配内存
Kill_Bstr(bs):将Bstr字符串从内存中删除。
以上宏函数都可以在代码中直接使用。
*any type 是指下面这些数据类型: (variant/string/byte/short/Integer/Longint/single/Double/BSTR/Ubyte/Uinteger/Ulongint/Ushort/Ubyte)

**************************************
接下来这部分,是有点悲催的封装
***************************************
axsuite3中使用Idispatch访问com组件的函数:
Sub AxCall (ByRef pmember as tmember,...)
说明:写或设置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必须要有一个窗口容器。
         本函数就是用于创建一个普通窗体,作为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

说明:创建一个工具条,作为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

说明:创建一个子窗体,作为ocx控件的容器
注:h_parent指窗体的句柄,name1是指窗体的名称,progid指ocx的progid,
x,y指窗体的左上角的坐标位置,w,y分别是窗体的宽度和高度。style,exstyle详见api教程。

Sub AxWinKill(byVal h_Control as hwnd)
说明:销毁窗体。关闭窗口时,必须销毁窗体
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控件时,创建一个普通窗体作为Ocx的容器。

发表评论 评论 (1 个评论)

回复 tmtony 2015-6-3 14:18
强!

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

QQ|站长邮箱|小黑屋|手机版|Office中国/Access中国 ( 粤ICP备10043721号-1 )  

GMT+8, 2024-3-29 14:30 , Processed in 0.074807 second(s), 18 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

返回顶部