前 言
本来我也是非常赞同网上一个流行的观点, VB 只是一个玩具。诚然,作为一个 VB 的普通使用者的确无法玩出更多的东东。但是,这几个月我完全不管 VB 的普通应用,而是一头扎入 COM 的海洋里,凭着潘爱民老师的一片小帆《 COM 原理及应用》以及一袋干粮《 Advance Visual Basic 》。居然在冰冷的技术海洋里转了几个月。终于发现了一个 VB 惊天之迷。然后当然有了这个长篇。
如里不是偶然,在五笔字型里, VB 是代表“好”字。但我所说的迷不是指这个。请你跟随我来拨云见日,看清 VB 是什么。如果当你全部看清了以下的事实,我相信你不会说 VB 是一个玩具。
_ _
_ 起初,比尔的灵运行于水上。 _
_ 比尔说要有 DOS _ _ ,于是就有了 DOS _
_ …… _
_ 第八天,比尔说要有 VB _ _ ,于是就创造出了 VB _ _ 。 _
_ _ _ 《 3S _ _ 新约第一章》 _
深度下潜
你需要一套不错的潜水服( VB6.0 企业版,你不会说你没有吧,其实我只有 D 版的,呵呵)一个潜水镜( VC6.0 所带的 OleView ),当然你还得有较好的游泳技术(坚实的 COM 技术和 C/C++ 功底,不过我也不是很好),然而最重要的是,你可以忍受这次痛苦的经历。如果你是 PLMM ,可以直接与我联系,我会来保护你安全,呵呵。
Everybody ,ok? Lets go
第一天
** 下潜深度(一米,水温 ** ** 0 ** ** ° ** ** C ** ** ),时间北京时间零点整。 ** ** **
“大家好!我是这次探险的队长 BlueDog ,其实我并不是情圣,呵呵,虽然很多 MM 都把我当作梦中情人。”
“你们都不舒服么,为什么大家都在呕吐,噢,我知道了,这很正常么,是晕船呀。”
“呯!”
。。。。。。。
好了,费话少说。拿出你们的 JJ (操,我是指你的机器,电脑,计算机,懂不懂!)
打开一个 VB 工程,建一个标准的 EXE 。接下来的,我们需要使用到 VB 的指针,当我的话没有说完的时候,一只蚊子嗡嗡的说: “老大, ** VB ** ** 中可没有指针呀”。 **
“啪”,世界清静了!
“我最不喜欢有人打断我的讲话了,哼!”
对了,在下水之前,我还没有发给你们一个很重要的装备氧气瓶( 3S Ole TypeLib ),这是居家旅行,杀人灭口的必备利器。
“哪里有得买呢?”
http://www.xtcz.net/bbs/dispbbs.asp?boardid=8&id=1096
你下载后,需要解压,你后你会得到一个 ** 3SoleLib.tlb ** 的文件,此文件是美国进口,中国贴牌生产的。所以使用此文件我不保证没有任何官司缠身。至少如果你用于商业软件,你得请我吃当地的大排档一次,作为你的使用费。
然后用最经典的 DOS 命令
** copy c:\3solelib.tlb c:\windows\system32 **
好了,你然后在你新建的工程中选择 工程 -> 引用 ,引用这个文件,不会用,去死吧。
然后是不是发生了很奇妙的事情???
没有,晕,老大,你按 F2 看看,是不是多了一个 ** olelib ** 的东东
不知道?去死吧,受我一记极度冰冻拳。
有什么用?好,我来告诉你有什么用。
以前,你写个 API 是不是要用 Declare 之类的东东,现在用不着了,你可以直接使用这个 API 了,至少对于大部分的与 COM 有关的 API 是这样子的了。(具体的原因以后进行说明)
如果你真的不懂也不紧,谁叫你是郭靖呢。我们需要里面一个很重要的东东,你在对象浏缆器中可以查找 MoveMemory ,是不是可以找到以下相关的定义。
** Sub MoveMemory(pDest As Any, pSource As Any, ByteLen As Long) **
这便是我们今天所要找的东东。
下面我们在一个 Form 上加一个按钮。然后在 CODE 界面录入
Private Sub Command1_Click()
Dim i As Long
Dim j As Long
i = 3
j = 4
MoveMemory ByVal Varptr(i), ByVal VarPtr(j), 4
Debug.Print i, j
End Sub
运行,看看,发生了什么。 I 的值也变成了 4 ,这是真的。神呀。一定发生了什么。让我们来看看倒底发生了什么。
首先我们看到 ** Varptr, ** 老师告诉我们有问题问 MSDN ,但是 MSDN 没告诉我们。到 GOOGLE 查一查,好多不多,原来是取变量的地址。再到 VB 的对象浏缆器中找找, 打开显示隐含成员 ,然后再查找, VB 会显示
** Function VarPtr(Ptr As Any) As Long **
** VBA._HiddenModule ** ** 的成员 **
比尔在这里隐藏了这个东东,在它的附近有 ObjPtr 、 StrPtr ,它们又是作什么用的呢,简单的说 Objptr 是取对象地址, StrPtr 是取字符串地址的。这两个东东明天再谈。
那么,另一个 MoveMemory 又是什么?来看看 MSDN 的原文
The MoveMemory function moves a block of memory from one location to another.
**VOID MoveMemory (**
** PVOID** _Destination_ **, **// address of move destination
** CONST VOID** _*Source_ **,** // address of block to move
** DWORD** _Length_ // size, in bytes, of block to move
**);**
对于梵文不好的同学,我给大家翻译一下( “ ** MoveMemory ** ** 这个函数的作用是将一堆钱从一个口袋移到另一个口袋,) ** 好,太好了,那么要是写上 ** **
** Movemoney(mybag,bossbag,1000000000000) **
大哥,看清点是 Memory 不是 money !
那么,
就只能将一块内存的数据搬到另一块内存
是这样。
其实很早以前,美国的高手风清杨同志( Bruce McKinney )就搞出了这个东东,让 VB 门人也可以象 C 门人一样练葵花宝典而不用自宫。实在是我等之大幸。不过他重新定义成 CopyMemory ,实际上 Windows API 中是没有这个东东的。
好了,笑话少说,看看上面那行代码是什么意思
MoveMemory ByVal Varptr(i), ByVal VarPtr(j), 4
是不是指从 j 处移到 4 个字节( long 型)到 I 处。
Excellent , 不过你还有一个地方没注意,为什么我要用 Byval 而不用 Byref
不信,你用
MoveMemory VarPtr(i), VarPtr(j), 4 这行代码来代替上面那行,再运行一下,
山还是那座山, I 还是等于 3 ,所以我们还要来仔细研读 MoveMemory 在氧气瓶里的定义
** Sub MoveMemory(pDest As Any, pSource As Any, ByteLen As Long) **
看出来没有,在 VB 中
** 指定 ** ** As Any ** ** 来禁止类型检查,从而允许将任意数据类型传递给该过程 ** ** **
那么如果我们用 Byval 时,传的就是 j 的地址值。
而用 byref 传的就是储存 j 的地址值的临时变量的地址值(为什么这么拗口呀)
明白?
如果你不明白,正是所谓的资质有限,呵呵,不怪你。
这位同学又说了,那要是这样,我不直接用
** MoveMemory i, j, 4 **
就好了,何必这么麻烦。聪明,你看看人家的理解能力。
不过我只是为了告诉大家 varptr 是如何用的而已。
另一个同学就说了,其实还有更简单的
I=j
猪。
** 这时候深度计显示已达到一米,一个同学惊呼,“不明生物来袭”。。。。 ** ** **