不要频繁的连接数据库、刷新窗体、过多地使用timer

解决方案 »

  1.   

    再转贴一篇文章  
    VB超频快餐
    用Mid$命令超速字符串添加操作
    从头开始删除集合项目
    用InStr函数实现代码减肥
    精用Boolean表达式,让代码再减肥
    函数名巧做局部变量
    火眼识破隐藏的Variant变量
    GoSub在编译程序中速度变慢
    减少DoEvents语句的数量
    为常量定义合适的类型
    And、Or和Xor:让我们来优化表达式
    静态变量慢于动态变量
    善用"Assume No Aliasing"编译选项
    你真正理解"Allow Unrounded Floating Point Operations"选项的含义吗?
    除法运算符""与"/"的区别
    使用"$-类型"字符串函数会更快
    妙用Replace函数替代字符串连接操作符&
    固定长度字符串数组:赋值快,释放快!
    未公开的返回数组型函数加速秘诀
    深入使用LIKE操作符
    创建任意长度重复字符串的简洁方法
    另辟蹊径处理字符串中的字符:字节数组法
    快速清除数组部分内容
    快速初始化Variant和String类型数组
    访问简单变量总是快于数组元素值
    创建新表时,快速拷贝字段
    无闪烁地快速附加字符串到textbox控件
    快速找到选中的OptionButton
    表单及控件的引用阻止了表单的卸载
    重定义编译DLL文件的基地址
    快速调入TreeView控件以及ListView控件的子项内容
    Friend过程快于Public过程
    使用Objptr函数快速查找集合中的对象
    使用ObjPtr检测2个对象变量是否指向同一对象
    读取文件内容的简洁方法
    字体对象克隆招法 用Mid$命令超速字符串添加操作
    大家都知道,&操作符的执行速度是相当慢的,特别是处理长字符串时。当必须重复地在同一变量上附加字符时,有一个基于Mid$命令的技巧可以使用。基本思路就是:预留一个足够长的空间存放操作的结果。下面是应用这个技术的一个例子。假设要建立一个字符串,它要附加从1开始的10000个整数:"1 2 3 4 5 6 7 ... 999910000"。下面是最简单的实现代码:
    res = ""
    For i = 1 to 10000: res = res & Str(i): Next<>
    face=宋体>代码虽然简单,但问题也很明显:Res变量将被重分配10000次。下面的代码实现同样的目的,但效果明显好转:Dim res As String
    Dim i As Long
    Dim index As Long’预留足够长的缓冲空间
    res = Space(90000)’指针变量,指出在哪里插入字符串
    index = 1’循环开始
    For i = 1 to 10000
    substr = Str(i)
    length = Len(substr)’填充字符串的相应区间段数值
    Mid$(res, index, length) = substr
    ’调整指针变量
    index = index + length
    Next
    ’删除多余字符
    res = Left$(res, index - 1)测试表明:在一个333MHz的计算机上,前段代码执行时间为2.2秒,后者仅仅为0.08秒!代码虽然长了些,可是速度却提高了25倍之多。呵呵,由此看来:代码也不可貌相啊
    从头开始删除集合项目删除集合中的所有内容有许多方法,其中有些非常得迅速。来看看一个包含10,000个项目的集合:
    Dim col As New Collection, i As Long
    For i = 1 To 10000
       col.Add i, CStr(i)
    Next可以从末尾位置为起点删除集合内容,如下:For i = col.Count To 1 Step -1
    col.Remove iNext也可以从开始位置为起点删除集合内容,如下:For i = 1 To col.Count Step 1
    col.Remove i
    Next<>
    face=宋体>试验证明,后者要快于前者百倍多,比如0.06秒比4.1秒。原因在于:当引用接近末尾位置的集合项目时,VB必须要从第1个项目开始遍历整个的项目链。 <>
    face=宋体>更有趣的是,如果集合项目的数量加倍,那么从末尾开始删除与从头开始删除,前者要比后者花费的时间将成倍增长,比如前者是24秒,后者可能为0.12秒这么短!
    最后提醒您:删除集合的所有内容的最快方法就是“毁灭”它,使用下面的语句: Set col = New Collection对于一个包含20,000个项目的集合,上述操作仅仅耗时0.05秒,这比使用最快的循环操作进行删除也要快2倍左右。
    用InStr函数实现代码减肥可以采用“旁门左道”的方式使用Instr函数实现代码的简练。下面是一个典型的例子,检测字符串中是否包含一个元音字母:1、普通的方法:If UCase$(char) = "A" Or UCase$(char) = "E" Or UCase$(char) = "I" Or UCase$(char) = "O" Or UCase$(char) = "U" Then’ it is a vowelEnd If2、更加简练的方法:If InStr("AaEeIiOoUu", char) Then’ it is a vowelEnd If同样,通过单词中没有的字符作为分界符,使用InStr来检查变量的内容。下面的例子检查Word中是否包含一个季节的名字: 1、普通的方法:If LCase$(word) = "winter" Or LCase$(word) = "spring" Or LCase$(word) = _ "summer" Or LCase$(word) = "fall" Then’ it is a season’s nameEnd If2、更加简练的方法:If Instr(";winter;spring;summer;fall;", ";" & word & ";") Then’ it is a season’s nameEnd If有时候,甚至可以使用InStr来替代SelectCase代码段,但一定要注意参数中的字符数目。下面的例子中,转换数字0到9的相应英文名称为阿拉伯数字: 1、普通的方法:Select Case LCase$(word)Case "zero"result = 0Case "one"result = 1Case "two"result = 2Case "three"result = 3Case "four"result = 4Case "five"result = 5Case "six"result = 6Case "seven"result = 7Case "eight"result = 8Case "nine"result = 9End Select2、更加简练的方法:result = InStr(";zero;;one;;;two;;;three;four;;five;;six;;;seven;eight;nine;", _";" & LCase$(word) & ";") \ 6精用Boolean表达式,让代码再减肥当设置基于表达式结果的Boolean型数值时,要避免使用多余的If/Then/Else语句结果。比如:If SomeVar > SomeOtherVar ThenBoolVal = TrueElseBoolVal = FalseEnd If上面这段代码就很烦琐,它们完全可以使用下面的一行代码来替代:BoolVal = (SomeVar > SomeOtherVar)括号不是必须的,但可以增加可读性。根据表达式中的操作数不同,后者比前者执行起来大约快50%到85%。后者中的括号对速度没有影响。有时,使用这个技术实现代码的简练并非很明显。关键是要牢记:所有的比较操作结果或者是0(false),或者是-1(True)。所以,下面例子中的2段代码是完全相同的,但是第2段要运行得快些:1、传统方法:If SomeVar > SomeOtherVar Thenx = x + 1End If2、更简练的方法x = x - (SomeVar > SomeOtherVar)
    函数名巧做局部变量很多程序员都没有认识到“在函数本身中使用函数名”的妙处,这就象对待一个局部变量一样。应用这个技巧可以起到临时变量的作用,有时还能加速程序运行。看看下面的代码:Function Max(arr() As Long) As LongDim res As Long, i As Longres = arr(LBound(arr))For i = LBound(arr) + 1 To UBound(arr)If arr(i) > res Then res = arr(i)NextMax = resEnd Function去掉res变量,使用函数名称本身这个局部变量,可以使程序更加简练:Function Max(arr() As Long) As LongDim i As LongMax = arr(LBound(arr))For i = LBound(arr) + 1 To UBound(arr)If arr(i) > Max Then Max = arr(i)NextEnd Function
    火眼识破隐藏的Variant变量如果没有用As语句声明变量,默认类型就是Variants,比如:Dim name ’ this is a variant或者,当前模块下没有声明Option Explicit语句时,任何变量都是Variants类型。许多开发者,特别是那些先前是C程序员的人,都会深信下面的语句将声明2个Interger类型变量:Dim x, y As Integer而实际上,x被声明为了variant类型。由于variant类型变量要比Integer类型慢很多,所以要特别注意这种情况。正确的一行声明方法是:Dim x As Integer, y As IntegerGoSub在编译程序中速度变慢编译为本地代码的VB应用程序中,如果使用 GoSubs 命令,就会比通常的 Subs 或者 Function 调用慢5-6倍;相反,如果是p-code模式,就会相当快。
    减少DoEvents语句的数量不要在代码中放置不必要的DoEvents语句,尤其是在时间要求高的循环中。遵循这个原则,至少能在循环中的每N次反复时才执行DoEvents语句,从而增强效率。比如使用下面的语句:If (loopNdx Mod 10) = 0 Then DoEvents如果只是使用DoEvents来屏蔽鼠标以及键盘操作,那么就可以在事件队列中存在待处理项目时调用它。通过API函数GetInputState来检查这个条件的发生:Declare Function GetInputState Lib "user32" Alias "GetInputState" () As Long’ ...If GetInputState() Then DoEvents
    为常量定义合适的类型VB在内部使用最简单、最可能的数据类型保存符号数值,这意味着最通常的数字类型-比如0或者1-都按照Integer类型存储。如果在浮点表达式中使用这些常量,可以通过常量的合适类型来加速程序运行,就象下面的代码:value# = value# + 1#.这个语句强迫编译器按照Double格式存储常量,这样就省却了运行时的隐含转换工作。还有另外的一种处理方法就是:在常量声明时就进行相应类型的定义,代码如下:Const ONE As Double = 1And、Or和Xor:让我们来优化表达式要检测一个整数值的最高有效位是否有数值,通常要使用如下的代码(有二种情况:第一组If判断表明对Integer类型,第二组对Long类型):If intValue And &H8000 Then’ most significant bit is setEnd IfIf lngValue And &H80000000 Then’ most significant bit is setEnd If但由于所有的VB变量都是有符号的,因此,最高有效位也是符号位,不管处理什么类型的数值,通过下面的代码就可以实现检测目的:If anyValue < 0 Then’ most signific
      

  2.   

    静态变量慢于动态变量 在过程中引用静态局部变量要比引用常规局部动态变量慢2-3倍。要想真正地加速过程的执行速度,最彻底的方法就是将所有的静态变量转换为模块级别变量。 这种方法的唯一不足是:过程很少是自包含的,如果要在其他工程中重用,就必须同时拷贝并粘贴这些模块级别变量。 另外的一种处理方法是:在时间要求高的循环前,将静态变量数值装入动态变量中。 善用"Assume No Aliasing"编译选项 据说,如果过程能够2次或多次引用同样的内存地址,那么过程就会包含别名数值。一个典型的例子如下: Dim g_GlobalVariable As Long ... Sub ProcWithAliases(x As Long) x = x + 1 g_GlobalVariable = g_GlobalVariable + 1 End Sub 如果传递给这个过程g_GlobalVariable变量,则将通过一个直接引用以及x参数两种方式修改变量的数值2次。 别名数值经常是不良编程习惯的产物,对于程序优化有害无益。事实上,如果能够完全确认应用程序从来没有使用到别名变量,就可以打开"Assume No Aliasing"高级编译选项,这将告知编译器没有过程可以修改同一内存地址,使编译器产生更加有效率的汇编代码。更特别的是,编译程序将试图缓冲这些数据到CPU的寄存器中,从而明显地加速了程序运行。 总结一下,当遇到以下情况时,就不会有别名数值:(1) 过程不引用任何全局变量 (2) 过程引用了全局变量,但从来不通过ByRef参数类型传递同一变量给过程 (3) 过程含有多个ByRef参数类型,但从来不传递同一变量到其中的2个或者多个之中。
    你真正理解"Allow Unrounded Floating Point Operations"选项的含义吗?来自微软的资料鼓吹:高级优化对话框中的所有编译选项都被认为是不稳定的,它们可能导致不正确的结果,甚至程序崩溃。对于其中的大多数,这种说法是正确的,但是经常有一个叫做"Allow Unrounded Floating Point Operations"的选项能够给予正确的结果,防止应用程序产生bug。考虑下面的代码段:Dim x As Double, y As Double, i As Integerx = 10 ^ 18y = x + 1 ’ this can’t be expressed with 64 bitsMsgBox (y = x) ’ 显示 "True" (不正确的结果)严格地说,由于X和Y变量不包含相同的数值,MsgBox将显示False。可问题是,由于数值1E18与1E18+1都以相同的64位浮点Double类型来表示,它们最终包含了几乎相同的数值,最后的MsgBox结果将是True。如果打开了"Allow Unrounded Floating Point Operations"编译选项,VB就能重用已在数学协处理器堆栈中的数值,而不是内存中的数值(比如:变量)。因为FPU堆栈具备80位的精度,因此就可以区分出这2个数值的不同:’ if the program is compiled using the’ "Allow Unrounded Floating Point Operations" compiler optionMsgBox (y = x) ’ 显示 "False" (正确的结果)总结一下:当以解释模式、或者编译的p-code模式、或者编译的native代码模式但关掉"Allow Unrounded Floating Point Operations"选项这3种方式运行一个程序时,所有浮点数字运算在内部都以80位的精度进行处理。但如果有一个数值是存储在64位Double变量中,结果就是接近的了,并且,随后使用那个变量的表达式也将产生近似的结果,而不是绝对正确的结果。相反,如果打开"Allow Unrounded Floating Point Operations"编译选项后运行一段native编译代码,在随后的表达式中VB就经常能重用内部的80位数值,而忽略存储在变量中的当前数值。注意:我们并不能完全控制这个功能,VB也许对此生效,也许就不生效,这要取决于表达式的复杂程度以及最初分配数值语句与随后产生结果的表达式语句的距离远近。
    除法运算符"\"与"/"的区别 整数间执行除法运算时,要使用 "\" 而不是 "/"。 "/" 运算符要求返回一个单一数值,所以,表面上看似简单的一行代码: C% = A% / B% 实际上包含了3个隐含的转换操作:2个为除法运算做准备,从Integer转换到Single;一个完成最后的赋值操作,从Integer转换到Single。但是如果使用了"\"操作符,情况就大不相同了!不仅不会有这么多中间步骤,而且执行速度大大提高。 同时请记住:使用"/"操作符做除法运算时,如果其中之一是Double类型,那么结果就将是Double类型。所以,当2个Integer或者Single类型数值做除法运算时,如果想得到高精度的结果,就需要手工强迫其中之一转换为Double类型: ’结果为 0.3333333 Print 1 / 3 ’结果为 0,333333333333333 Print 1 / 3#
    使用"$-类型"字符串函数会更快 VB官方文档似乎很鼓励使用"无$"类字符串函数,比如:Left、LTrim或者UCase,而不是实现同样功能的Left$、LTrim$和UCase$函数。但是我们必须认识到:前者返回variant类型的数值,当用于字符串表达式中时,最终必须要转换为字符串(string)类型。 因此,在严格要求时间的代码段中,我们应该使用后者,它们将快5-10%。
    妙用Replace函数替代字符串连接操作符&你大概不知道Replace函数还能这么用吧?比如下面的语句:MsgBox "Disk not ready." & vbCr & vbCr & _"Please check that the diskette is in the drive" & vbCr & _"and that the drive’s door is closed."可以看出,为了显示完整的字符串含义,要将可打印字符与非打印字符(比如:回车符vbCr)用&符号连接在一起。结果是:长长的字符连接串变得难于阅读。但是,使用Replace函数,可以巧妙地解决这个问题。方法就是:将非打印字符以字符串中不出现的一个可打印字符表示,这样完整地写出整个字符串,然后使用Replace函数替换那个特别的打印字符为非打印字符(比如:回车符vbCr)。代码如下:MsgBox Replace("Disk not ready.§§Please check that the diskette is in the " _& "drive§and that the drive’s door is closed.", "§", vbCr)固定长度字符串数组:赋值快,释放快!固定长度字符串的处理速度通常慢于可变长度字符串,这是因为所有的VB字符串函数和命令只能识别可变长度字符串。因此,所有固定长度字符串比然被转换为可变长度字符串。但是,由于固定长度字符串数组占据着一块连续的内存区域,因此在被分配以及释放时,速度明显快于可变长度的数组。比如:在一个Pentium 233MHz机器上,对于一个固定长度为100,000的数组,给其中30个位置分配数值,大约只花费半秒种的时间。而如果是可变长度的数组,同样的操作要耗费8秒之多!后者的删除操作耗时大约0.35秒,但固定长度的数组几乎可以立即“毙命”!如果应用程序中涉及到这么大的一个数组操作,选择固定长度方式数组绝对是确定无疑的了,无论是分配数值,还是释放操作,都可以风驰电掣般完成。
    未公开的返回数组型函数加速秘诀 在VB6中,函数是能够返回数组对象的。这种情况下,我们不能象返回对象或者数值的其他函数一样使用函数名当做局部变量来存储中间结果,因此不得不生成一个临时局部数组,函数退出前再分配这个数组给函数名,就象下面的代码一样: ’ 返回一个数组,其中含有N个随即元素 ’ 并且将平均值保存在AVG中 Function GetRandomArray(ByVal n As Long, avg As Single) As Single() Dim i As Long, sum As Single ReDim res(1 To n) As Single ’ 以随机数填充数组,并计算总和 Randomize Timer For i = 1 To n res(i) = Rnd sum = sum + res(i) Next ’ 赋值结果数组,计算平均值 GetRandomArray = res avg = sum / n End Function 难以置信的是,只需要简单地颠倒最后2条语句的顺序,就能使上面这段程序变得快些: ’ ... ’ 赋值结果数组,计算平均值 avg = sum / n GetRandomArray = res End Function 例如,在一个Pentium II 333MHz 机器上,当N=100,000时,前段程序运行时间为0.72秒,后段程序则为0.66秒,前后相差10%。 原因何在呢?前段程序中,VB将拷贝res数组到GetRandomArray对应的结果中,当数组很大时,花费的时间是很长的。后段程序中,由于GetRandomArray = res是过程的最后一条语句,VB编译器就能确认res数组不会被再使用,因此将直接交换res和GetRandomArray的地址数值,从而节省了数组元素的物理拷贝操作以及随后的res数组释放操作。 总结如下:当编写返回数组的函数时,一定要将分配临时数组到函数名的语句放在最后,就是其后紧挨者Exit Function 或者End Function的位置。
    深入使用LIKE操作符 在VB中,相对于本身的潜在功能,LIKE可能是最被忽视的一个操作符了。它的最基本用途是检查一个字符串与给定样式的匹配程度。比如,很容易检查一个产品ID号是否由一个字母以及3个数字组成: If ProductID Like "[A-Za-z][0-9][0-9][0-9]" Then Print "OK" ’ this is equivalment, because "#" stands for a digit If ProductID Like "[A-Za-z]###" Then Print "OK" 除了上述基本功能,LIKE在其他情况下也非常有用。以下就一一列举: 比如,可以检查一个字符串只包含大写字母: If Not ProductID Like "*[!A-Z]*" Then Print "OK" 同理,也可以检查一个字符串只包含数字: If Not ProductID Like "*[!0-9]*" Then Print "OK" 下面的语句检查一个字符串只包含字母或者数字符: If Not ProductID Like "*[!A-Za-z0-9]*" Then Print "OK" 下面的语句检查一个字符串是否为合法的VB变量名,就是说,开头是一个字母,接着跟随字母或数字符: ’ VarName是被检查的字符串 If VarName like "[A-Za-z]*" And Not Mid$(VarName, 2) Like "*[!A-Z_a-z0-9]*" _ Then Print "OK" 下面的语句检查字符串是否至少包含2个空格(连续的或者间隔的): If TestString Like "* * *" Then Print "OK" 而下面的语句进一步确认2个空格是不连续的: If TestString Like "* ?* *" The
      

  3.   

    快速清除数组部分内容清除动态数组的最快方法是使用ReDim,清除静态数组则是使用删除。但是如果只想清除数组的一部分内容,怎么办呢?看上去似乎只能使用For-Next循环了。如果处理的是数字数组,有一个较快的方法。它基于ZeroMemory API函数,正如函数名所示,它能将一块内存区域填充为0。看看怎么应用这个函数来清除一个Long类型数组的一部分内容:Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (dest As _Any, ByVal Bytes As Long)’定义数组,填充数据Dim a(1000) As LongFor i = 1 To UBound(a)a(i) = iNext’从a(200)开始清除100个元素内容ZeroMemory a(200), 100 * Len(a(1))请注意上述代码中清除长度的表示方法,使用Len()函数保证了当数组类型改变时代码仍然有效。
    快速初始化Variant和String类型数组VB中没有提供定义数组并同时初始化其内容的方法,所以大多数情况下,必须单独地设置每一个元素,就象下面一样:Dim strArray(0 To 3) As StringstrArray(0) = "Spring"strArray(1) = "Summer"strArray(2) = "Fall"strArray(3) = "Winter"在VB4、VB5和VB6中,可以使用Array()函数随意创建一个Variants类型数组:Dim varArray() As VariantvarArray() = Array("Spring", "Summer", "Fall", "Winter")但却没有同样的函数能创建非Variant类型数组。但是我们发现,在VB6中可以使用Split()函数创建字符串数组:Dim varArray() As String’由Split建立的数组下标通常是从0开始的varArray() = Split("Spring;Summer;Fall;Winter", ";")在VB6中,同样能充分利用函数返回数组的能力,创建数组初始化程序段。比如下面的代码段:Function ArrayInt(ParamArray values() As Variant) As Integer()Dim i As LongReDim res(0 To UBound(values)) As IntegerFor i = 0 To UBound(values)res(i) = values(i)NextArrayInt = res()End Function同时,也可以创建一个子程序段来检测传递给它的数值的类型,并返回正确类型的数组。这种情况下,函数应该定义为返回Variant。
    访问简单变量总是快于数组元素值读写数组中的元素速度通常都慢于访问一个简单变量,因此,如果在一个循环中要重复使用同一数组元素值,就应该分配数组元素值到临时变量中并使用这个变量。下面举一个例子,检测整数数组中是否存在重复项:Function AnyDuplicates(intArray() As Integer) As Boolean’如果数组包含重复项,返回TrueDim i As Long, j As Long,Dim lastItem As LongDim value As Integer’只计算机UBound()一次lastItem = UBound(intArray)For i = LBound(intArray) To lastItem’ 保存intArray(i)到非数组变量中value = intArray(i)For j = i + 1 To lastItemIf value = intArray(j) ThenAnyDuplicates = TrueExit FunctionEnd IfNextNext’没有发现重复项AnyDuplicates = FalseEnd Function上述程序有2层循环,通过缓存intArray(i)的数值到一个普通的、非数组变量中,节省了CPU运行时间。经测试,这将提高80%的速度。创建新表时,快速拷贝字段在VB6中,无需离开开发环境就可以创建新的SQL Server和Oracle表。方法很简单:打开DataView窗口,用鼠标右键单击数据库的表文件夹,再选择新表格菜单命令。当处理相似表格时,就是说具有许多相同字段的表格,我们完全可以在很短的时间内容完成设定操作。具体步骤是:在设计模式下打开源表格,加亮选择要拷贝字段对应的行,按Ctrl-C拷贝信息到粘贴板;然后,在设计模式打开目标表格,将光标置于要粘贴字段所在的位置,按Ctrl-V。这样,就拷贝了所有的字段名称以及它们所带的属性。
    无闪烁地快速附加字符串到textbox控件附加文本到TextBox或者RichTextBox控件的通常方法是在当前内容上连接上新的字符串:Text1.Text = Text1.Text & newString但还有一个更快的方法,并且会减少连接操作的闪烁感,代码如下:Text1.SelStart = Len(Text1.Text)Text1.SelText = newString快速找到选中的OptionButtonOptionButton控件经常是作为控件数组存在的,要快速找到其中的哪一个被选中,可以使用下面的代码:’假设控件数组包含3个OptionButton控件intSelected = Option(0).Value * 0 - Option(1).Value * 1 - Option(2).Value * 2注意,因为第一个操作数总是0,所以上述代码可以精简如下:intSelected = -Option(1).Value - Option(2).Value * 2表单及控件的引用阻止了表单的卸载当指派表单或者表单上的控件到该表单模块以外的一个对象变量中时,如果要卸载表单,就必须首先将那个变量设置为 to Nothing。也就是说,如果不设置为Nothing,即使看不到这个对象了,但它仍旧是保存在内存中的。注意:这并非是一个bug,这仅仅是COM引用规则的一个结果。唯一要注意的就是引用的这个控件将阻止整个表单的卸载操作,它将依赖于它的父表单而存在。重定义编译DLL文件的基地址许多VB开发者都知道应该在工程属性对话框的“编译”功能页面中定义一个DLL基地址数值。这不同于工程中任何其他DLL或OCX的基地址。当操作没有源代码的编译DLL或者OCX文件时,可以使用EDITBIN程序修改它的基地址。EDITBIN程序随Visual Studio安装后就有了,可以在主Visual Studio目录的VC98\BIN目录下找到它。比如,以下代码重新设定一个编译DLL文件的基地址为12000000(16进制):EDITBIN /REBASE:BASE=0x12000000 myfile.dll同样,EDITBIN程序对可执行文件也有一些处理技巧。以下是该程序支持的完整功能选项列表(使用EDITBIN /? 可以列出这些):/BIND[:PATH=path]/HEAP:reserve[,commit]/LARGEADDRESSAWARE[:NO]/NOLOGO/REBASE[:[BASE=address][,BASEFILE][,DOWN]]/RELEASE/SECTION:name[=newname][,[[!]{cdeikomprsuw}][a{1248ptsx}]]/STACK:reserve[,commit]/SUBSYSTEM:{NATIVE|WINDOWS|CONSOLE|WINDOWSCE|POSIX}[,#[.##]]/SWAPRUN:{[!]CD|[!]NET}/VERSION:#[.#]/WS:[!]AGGRESSIVE
    快速调入TreeView控件以及ListView控件的子项内容有一个简单但仍未发现的技巧可用于在TreeView控件中装载多个节点,或者在ListView控件中装载多个ListItems。这种方法要比传统做法快。先看看下面这个传统方法:For i = 1 To 5000TreeView1.Nodes.Add , , , "Node " & iNext改进一下,代替重复引用TreeView1对象的Nodes集合,我们可以先将之保存在临时对象变量中:Dim nods As MSComctlLib.NodesSet nods = TreeView1.NodesFor i = 1 To 5000nods.Add , , , "Node " & iNext甚至,如果使用With代码块,还可以不需要临时变量:With TreeView1.NodesFor i = 1 To 5000.Add , , , "Node " & iNextEnd With经测试,优化的循环代码要比传统方法执行速度快40%左右。原因在于:将Nodes集合对象保存在临时变量中,或者应用With代码块后VB将使用隐藏的临时变量后,就可以避免在循环中重复绑定Nodes对象到它的父TreeView1对象上。由于这种绑定是低效率的,因此省却它就能节省大量的执行时间。同样的道理对于其他ActiveX控件也生效:
    ListView控件的ListItems、ListSubItems以及ColumnHeaders集合Toolbar控件的Buttons和ButtonMenus集合ImageList的ListImages集合
    StatusBar控件的Panels集合
    TabStrip控件的Tabs集合
    Friend过程快于Public过程你可能会非常惊奇:Friend类型过程的执行速度要明显快于Public类型。这可以通过创建一个带有Private类和Public类 (设定Instancing = MultiUse)的ActiveX EXE工程看到,在2个类模块中添加下面的代码:Public Sub PublicSub(ByVal value As Long)’End SubPublic Function PublicFunction(ByVal value As Long) As Long’End FunctionFriend Sub FriendSub(ByVal value As Long)’End SubFriend Function FriendFunction(ByVal value As Long) As Long’End Function然后,在表单模块中创建一个循环,执行每个例程许多次。比如,要在一个Pentium II机器上查看执行时间上的区别,可以调用每个例程1,000,000次。下面是测试的结果:Private类模块中,反复调用1,000,000次Public Sub或者Function耗费了0.46秒,而调用内容相同的Friend类型模块则分别只有0.05秒和0.06秒。前后竟然相差了8-9倍之多!对于MultiUse类型的Public类模块,也是一样的结果。对于这个不可思议的结果的可能解释是:Friend型过程没有处理汇集和拆装代码的消耗(Public过程可以从当前工程外被调用,因此COM必须要来回地汇集数据)。但是在多数情况下,这些时间差别是不明显的,特别是程序中包含一些复杂和耗时的语句时。即使这样,Friend型过程仍有其他的优势高于Public类型,比如:接受和返回在BAS模块中定义的UDT变量的能力。
    使用Objptr函数快速查找集合中的对象 ObjPtr函数的一个最简单但是却最有效的用途就是提供快速寻找集合中对象的关键字。假设有一个对象集合,它没有可以当做关键字以从集合中取回的属性。那么,我们就可以使用ObjPtr函数的返回值作为集合中的关键字: Dim col As New Collection Dim obj As CPerson ’创建新的CPerson对象,并添加到集合中 Set obj = New CPerson obj.Name = "John Smith" col.Add obj, CStr(ObjPtr(obj)) ’关键字必须是字符串 因为任何对象都有一个明确的ObjPtr数值,而且它是不变的,所以,我们可以容易地、快速地从集合中取回它: ’ 删除集合中的对象 col.Remov