总结了一些Visual Basic的应用与操作技巧,并对其强大的程序调试功能进行了介绍,用于读者在案例开发过程中参考。
在程序编写过程中,即使是最出色的设计人员,也难免会被这样或那样的问题所困扰,本节以FAQ的形式列举了一些在使用Visual Basic过程中的常见问题,以期为读者释疑解惑。
(1) 编程中经常碰到API,请问API的意义是什么?
答: API是Application Programming Interface(应用编程接口)的缩写,也就是应用程序调用系统功能的接口。Windows API主要包括由Windows系统定义的函数、消息及与之相关的数据类型。使用各种开发工具归根结底都是和API打交道。但是API本身比较难掌握,所 以Visual Basic提供了可视的面向对象的控件,初学者即使不太了解API,也可以编写Windows程序。但是Visual Basic提供的控件毕竟是有限的,不可能包括API的所有方面,所以一些复杂的功能仍然需要调用API来实现。
(2) 问要在VB的主窗体中装入一幅事先选好的图片,程序运行后可以在图片上进行修改并保存它,以备以后调用。请问怎样办?
答 :可以把Form或PictureBox的AutoDraw属性设为True,进行修改后使用VB的SavePicture语句进行存盘。 如:SavePicture Picture1.Picture, “c:\test.bmp”这种存盘的文件为.bmp文件,颜色数与当前屏幕的色彩数相同。如果你的存盘要求很高,希望控制存盘格式,只能借助于其他控 件,比如ImageMan(http://www.data -tech.com下载)、Lead Tools(http://www.leadtools.com 下载)等。
(3) 问:若在一个窗体中设置了两个命令按钮Command1和Command2。Commamd1执行一个费时的操作,包括调用多个过程和函数;而Command2则是终止/暂停Command1的运行,不是退出该程序。不知用VB如何解决?
答:你可以采用一种变通的方法,在程序中定义一个Boolean变量,在执行command1中的程序时监视该变量,如果为False退出程序;在command2中加入代码,只要点击command2就将该变量设置为False。下面是示例程序。
Dim bMark As Boolean
Private Sub Command1_Click( )
bMark = True
For I = 1 To 150000 ' Start loop.
DoEvents ' Yield to operating system.
Text1.Text = Str(I)
If Not bMark Then
Exit Sub
End If
Next I ' Increment loop counter
End Sub
Private Sub Command2_Click( )
bMark = False
End Sub
(4) 问 :我在为一数组赋值时出现如下错误:“实时错误9——下标越界”。出错的代码如下:
Dim inputdata( ) As Single
inputdata(0) = Text2(0).Text / Text2(1).Text '注释:入学率
请问为何会出现这种错误?
答: VB在使用数组前必须指定数组的大小。一种办法是在定义时确定大小,如:Dim InputData(10) As Single,另一种是采用动态数组。对于你的程序,数组声明部分可以不用修改,而在出错语句前加一句:ReDim InputData(10) As Single
(5) 问 :在按下右上角的关闭键后,怎样避免当前窗口被关闭?
答: 在按下关闭键后,会发生Form_Unload和Form_QueryUnload事件。这两个事件都有个Cancel参数,如果在事件处理过程中将其设 为True就可以避免窗口被关闭。对于你的问题,Form_QueryUnload事件可能更好些,因为它有一个UnloadMode参数可以区分关闭窗 口的指令是用户做出的,还是系统做出的,或者是本程序代码产生的。
(6) 问 :我是第一次编写ActiveX DLL程序,在DLL中,我只在类模块中写了一个函数CARD,编译成DLL后,在另外一个程序中调用,在模块中声明:
Public Declare Function card_config Lib "c:\test\card.dll" (ByVal address As Integer, ByVal intermit As Integer)
在一个按钮中写如下代码:
c = card_config(12,12)
运行后出现错误;编译Activex DLL后,调用时出现错误:“实时错误453,找不到DLL入口点”。
答: Declare语句只能用来调用标准DLL,而不能用于调用ActiveX DLL,这是你程序出错的原因。VB无法生成标准DLL,只能生成ActiveX DLL。要调用ActiveX DLL,一般通过CreateObject语句调用,或在集成环境中选择菜单“工程”→“引用”,在对话框中选择你要调用的ActiveX DLL。这样你就可以在程序中使用ActiveX DLL中定义的对象或函数。
(7) 问: 怎样在VB中启动其他Windows应用程序,例如记事本?
答: 你可以使用VB的Shell函数调用其他应用程序。如:
Shell“Notepad.exe c:\autoexec.bat”
(8) 问 :如何打印 MSChart 控件中的内容?
答: MSChart本身没有打印功能,所以必须先用EditCopy将图像放在剪贴板中,然后再打印,如:
MSChart1.EditCopy
Printer.Print ″ ″
Printer.PaintPicture Clipboard.GetData(), 0, 0
Printer.EndDoc
(9) 问 :VB中的进制转换是怎样的?
答:用函数Oct()将十进制位数 转换为八进制,用Hex()将十进制位数转换为十六进制,不过值得注意的是,转换后数字型变为字符型。如果是一个变量可以用如下代码完成十 进制向其他进制转换的目的。
dim Anum as long
Anum=& 010 '&0是八进制的,表示符号Anum自行转换为8
Anum=&HA '&H是十六进制的,表示符号Anum自行转换为10
如果有一个字符变量Astring 为八进制的或十六进制的,用Anum=” &0” + Astring和Anum=“&H”+Astring 能将它转换为十进制。
VB中用如下代码可以实现十进制到二进 制的转换:
Option Explicit
Ptivate FunctiOn TenturnTwo (ByVal varNum As Long)
Dim returnString As String,ModNum As Integer
DO While varNum>0
ModNum=varNum Mod 2
varNum=varNum\2
returnString=Trim(Str (ModNum))+returnString
Loop
TenturnTwo=returnString
End Function
Private Function TwoturnTen (ByVal varString As String)
Dim Slen As Long,I As Long,
returnNum As Long
Slen=Len(varString)
For I=o To Slen-1
returmNum=returnNum +Val(Mid (varString,I+1,1))*(2^(Slen-I-1))
Next
TWoturnTen=returnNum
End Function
(10) 问:如何让文本框只接受数字?
答:使用如下代码,在文本框的按键事件中加入:
Private Sub Textl_KeyPress(KeyAscii As Integer)
If keyAscii>=33 Then
If KeyAscii<=vbkey9 And KeyAscii>=vbKey0 Then
Else '把KeyAscii设为0就是取消输 入。
KeyAscii=0
MsgBox ”不要输入数字!”
End If
End If
End Sub
注意:KeyAscii键值与KeyCode 相同,可以查看KeyCode值,不过有些KeyCode键值必须在 KeyDown和KeyUp中才有效,在 KeyPress的KeyAscii中没用。利用 KeyAscii=0的方式在KeyPress中有用,但在KeyDown中让KeyCode=0 就不行了。
(11) 在VB5.0下,如何用程序改变中文与英文的输入方式?
答:VB5.0在可以输入文字的地方(如TextBox,ListBox,ComBox... 等)有一个输入法切换属性IMEMode。们可以先用ImeStatus函数来检测当前的输入状态,并用IMEMode来控制其输入状态。 下面是IMEMode的属性值。
Text1.IMEMode=0(预定值)
Text1.IMEMode=l(切换为中文输 入)
Text1.IMEMde=2(切换为英文输 入)
Text1.IMEMde=3(关闭中文输入 的功能,也就是只能做英文输入)
(12) 问:如何编程使文本框中文本的某一特定字符或字符串同时高亮显示?
答: 由于普通TextBox控件不支持不连续字符串的同时高亮显示,所以选择RichTextBox控件。 新建一工程,在窗体上添加一个RichTextBox控件和两个Command(按钮)控件,都采用系统默认的Name属性值;设置 RichTextBox的Text属性值为空,Command1和Command2的Caption属性值分别设为“输入文本”和“选择字符串”。最后, 添加如下VB代码:
Private Sub Command1—Click( )
Dim str As String
Dim Text As String
str=″输入文本″
Text=InputBox(str)
RichTextBox1.Text=Text
End Sub
Private Sub Command2—Click( )
Dim str As String
Dim Text As String
Dim Position As Integer
Dim Lenth As Integer
str=″输入要高亮显示的字符串″
Text=InputBox(str)
If Text 〈〉 ″ ″ Then
Position=InStr(RichTextBox1.Text, Text)-1
Lenth=Len(Text)
RichTextBox1.SelStart=Position
RichTextBox1.SelLength=Lenth
RichTextBox1.SelColor=RGB(255,0,0)
Do While InStr(Position+Lenth+1, RichTextBox1.Text, Text) 〈〉 0
Position=InStr(Position+Lenth+1, RichTextBox1.Text, Text)-1
RichTextBox1.SelStart=Position
RichTextBox1.SelLength=Lenth
RichTextBox1.SelColor=RGB(255,0,0)
Loop
End If
End Sub
按 F5执行程序,单击“输入文本”按钮,在弹出的对话框中输入一些文本,确定后,刚刚输入的文本将显示在RichTextBox中;再单击“选择字符串”按 钮,在弹出的对话框中输入你希望高亮显示的字符串,确定后,RichTextBox中相应的字符串将以红色高亮显示。
(13) 问:如何把数据文件输出到Text控件中?如果数据量比较大,窗体满屏也不够大,怎么解决?
答: 有一个比较简单的方法,就是把数据放到一个文本框(Text)里,并在其中加上水平和垂直滚动条。具体实现步骤为:先在窗体(Form)里加入一个文本 框,采用默认名Text1;然后,设置文本框Text1的属性:Text属性设置为空,MultiLine属性设置为True,ScrollBars属性 设置为3-Both;接着添加如下VB代码:
Private Sub Form—Load()
Dim Handle As Integer
Dim FileName As String
On Error GoTo ErrExit
begin:
′输入要显示的数据文件的名称
FileName=InputBox$(″Input Filename″,
″Open File″)
On Error GoTo FileErr
Handle=FreeFile
Open FileName For Input As #Handle
′把数据文件中的数据输出到文本框中
Text1.Text=Input$(LOF(Handle), Handle)
Close #Handle
Exit Sub
FileErr:
Dim ErrNum As Integer
If Err.Number=53 Then
ErrNum=MsgBox(″File not exist″, vbOKCancel, ″Error Information″)
If ErrNum=1 Then
GoTo begin
Else
Exit Sub
End If
End If
MsgBox Err.Description, , ″file open failed″
ErrExit:
Exit Sub
End Sub
′使文本框充满整个窗体
Private Sub Form—Resize()
Text1.Left=0
Text1.Top=0
Text1.Width=Form1.Width-100
Text1.Height=Form1.Height-400
End Sub
通过这样的处理,不仅能解决问题,而且用户还可以在文本框中对数据进行编辑。
(14) 问:想做一个对话窗体,包含驱动器列表框、目录列表框和文件列表框,并能实现三者的同步操作,怎么做?
答:在实际应用中,经常会遇到上述问题,在VB中解决这个问题非常简单,可以通过Path属性的改变引发Change事件来实现。例如:
Sub Dir1—Change( )
File1.Path=Dir1.Path
End Sub
该事件过程使窗体上的目录列表框Dir1和文件列表框File1产生同步。因为目录列表框Path属性的改变将产生Change事件,所以在Dir1的Change事件过程中,把Dir1.Path赋给File1.Path,就可以产生同步效果。
类似地,增加下面的事件过程,就可以使三种列表框同步操作:
Sub Drive1—Change( )
Dir1.Path=Drive1.Drive
End Sub
该过程使驱动器列表框和目录列表框同步,前面的过程使目录列表框和文件列表框同步,从而使三种列表框同步,问题即可解决。
(15) 问:怎样在VB中实现动画窗口?
答:下面就来看一下动画窗口的实现步骤。其中hwnd是指定产生动画窗口的句柄。dwTime指定动画持续的时间,以毫秒为单位。DwFlags指定动画类型,这个参数可以是一个或多个下列标志的组合。
标志描述:
AW_SLIDE:值为&H40000,使用滑动类型。当使用AW_CENTER标志时,这个标志被忽略。
AW_BLEND:值为&H80000,使用淡出淡入,Windows 2000中使用。只有当hWnd为顶层窗口的时候才可以使用此标志。程序只需一个窗体即可
窗体的代码
Private Declare Function AnimateWindow Lib "user32" (ByVal hwnd As Long, ByVal dwTime As
Long, ByVal dwFlags As Long) As Boolean
Private Const AW_HOR_POSITIVE = &H1 '自左向右显示窗口
Private Const AW_HOR_NEGATIVE = &H2
'自右向左显示窗口
Private Const AW_VER_POSITIVE = &H4
'自上而下显示窗口。
Private Const AW_VER_NEGATIVE = &H8
'自下向上显示窗口。
Private Const AW_CENTER = &H10
Private Const AW_BLEND = &H80000
Private Sub Form_Load()
Randomize Timer
x = Int(6 * Rnd + 1) '取随机整数
Select Case x '根据随机数选择相应的动画过程
Case 1
flag = AW_HOR_NEGATIVE
Case 2
flag = AW_HOR_POSITIVE
Case 3
flag = AW_VER_NEGATIVE
Case 4
flag = AW_VER_POSITIVE
Case 5
flag = AW_CENTER
Case 6
flag = AW_BLEND '只在Windows 2000中起作用
End Select
AnimateWindow Form1.hwnd, 200, flag
Me.Refresh
End Sub
注意:在Windows 98中动画过程会使动画的窗口出现杂乱图形,Windows 2000中会出现黑色的窗口,用Refresh清除。
(16) 问:如何用VB做一个聊天的程序?
答:所谓“聊天”是指两个程序能够发送数据给对方。这个程序涉及到数据通信的知识,仿佛很复杂,不过,由于VB给我们提供了一个winsock控件,问题就变得很简单了。
首 先编写“聊天(主机)”程序。在窗体里添加winsock控件,并设置其protocol属性为1-sckudpprotocol,其他属性为默认值。接 着添加两个标签和两个文本框,设置两个标签的标题属性分别为“接收窗”和“发送窗”;两个文本框的标题属性为空。最后编写代码:
(1)“聊天(主机)”
private sub form—load()
′设置网络地址
winsock1.localport=1024
winsock1.remotehost="202.96.6.1"
winsock1.remoteport=1999
end sub
private sub text1—change()
′发送用户输入的内容
winsock1.senddata text1.text
end sub
private sub winsock1—dataarrival(byval bytestotal as long)
dim rec as string
′接收对方数据并在文本框内显示
winsock1.getdata rec, vb string
text2.text=rec
end sub
(2) “聊天(副机)”
private sub form_load()
′设置网络地址
winsock1.localport=1999
winsock1.remotehost="202.96.6.1"
winsock1.remoteport=1024
其他部分程序与(主机)相同。最后将两个程序存盘,并编译成可执行文件。现在就可以使用这个程序进行对话了。
(17) 问:如何关于关闭程序?
答: 也许大家会说关闭程序不是很简单吗,用end语句即可。事实上,用end语句关闭程序并不是一个很好的方法,end语句虽然可以结束程序,但并不能把窗体 完全从内存中移走,造成的结果是窗体还占用着部分资源;完全释放所占资源的方法还是使用unload语句,然后使用 set form = nothing 语句。如果程序中窗体较多,可以使用下面的方法一次将所有窗体移走:
sub unloadallforms( )
dim form as form
for each form in forms
unload form
set form = nothing
next form
end sub
上面这个函数采用窗体对象的方法,不需要一个一个地使用unload语句,在程序结束按钮中调用它即可。
(18) 问:如何使一副小的图片填充整个窗体的背景?
答:有很多种方法可以实现。 下面就讲两种最常用的方式:
l 用窗体自己的(PaintPicture)方法
l 用 Windows 的 API 函数 BitBlt
下面是这两种方法的示例:
l 程序需要一个窗体、一个图片(Image)控件
Private Sub Form_Paint( )
Dim X As Long, Y As Long
Me.ScaleMode = 3
Picture1.BorderStyle = 0
Picture1.ScaleMode = 3
Picture1.AutoRedraw = True
With Me
.AutoRedraw = True
For X = 0 To .ScaleWidth \ Picture1.Width
For Y = 0 To .ScaleHeight \ Picture1.Height
Call Me.PaintPicture(Picture1.Picture, X * Picture1.Width, Y *
Picture1.Height)
Next
Next
End With
Picture1.Visible = False
End Sub
Private Sub Form_Resize( )
Form_Paint
End Sub
l 第二种方法
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Const SRCCOPY = &HCC0020 ' (DWORD) dest = source
Private Sub Form_Paint()
Dim X As Long, Y As Long
Me.ScaleMode = 3
Picture1.BorderStyle = 0
Picture1.ScaleMode = 3
Picture1.AutoRedraw = True
With Me
.AutoRedraw = True
For X = 0 To .ScaleWidth \ Picture1.Width
For Y = 0 To .ScaleHeight \ Picture1.Height
BitBlt Me.hDC, X * Picture1.Width, Y * Picture1.Height, Picture1.Width,
Picture1.Height,
Picture1.hDC, 0, 0, SRCCOPY
Next
Next
End With
Picture1.Visible = False
End Sub
Private Sub Form_Resize( )
Form_Paint
End Sub
以上两种方法可任选一种。