回 帖 发 新 帖 刷新版面

主题:[讨论]Automation 问题

REM ------------------------------------------------
REM - 未引入 CorelDRAW 库时这样调用 : Example1
REM -----------------------------------------------

Dim oCdr As Object
Dim oDoc As object

Set oCdr = CreateObject("CorelDRAW.Application.13")
Set oDoc = oCdr.ActiveDocument

oDoc.SaveAs("E:\abcd.cdr")

Set oDoc = Nothing
Set oCdr = Nothing

REM ------------------------------------------------
REM - 引入 CorelDRAW 库后我这样调用 : Example2
REM -----------------------------------------------

Dim oCdr As Object
Dim oDoc As Document

Set oCdr = CreateObject("CorelDRAW.Application.13")
Set oDoc = oCdr.ActiveDocument

oDoc.SaveAs("E:\abcd.cdr")

Set oDoc = Nothing
Set oCdr = Nothing

Example1 可以调用 SaveAs 方法时说类型转换错误!
Example2 却可以通过!

按理说Example1 运行肯定没有问题才对呀!

大家必须来理一理这个问题了!

回复列表 (共15个回复)

11 楼

这个问题确实奇怪之! 

这是这样理解的!

在WINDOW下不管哪一个程序使用 COM 接口时,都是运行时连接的!

但是在VB中呢 ,给COM对象的方法传值, 有时候是 BYREF 按地址传递, 有时候是以 BYVAL 按值专递
但是VB怎么能知道应该给方法用 BYREF 传还是 BYVAL, 这就是引用库的好处了!引用了库以后!
VB在没有运行以前就可以通过 库中的相关说明来确定按哪种方法传递,这就是库的作用了!
这样在VB程序编译时编译器就为这个方法调用按库中说明的方法来做!所以引用了库以后不会有问题了!

出错的原因呢!
SaveAs("XXXX") 不管是引用库还是没有引用库其SaveAs方法内部得到的值都是指向这个字符串的指针,也是这个字符串的地址,所以出错的肯定会不在这里,也就是说,用字符串常量时!不管你是BYVAL 还是 BYREF 其最终目标方法得到的都是同一个值!

所以错误肯定是出在对其值的处理上的! 我想原理应该是这样的!
在调用一个COM对象的方法时!除了提供一个值参数,还要提供值参数的类型说明!
问题就出在这里! 比方说如果一个方法需要的是一个地址值,你给它一个地址值,类型说明却说明为
实际有效值,其处理结果自然会出错!错误就出在这里了!

当没有引用库时, SaveAs("XXXX") 由于编译时VB不知道给要为这个方法的参数说明为什么类型,所以默认是实际有效值,而不是地址值,而这个方法需要的是一字符串"XXXX"的地址,所以没有引用库时编译把地址值当成了实际编译出去了!运行到SaveAs内部时,其检测不到类型说明不是一个它需要的类型值,所以给调用方返回了类型不正确的错误!
因为这是后期检测所以VB是检测不到的!也只能程序运行了才能知道!

引用库后,VB可以从库中得到该SaveAs("XXXX")调用其参数类型说明为一个地址值,所以编译得到的是正确的,所以运行能够成功!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

当然这只是我的理解!不过我相信我是对的!   但确不知道怎么决解这个问题!为什么需要解决呢!

因为 CorelDRAW.Application.13 是一个COM对象部件,按理来说通用的不管在那一种语言里!

所以 VBScript 应该也能和 JavaScript 也能用! 但是现在就是 VBScript , JavaScript 这些没有像VB一样能让你引入库, 其应该如果正确调用? 

我的问题始终就是这个问题! 没有引用库的时候如果才能正确调用这个方法?

12 楼

老大...你看来是版主做得太认真了!
一直看贴都是想帮别人做什么!别人想做什么!你帮它达至目的!,

可能很少有人像我这样跟大家说错误,和分析错误,以及大家一起讨论错误及期决解方案,我们就是要知道错误的原因,与及语言本身的实际过程!以深入理解之!

13 楼

就是说,用字符串常量时!不管你是BYVAL 还是 BYREF 其最终目标方法得到的都是同一个值!


我不知道是你理解上有问题,还是我的理解错误。

在VB中传字符串时都是以byval传入,即使如始此在调用的函数中是可以修改这个字符串的值。也就是说,byval传的字符串,在函数中得到的是一个字符数组的首地址,这是因为VB运行库中间做的一些转换,以适应C/C++做的接口。
但是,以byref传入的字符串,在调用时却会产生错误(我不知道这时函数得到的到底是什么)。这就是所以一旦API的参数有string声明时,一定就是byval而绝不会出现byref的原因。

14 楼

你说对了!我的意思也就是说不管是用 BYREF 还是 BYVAL 都到的都是指针!

15 楼

我猜——请注意,是猜的。
可能是[color=0000FF].SaveAs[/color]的参数用的是字符串指针。
使用前期绑定方式时可能其参数声明被自动修改成了[color=0000FF]Byval *** As[/color] [color=FF0000]String[/color],这样直接传入一个字符串常量就可以正常调用了。但后期绑定时候参数声明可能是 [color=0000FF]ByRef *** As[/color] [color=FF0000]Any[/color](一般VB在处理指针类型的参数时,都是默认用这种方式),这时候你传入一个字符串进去就会出错了。这时只能用[color=FF0000]byval strptr(***)[/color]来传入参数。
当然,这仅仅是我基于API函数调用参数声明时的不同声明方式的角度来瞎猜的,不知道COM是不是也有这种现象(以前用COM没碰过这种问题),你可以试试……

我来回复

您尚未登录,请登录后再回复。点此登录或注册