浅谈VB6.0中的实用技巧 (一)
VB6.0中文本框处理技巧
在Visual Basic中,文本框(TextBox)是最常用的控件,熟练运用文本框
是开发出高质量的应用程序的基础。笔者在从事应用程序开发中,摸索出有关文
本框的应用技巧,写出来与VB爱好者共享。
1、设置只读文本框。
有些时候在窗口显示一段信息,但又不希望用户去改变它,怎样实现文本的
只读呢?首先,我们可以利用标签框( label )的只读属性,以标签来代替文本
框以实现只读属性,但也可以用小程序实现真正的文本框的只读。
Sub Text1_KeyPress (keyascii As Integer)
keyascii = 0
End Sub
或者也可以用sendkey方法使文本框失去焦点,如以下程序:
Sub Text1_KeyDown (KeyCode As Integer, Shift As Integer)
SendKeys "{tab}"
End Sub
2、限定文本框的输入内容和格式。
以下程序可以实现限定文本框只能输入数字:
Sub Text1_KeyPress (keyascii As Integer)
If keyascii <48 Or keyascii> 57 Then
Beep
Beep
johny@nease.net
keyascii = 0
End If
End Sub
若想限定文本框输入格式,可以使用VB的FORMAT函数,也可以使用专业版的
屏蔽控件(Masked Edit),通过设定屏蔽控件的Mask属性可以对文本框的输入格式
作精确控制。
3、为TextBox 创建快捷键。
VB规定,添加在窗体上的控件均在其Tabindex 属性中记载其加载顺序,程序
运行时焦点按Tabindex 属性规定的顺序在控件间跳转。而为了简化操作,可VB中
为任何具有 caption的属性的控制创建快捷键,这通过caption 属性中在想作为
快捷键的字母前加&号实现。但有一个问题值得注意,而类似文本框这样的控件无
caption 这样的属性,这时可将标签与文本框同时使用。为 lable创建快捷键,
标签 Tabindex 属性设置比文本框小1,又因为label 不能接收按点,焦点会自动
跳至文本框。这相当于为文本框创建了快捷键。具体步骤如下:
(1) 首先绘制标签,再绘制文本框。或随意绘制各种控制,将标签 Tabindex
属性设置比文本框小1
(2) 在标签的caption 属性中使用“&”号设定快捷键
这样就相当于为文本框设定了快捷键,当你按下标签框的快捷键时,焦点就会跳
至文本框上。
4、在设计时实现文本框换行。
对于文本框,在设计时properties 窗口不能输入换行符,但可以再程序执行时
用代码来换行,即使用 ASCII字符的13和10,如下列小程序就可将两行文本放入文本框:
Sub form_load( )
NL=chr(13)+chr(10)
text1.text=“my name is ”& NL & “ liu qiang”
End sub
5、创建口令文本框。
创建口令文本框可用设置属性的方法,也可以通过调用WINDOWS的API应用函数接口
来实现。首先,文本框的属性 Passwordchar和maxlength 可用来设置口令框。其中 Passwordchar 指定文本框显示的字符,如指定“*”,则在文本框内显示“*”,
Maxlength确定文本框中能输入几个字符。超过Maxlength以后,文本框发出警告声,
不能接收更多的字符。若使用WINDOWS应用函数接口,可用GetWindowLong、
SetWindowsLong和SendMessage等接口函数来实现,有兴趣的读者可查阅Windows
API函数手册或VB的联机帮助文件就可以了。
改变 ListIndex而不发生 Click 事件
在修改 Combo 或 Listview 的ListIndex 时, 会发生 Click 事件,
下面的函数可以阻止该事件。
声明:
Private Declare Function SendMessage Lib _
"user32" Alias "SendMessageA" (ByVal _
hWnd As Long, ByVal wMsg As Long, ByVal _
wParam As Long, lParam As Any) As Long
Const CB_GETCURSEL = &H147
Const CB_SETCURSEL = &H14E
Const LB_SETCURSEL = &H186
Const LB_GETCURSEL = &H188
函数:
Public Function SetListIndex(lst As Control, _
ByVal NewIndex As Long) As Long
If TypeOf lst Is ListBox Then
Call SendMessage(lst.hWnd, _
LB_SETCURSEL, NewIndex, 0&)
SetListIndex = SendMessage(lst.hWnd, _
LB_GETCURSEL, NewIndex, 0&)
ElseIf TypeOf lst Is ComboBox Then
Call SendMessage(lst.hWnd, _
CB_SETCURSEL, NewIndex, 0&)
SetListIndex = SendMessage(lst.hWnd, _
CB_GETCURSEL, NewIndex, 0&)
End If
End Function
调整 Combo 下拉部分的宽度
声明:
Private Declare Function SendMessage Lib _
"USER32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Private Const CB_GETDROPPEDWIDTH = &H15F
Private Const CB_SETDROPPEDWIDTH = &H160
Private Const CB_ERR = -1
函数:
' 取得 Combo 下拉的宽度
' 可以利用该函数比例放大或缩小宽度
Public Function GetDropdownWidth(cboHwnd As Long) As Long
Dim lRetVal As Long
lRetVal = SendMessage(cboHwnd, CB_GETDROPPEDWIDTH, 0, 0)
If lRetVal <> CB_ERR Then
GetDropdownWidth = lRetVal
'单位为 pixels
Else
GetDropdownWidth = 0
End If
End Function
'设置 Combo 下拉的宽度
'单位为 pixels
Public Function SetDropdownWidth(cboHwnd As _
Long, NewWidthPixel As Long) As Boolean
Dim lRetVal As Long
lRetVal = SendMessage(cboHwnd, _
CB_SETDROPPEDWIDTH, NewWidthPixel, 0)
If lRetVal <> CB_ERR Then
SetDropdownWidth = True
Else
SetDropdownWidth = False
End If
End Function
Combo的自动查询技术
Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long,
lParam As Any) As Long
Public Const CB_FINDSTRING = &H14C
Private Sub Combo1_Change()
Dim iStart As Integer
Dim sString As String
Static iLeftOff As Integer
iStart = 1
iStart = Combo1.SelStart
If iLeftOff <> 0 Then
Combo1.SelStart = iLeftOff
iStart = iLeftOff
End If
sString = CStr(Left(Combo1.Text, iStart))
Combo1.ListIndex = SendMessage(Combo1.hwnd, _
B_FINDSTRING, -1, ByVal CStr(Left( _
ombo1.Text, iStart)))
If Combo1.ListIndex = -1 Then
iLeftOff = Len(sString)
combo1.Text = sString
End If
Combo1.SelStart = iStart
iLeftOff = 0
End Sub
静态变量 iLeftOff 指定了字符长度。
自动选择 Text 的内容
在使用 VFP 的应用进行录入时,每进入一个录入框,就自动选择
该框中的所有内容。利用以下的代码,也可实现类似的功能。
Private Sub MyTextBox_GotFocus()
AutoSelect MyTextBox
End Sub
Sub AutoSelect(SelObject As Control)
SelObject.SelStart = 0
If TypeOf SelObject Is MaskEdBox Then
SelObject.SelLength = Len(SelObject.FormattedText)
Else
If TypeOf SelObject Is TextBox Then
SelObject.SelLength = Len(SelObject.Text)
End If
End If
End Sub
捕捉 MouseExit 事件
MouseDown、MouseUp、MouseMove。VB 似乎提供了很好的 Mouse 事件。
但好象还缺少什么!对!还差 MouseExit(鼠标移出)事件。在 VB 中,我
们要捕捉 MouseExit 事件,必须用 API 函数:
Private Declare Function SetCapture Lib "user32" (ByVal hWnd As Long)
As LongPrivate Declare Function ReleaseCapture Lib "user32" () As Long
然后,我们可以在控件(以 Picture1 为例)的 MouseMove 事件上加上以下代码:
Dim MouseExit As Boolean
MouseOver = (0 <= X) And (X <="Picture1.Width)" And (0 <="Y)" And (Y <="Picture1.Height)<Br"> If MouseExit Then
……..
SetCapture Picture1.hWnd
Else
……..
ReleaseCapture
End If
如何让文本框输入完后,直接跳入下一行?
我们在编制程序的时候,特别是数据库软件,经常会遇到这样一个问题:
在文本框中输入完后,用户习惯性的按下回车键。但是系统“嘀”的一声,
并没有象想象那样跳入下一行或者其他的什么。那么能不能让程序在输入完
后干其他的事呢?试一试下面的代码吧。
Sub Text1_keyPress(KeyAscii As Integer)
If KeyAscii=13 Then
SendKeys"{tab}"
End If
End Sub
如何强制文件对话框再次读取正确的磁盘?
如果构造了一个以通用对话框为模型的简单对话框(通常应使用通用对话框
的OCX),会发现再次选择软盘驱动器并不实际.再次读盘,改变到C盘,并再次选择
A盘.只是使它读新软盘中的目录.
为了解决这个问题,在一个按钮的代码段中加入以下代码:
drive1.refresh
dir1.refresh
file1.refresh
VB6.0的OPEN对话框控件图示功能扩充
Visual Basic For Windows(VB)提供了丰富的控件,但其提供的公用
对话框控件在打开文件时(例如*.Bmp和*.Pcx等)不能显示文件内容即图
像,本文给出了一个实例,可以模拟一些图形软件包在打开文件的同时显示图
像,模拟和扩充OPEN控件功能。
为模拟的扩充OPEN功能,下面给出了一个完整的VB程序,实现方法如下:
一、建立窗体
首先建立一个窗体(窗体名为OPNFILE),窗体上包含驱动器列表、目录
列表、文件列表、两个命令按钮(确认、取消)和显示影像的控件(picture或image),
下面是这6个控件的建立方法和有关属性的改变。
1、DirvelistBox驱动器列表控件
双击驱动器列表控件,在窗体上调准控件的位置,控件名称为“Drive1”。
2、DirlistBox目录列表控件
双击目录列表控件,在窗体上调准控件的位置,控件名称为“Dirl”
3、FilelistBox文件列表控件
双击文件列表控件,在窗体上调准控件的位置和尺寸,控件名称为“Filel”,
修改“Pattern”属性为“*.bmp, *.pcx”。
4、Command Buttom命令按钮控件
双击命令按钮控件,建立命令按钮,第一个取名为Command1,修改Caption
属性为“确认”,第二个取名为Command2,修改Caption属性为“取消”。
5、显示影像的控件
既可以选picture控件,也可选image控件显示图像,以image控件为例。双击
image控件,调准矩形框的大小和位置,取名为imagel,设置strtch属性。
Strech=false时,图形以原尺寸显示。
二、事件过程的建立
1、驱动器更改事件过程
Sub Drive-change()
①Dirl.Path=Drivel.Drive
②ChDrive.Path= Drivel.Drive
End Sub
其中①当驱动器发生更改时,改变目录路径;②更改路径。
2、目录更改事件过程
Sub Dirl change()
Filel.Path=Dirl.Path
End Sub
该事件过程是对目录发生更改时,作出文件路径更改的响应。
3、文件列表单击事件
Sub Filel-click()
Imagel.Picture=loadpicture(Filel.path+”\”+Filel.FileName)
End Sub
单击任一图形文件名时,在image控件框上显示图像。
4、命令按钮控件
Sub Command1-click()
F1$=Filel.Path+”\”+FileName
End
End Sub
Sub Command2-click()
F1$=” ”
End Sub
F1$为选择文件名称,供软件使用,若用户单击“取消”按钮,F1$为空串。
单击驱动器名可以改变驱动器,单击目录列表中某一目录可以更改目录,单击
某一图形文件可以显示图形,在文件列表中按“↑”或“↓”键,可以随着文件名
的变化,图像框中的图形也随之发生更改。
F1$可以供应用程序调用,其中包含驱动器名、目录和文件名。
VB6.0网格中输入数据
VISUAL BASIC提供的网格控制(Grid)主要是用来直观地输出数据,但不能
输入数据,使用起来很不方便。能不能向网格中输入数据呢?笔者提出了两种解决
方法,供大家参考:
方法一:
改写网格的KeyPress事件,在每次有合法字符输入时,把Grid的Text项和输
入字符连接。这种方法缺点是:一代码较复杂,需要处理各种ASCII字符信息;
二是通过编程只能实现很少的编辑功能,如用退格键删除前一字符,用Del键删除
所有字符;三是这种方法不能输入汉字,使用起来受到很大的限制。
方法二:
利用一文本框作为缓冲,实现编辑功能。当网格改变行列时,把网格当前行列
的内容传递给文本框;当网格中有ASCII字符产生时,把输入焦点设置为文本框,
并把输入的ASCII字符送给文本框;当编辑完文本框的内容时,按Enter键或TAB键,
把文本框的内容送给网格的当前行列,并把输入焦点设置为网格。如下程序所示
(其中Textl为文本框,Labell为标签,Gridl为网格):
Option Explicit
Const EnterAsc=13
Const TabAsc=9
Private Sub Form-Load()
Labell.Caption=”请输入”
End Sub
Private Sub Gridl-KeyPress(KeyAscii As Integer)
Text1.StFocus
Textl.SelStart=0
If KeyAscii <> EnterAsc And KeyAscii <> TabAsc Then
SendKeys Chr (KeyAscii)
End IF
End Sub
Private Sub Gridl-RowColChange()
Textl.Text=Grid1.Text
End Sub
Private Sub Text1-KeyPress(KeyAscii As Integer)
If KeyAscii=EnterAsc Then
Grid1.SetFocus
KeyAscii=0
End If
End Sub
Private Sub Text1-LostFocus()
Grid1.Text=Text1.Text
End Sub
如何使VB的网格控件具有输入功能
我们在使用Visual Basic for Windows开发时,经常用到网格控件(Grid.vbx),
因为此控件可以用来作类似于电子表格形式的输出表,且编程简单,但在此网格控件
只有输出功能,而不能直接在网格上输入,这给使用者带来一些不便。如何在执行时
向网络控件中输入数据,人们使用了一些方法,但大都使用一文本控件作中间转换,
即将欲输入的信息先输入到该文本控件,然后将文本控件的TEXT属性赋给网格的TEXT
属性,这种方法尽管解决了向网格输入数据问题,但增加了一文本框,对界面有些不
美观,修改部分数字不方便,且影响速度,那么,如何直接向网格输入数据呢?
本文将解决直接向网格输入数据问题,基本思想是:使用网格控件KeyPress事件,
从键盘上接收所击键位的KeyAscii值,再由Chr$()或Chr()函数转换成字符,
然后读出网格单元的当前Text值与由键盘接收到的字符相加,组成新的字符串,再赋给
该单元的Text属性,即Grid.Text=Grid.Text+Chr$(KeyAscii)。程序清单如下:
程序中定义了两个Form级变量WgridCol%和WgridRow%。
Sub Grid-KeyPress(KeyAscii as Integer)
Grid.Col=WgridCol%
Grid.Row=WgridRow%
if KeyAscii=8Then `keyascii=8为退格删除键
if Grid.Text<>””Then Grid.Text=Mid$(Grid.Text,
1,Len(Grid.Text)-1)‘删除最后一个字符
Else
Grid.Text=Grid.Text+Chr$(KeyAscii)
End if
End Sub
Sub Grid-RowColChange()
Wgrid.Col%=Grid.Col
Wgrid.Row%=Grid.Row
End Sub
这样就可以实现对网格的任意输入,可以输入字符、数字等等。由于数字0到9的
Ascii值为48到57,小数点Ascii的值为46,所以可以输入任意实数。若您想防止用户
输入除数字、小数点以外的任何其他字符,可对来自于键盘的Ascii值进行判断,有条
件地接收,就实现了仅输入数值字符。同理也可以限制只输入字母字符。
根据这种思想,也可以对VB中一切不具有输入功能,但具有KeyAscii或者KeyDown
事件的控件进行直接输入,如标签Label等。
防止文本控件中的部分滚动
大家知道,Windows API的SendMessage函数可以用来向VisualBasic
控件中发送消息,例如向文本框控件上发送消息。现介绍如何利用该函数防
止文本框控件中的部分文本滚动,即该控件中不能滚动的部分不能被用户看
见。发送消息到文本框控件
Visual Basic中的文本框控件就是一个最小化的字处理程序。当该文本
控件的MultiLine属性被设置为True的时候,则文本可以自动换行;当在文本
框控件中键入了许多文本时,控件中的文本会向上滚动。这时文本就变得看不
到了,但这些文本实际上仍然在控件中——它们并没有被删除。
Windows API的SendMessage函数可以用来防止文本框控件中的文本滚动
因而超出我们的视线。当创建该文本框控件时,它的客户区域格式化为一个矩
形(该区域就是键入文本的地方),可以给该控件发送EM_SETRECTNP消息,对
该矩形区域进行限制,以在文本框的客户区域中指定一个特定区域。
在下面的样例程序中,我们希望文本控件的后一半原封不动地保持完整,
即不希望文本滚动而超出视线。可以从文本框控件的Height属性中提取出它的
高度,并将该值除以2,得到该文本框控件后一半的坐标。然后将该结果传递给
SendMessage函数,告诉EM_SETRECTNP防止该矩形区域滚动。
有些程序员可能会希望使用EM_SETRECT消息代替EM_SETRECTNP消息。但是,
使用EM_SETRECT消息会停止Windows对该格式化矩形区域中的文本的重新绘制,
导致文本框控件中的文本会看不到。
样例程序
该程序显示了如何临时冻结一个文本框控件中的特定部分,该部分包含的文本
不能滚动,因而不会超出视线之外。
1.在VisualBasic中开始一个新的工程,采用缺省的方法建立Form1。
2.将如下常量和声明语句添加到Form1的通用声明部分中(注意该声明语句需
要书写在一行内):
Private Declare Function SendMessage Lib "User"
(ByVal hWnd As Integer, ByVal wMsg As Integer,
ByVal wParam As Integer, lParam As Any) As Long
Const WM_USER = &H400
Const EM_SETRECTNP = WM_USER + 4
Const EM_SETRECT = WM_USER + 3
对于32位环境下使用Visual Basic5.0的用户,需要将如下声明语句添加到
Form1的通用声明部分中:
Private Declare Function SendMessage Lib "user32"
Alias "SendMessageA" (ByVal hwnd As Long, ByVal
wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Const EM_SETRECTNP = &HB4
Const EM_SETRECT = &HB3
3.将如下代码添加到Form1的Form_Load事件中:
Private Sub Form_Load()
Text1.Text = " 这 是 我 们 希 望 显 示 出 来 的 第 一 段"
Text1.Text = Text1.Text & " 它 位 于 文 本 框 控 件 中"
Text1.Text = Text1.Text & Chr$(13) & Chr$(10) & " 这是第二段,我们"
Text1.Text = Text1.Text & " 希望将之冻结以使文本不能滚动 "
End Sub
4. 将如下代码添加到Form1的Click事件中:
Private Sub Form_Click()
Dim R As RECT
Dim X As Long
ScaleMode = 3
R.Left = 0
R.Top = 0
R.Right = Text1.Width
R.Bottom = Text1.Height / 2
X = SendMessage(Text1.hWnd, EM_SETRECTNP, 0, R)
End Sub
5.创建一个新的模块。采用缺省的方法建立Module1.Bas。
6.将如下TYPE结构添加到Module1.Bas中:
Type RECT
Left As Integer
Top As Integer
Right As Integer
Bottom As Integer
End Type
对于32位环境下使用Visual Basic 5.0的用户,需要将如下TYPE结构添加到Module1.Bas中:
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
7.在Form1上添加一个文本框控件,采用缺省的方法建立Text1,将其MultiLine
属性设置为True。
按下F5来执行该程序,我们可以看到文本框显示在Form1上。在窗体上单击一次
鼠标,将新的文本键入到该文本框控件中。这时我们可以注意到,当我们在文本框控件
的开头处键入新的文本时,在文本框控件下半部分的文本不会滚动。
如果我们将EM_SETRECT消息替代EM_SETRECTNP消息发送给文本框,再次运行该程
序,这时我们会发现,文本框的下半部分显示不出来,尽管实际上文本仍然是存储在控
件中的。
防止用户编辑文本框控件中的内容
Visual Basic中的文本框控件允许用户在其中键入文本,以便在程序中使用。
相反,程序员可能会希望显示一些文本但不希望用户编辑该文本。本文介绍了如何创建
只读的文本框控件的内容。
使一个文本框控件只读
在Visual Basic中,如果文本框控件的MultiLine属性设置为True,文本将会自动
地换行到下一行。另外,如果文本框控件的ScrollBars属性设置为3-Both
(或者1-Vertical,或者2-Horizontal),用户还能够滚动控件中的内容。
程序员要想实现文本框控件中的文本不可编辑,可将文本框控件中的内容设置为只
读状态,这可以通过使用Microsoft Windows 应用程序编程接口(API)的SendMessage
函数来实现。SendMessage函数可以用来发送一个EM_SETREADONLY消息到文本框控件中,
这将使文本框控件变为只读。
要在程序中使用该SendMessage函数,需要将如下的声明语句包含在项目的通用声明
部分中(注意该声明语句需要书写在一行内):
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Long) As Long
该SendMessage 函数需要4个参数,如下所示:
hwnd一个长整数值,它包含文本框控件的句柄。
wMsg一个长整数值,它包含被发送的消息,在这个例子里,是EM_SETREADONLY。
wParam一个整数值,如果它为True,则控件被设置只读标记,如果它为False,
则删除控件的只读标记。
lParam一个长整数值,它应该被设置为0(EM_SETREADONLY不使用它)。
在程序运行了此SendMessage函数之后,将返回一个长整数值,指明调用成功
(返回值非0)或是失败(返回值为0)。
样例程序
该程序显示了如何防止用户编辑一个文本框控件中的内容。
1.在Visual Basic 中开始一个新的工程,采用缺省的方法建立Form1。
2.将如下的常量和声明语句添加到Form1的通用声明部分中(注意该声明语句
需要书写在一行内):
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer,
ByVal lParam As Long) As Long
Const WM_USER = &H400
Const EM_SETREADONLY = (WM_USER + 31)
3.在Form1上添加一个文本框控件,采用缺省的方法建立Text1。将其MultiLine
属性设置为True,并且将它的ScrollBars属性设置为3-Both。
4.在Form1上添加一个命令按钮控件,采用缺省的方法建立Command1。
5.将如下的代码添加到Command1的单击事件中:
Private Sub Command1_Click()
Dim RetVal As Long
RetVal = SendMessage(Text1.hwnd, EM_SETREADONLY, True, ByVal 0&)
End Sub
通过按下F5键来执行样例程序。在文本框控件中键入一些文本,可以使用水平和
垂直滚动条来滚动文本,还可以改变文本的内容。单击命令按钮,用户仍然可以使用
滚动条或是光标键来查看文本框控件的内容,但是不能编辑它。
巧用Visual Basic的TIMER控件
Visual Basic提供一个Timer控件,其本质上是一个具有间隔时间设置所触发的
时间程序,使我们可以将其隐藏在系统中,以某一时间间隔触发相关程序。灵活地运
用它可以取得很巧妙的效果。
下面,我们举一个例子。
我们可以在界面设计中设计出这样一种效果:一行文字在窗体中自左向右逐渐滚动,
从右边“滚”出窗体的文字,又在左边逐渐出现。如此循环下去。类似电视上的滚动信
息。这样可使你设计的软件显得很生动,极易引起用户的兴趣 。其实,使用Visual
Basic的Timer控件就可很容易地实现它。
首先,我们在窗体中设置两个Label控件Label1、Label2。这两个控件中除Left
属性外,其他属性设置成完全一样。这主要是为了实现循环滚动的效果。它们的Caption
属性设置为要滚动显示的文字。另外再调整好其字体、大小和颜色等。在Form-Load过
程中设置Label2.Left=-6240(窗体宽度),Label1.Left=0。这样可保证Label1
的一部分“滚”出窗体,则Label2的一部分就进入窗体。而形成循环滚动在窗体中设置?/FONT>Timer控件。Timer控件的Interval属性决定滚动的速度,单位是毫秒。例如,
我们设置成300,则每隔0.3秒滚动一次。然后,在Timer1-Timer()过程中加入如下
程序:
Private Sub Timer1-Timer()
Label1.Left=Label1.Left+50
Label2.Left=Label2.Left+50
If Label1.Left>=6240 Then
Label1.Left=-6240
End If
If Label2.Left>=6240 Then
Label2.Left=6240
End If
End Sub
滚动效果就形成了,感兴趣的读者可以试试看。只要灵活运用Timer控件,我们
还可以设计出更有趣的效果。如用Timer控件控制按钮控件的Visible属性,形成闪烁
按钮。用Timer控件控制显示不同的图象,形成简单的动画。
在 RichTextBox 之中, 如何将被选取的内容(包含文字及图片) 复制到剪贴簿?
如果不是写程序, 那么就是按下键盘 Ctrl+C。
当使用者按下 Ctrl+C 时, RichTextBox 会对自己送出 WM_COPY 的信息, 而接着 RichTextBox 的窗口程序收到此一信息时, 便会将被选取的内容(包含文字及图片)复制到剪贴簿&127;。
所以如果想要将 RichTextBox 中被选取的内容复制到剪贴簿, 只要对 RichTextBox 送出 WM_COPY 信息即可, 以下是程序撰写上的细节:
1. API 函数的声明式:
Const WM_PASTE = &H302
Const WM_CUT = &H300
Const WM_COPY = &H301
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
注:如果以上的声明放在「一般模块」底下, 应在 Const 之前加上 Public 保留字, 并且将 Private 保留字去掉。
2. 调用例:
SendMessage RichTextBox1.hWnd, WM_COPY, 0, ByVal 0&
在 ListBox 之中, 如何检测鼠标所在位置的选项?
我们可以利用 ListIndex 属性得知 ListBox 的选项, 但是当鼠标移到某一个选项上面(但还没有选取),如何得知此一选项呢?方法是对 ListBox 送出 LB_ITEMFROMPOINT 信息, 细节如下:
1. API 的声明:
Const LB_ITEMFROMPOINT = &H1A9
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
注:如果以上的声明放在「一般模块」底下, 应在 Const 之前加上 Public 保留字, 并且将 Private 保留字去掉。
2. 调用例:(在表单上布置一个 TextBox 及一个 ListBox, 然后利用 MouseMove 事件程序来检测鼠标所在位置的选项)
Private Sub List1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim pos As Long, idx As Long
pos = X / Screen.TwipsPerPixelX + Y / Screen.TwipsPerPixelY * 65536
idx = SendMessage(List1.hwnd, LB_ITEMFROMPOINT, 0, ByVal pos)
' idx 即等于鼠标所在位置的选项
If Idx <65536 Then Text1.Text="List1.List(idx)<Br"> End Sub
在VB6.0中使用数据窗体设计器插件
一个插件实际上是一个OLE服务器,用于扩展VB开发环境,增强VB的功能。我们可以使用插件为VB菜单增加定制项,可管理当前激活窗体及控件,并响应多种文件控制事件。VB在SAMPLES目录的ALIGN、DATAWIZ和SPY子目录下就包含了三个这样的插件应用程序。
这里我们着重讨论DATAWIZ下的数据窗体设计器插件。
1.数据窗体设计器插件的引入
通常,我们在使用VB数据控件设计数据窗体时,大量的时间都花在窗体的可视化设计过程上,如标签和数据装订控件的建立和对齐定位。我们设想要是能根据数据库结构自动生成数据窗体,那将是一件非常令人愉快的事情。随着VB4的推出,我们将会惊喜地发现,它不仅提供了实现插件的功能,而且包含了一个实用的数据窗体设计器(Data Form Designer)插件。利用该插件瞬间即可生成使用数据控件的简单数据窗体。但是由于该窗体设计器只是一个随VB发行的示例应用程序,我们必须首先载入该文件,生成VB的一个插件,再安装该插件才能使用。所以VB的数据窗体设计器可能还不广为人知,下面将它介绍给VB的使用者,希望能为设计数据窗体提供帮助。
2.载入数据窗体设计器示例文件
如果数据窗体设计器没有出现在可用插件的列表中,则必须载入它,其步骤是:
*选择File|Open Project菜单命令,打开\Vb\Samples\Datawiz\Dfd.Vbp项目文件
*选择File|Make EXE File命令创建一个可执行文件
*运行该程序,数据窗体设计器自动加入到下一步中要使用的可用插件到列表中
3.安装数据窗体设计器插件
安装数据窗体设计器插件是通过插件管理器完成的,其过程是:
*选择Add-Ins|Add-In Manager菜单命令
*选取Data Form Designer,即数据窗体设计器
*单击OK,则数据窗体设计器出现在Add-Ins菜单中
4.使用数据窗体设计器
通过几个简单的步骤就可创建一个查看并编辑库的示例应用程序:
*选择Add-Ins|Data Form Designer菜单命令,弹出一个数据窗体设计器窗口
*输入窗体名称
*选取一个数据库类型
*单击Open Database打开一个数据库
*从RecordSource列表中选取相应表
*从Available Columns中选取部分或全部字段至Included Columns中
*单击Build the Form按钮,产生所需要的数据窗体
*数据窗体建立完毕,单击Close按钮
*选择Tools|Options命令将该窗体设置为启动窗体
*运行该应用程序
5.数据窗体设计器完成的工作
数据窗体设计器为程序开发者创建的可视窗体包括以下的工作:
*在窗体上增加一个数据控件,并为其设置Connect,DatabaseName和RecordSource属性
*对于表中所选的数据库字段,增加一个有字段名的标签和相应的装订控件,装订控件的类型取决于字段的数据类型:
字段数据类型
装订控件类型
字符串、日期和数值
文本框
布尔
检查框
Memo域
多行文本框
二进制数据
OLE包容器
*增加四个命令按钮:增加、删除、刷新、更新和关闭,以执行不同的数据访问功能
为命令按钮和数据控件增加简单的程序代码和注释说明
当然,使用数据窗体设计器产生的数据访问窗体是非常简单的,但这个简单的窗体可以作为在应用程序中建立更复杂的数据访问功能的框架结构。
如何在输入光标进入TextBox时,将整个TextBox的内容变成反白?
利用 GetFocus 事件(发生于输入游标进入 TextBox时 )、 SelStart属性 (表示被选 取区的起始位置 )、及 SelLength 属性 (表示被选取区的长度 ),程序 如 下 :
Private Sub Text1_GotFocus()
Text1.SelStart = 0
Text1.SelLength = Len(Text1.Text)
End Sub
利用 EM_LINESCROLL 信息控制 TextBox 的卷动。
在含有卷动轴的 TextBox 中, 如何以程序控制 TextBox 的卷动?
传送 EM_LINESCROLL 信息给 TextBox 控制文件,方法是调用 SendMessage API 函数,细节如下:
1. API 的声明:
Const EM_LINESCROLL = &HB6
Private Declare Function SendMessageBynum Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
注:如果以上的声明放在「一般模块」底下, 应在 Const 之前加上 Public 保留字, 并且将 Declare 之前的 Private 保留字去掉。
2. 调用范例:
ret = SendMessageBynum(Text1.hwnd, EM_LINESCROLL, 0, 1 ) ' 下卷一行
ret = SendMessageBynum(Text1.hwnd, EM_LINESCROLL, 0, -1 ) ' 上卷一行
ret = SendMessageBynum(Text1.hwnd, EM_LINESCROLL, 1, 0) ' 右卷一列
ret = SendMessageBynum(Text1.hwnd, EM_LINESCROLL, -1, 0) ' 左卷一列
ret = SendMessageBynum(Text1.hwnd, EM_LINESCROLL, 1, 1 ) ' 下卷一行且右卷一列
注:以上的 Text1 为 TextBox 的名称。
利用 timeGetTime 更精准地计算时间差。
我想每 0.005 秒做某一件工作, 所以撰写了以下程序:
Dim tm1 As Single
Do
tm1 = Timer
While Timer - tm1 <0.005 ' 等于 0.005 秒
DoEvents
Wend
…做某一件工作
Loop
但实际上, 在 While 循环里面, Timer 函数几乎每次都得到相同的时间,只有大约隔了 0.05秒才会得到不同的时间, 也就是说 Timer 的准确性只有 0.05 秒, 但我希望进行的工作却是每 0.005 秒一次, 该怎么办呢?
可以改用 Windows API 的 timeGetTime 函数, 此一函数会传回 Windows 开机以来所经过的时间,时间单位是 1/1000 秒, 举例来说, 开机经过 2 分钟, 则传回值等于 2*60*1000, timeGetTime 的优点是时间可以精确到 1/1000 秒, 所以可以用来解决上述的问题,细节如下:
1. API 的声明:
Private Declare Function timeGetTime Lib "winmm.dll" Alias "timeGetTime" () As Long
注:如果以上的声明放在「一般模块」底下, 应将 Declare 之前的 Private 保留字去掉。
2. 程序范例:
Dim tm1 As Long
Do
tm1 = timeGetTime
While timeGetTime - tm1 <5 ' 等于 5/1000="0.005" 秒
DoEvents
Wend
…做某一件工作
Loop
快速读取 TextBox 第 N 行的资料
TextBox 是以 vbCr+vbLf 为分行符号, 如果我们要逐一读取 TextBox 每一行,无非是寻找 vbCr+vbLf 的所在位置, 然后取出每一行的字串, 不过这个方法真的不快,而且如果我们要读取第 N 行资料, 还是要从第 1、2、┅N-1 行逐一读起, 实在麻烦。
还好 Windows API 提供有读取 TextBox 第 N 行的功能, 细节如下:
1. API 的声明:
Const EM_GETLINE = &HC4
Const EM_LINELENGTH = &HC1
Const EM_LINEINDEX = &HBB
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Sub RtlMoveMemory Lib "KERNEL32" (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
注:如果以上的声明放在「一般模块」底下, 应在 Const 之前加上 Public 保留字, 并且将 Private 保留字去掉。
2. 程序范例:
Sub TB_GetLine(ByVal hWnd As Long, ByVal whichLine As Long, Line As String)
Dim length As Long, bArr() As Byte, bArr2() As Byte, lc As Long
lc = SendMessage(hWnd, EM_LINEINDEX, whichLine, ByVal 0&)
length = SendMessage(hWnd, EM_LINELENGTH, lc, ByVal 0&)
If length > 0 Then
ReDim bArr(length + 1) As Byte, bArr2(length - 1) As Byte
Call RtlMoveMemory(bArr(0), length, 2)
Call SendMessage(hWnd, EM_GETLINE, whichLine, bArr(0))
Call RtlMoveMemory(bArr2(0), bArr(0), length)
Line = StrConv(bArr2, vbUnicode)
Else
Line = ""
End If
End Sub
' 假设要读取 Text1 第 5 行的资料
Dim S As String
Call TB_GetLine( Text1.hWnd, 5, S )
' 传回值 S 即等于到 5 行的资料
注:TextBox 的行次是从 0 起算。
在VB中用定时控件实现长定时操作
Timer控件可用来在一定时间间隔执行操作,然而,一个Timer控件的时间间隔取值最大为64.767毫秒,这意味着即使最长的时间间隔也不比一分钟长多少(大约64.8秒),也就是说一个Timer控件只能响应大约一分钟之内的事件。如果要响应长时间的事件,例如,要开发一个学习系统的自我测试或考试过程,需要限制一个考试时间,一般都在10~150分钟,开始自动计时,时间到报警考试结束。则需多个Timer控件配合使用,这样做显得既繁琐又不实用。其实,可以只用一个Timer控件,在其Timer过程中使用一个计数器,从而响应任意长时间间隔的事件。
下面是一个定时实例的部分代码:
控 件
属 性
设置的值
Label1
Caption
″请输入限定时间(分钟):″
Text1
Text
″"
Command1
Caption
″确认″
Timer1
Interval
60000
Enabled
False
在窗体通用模块General里声明N、T两个变量,N作为计数器,T用来存放限定时间。
DIM N AS Integer
DIM T AS String
Command1- Click ( )
T=Text1.Text
Timer1.Enabled=True……
End Sub
Timer1- Timer( )
N=N+1
if n=val(T) Then
Beep
Timer1.Enabled=False
End if
End Sub
将定时器的Interval属性值设为60000,使得计数器每分钟加1,当然也可以设置为其他的值,如1000,这样就使得计数器每秒钟加1,但这样要浪费较多的系统时间。
处理多个具有相同要求的控件
我们往往有时需要处理多个具有相同特性的控件,如:把 100 个 Text 及 Label 的内容加起来。这时,我们可以使用下面的技巧:
1.如果是同一种类型的控件,我们可以使用控件组达到目标。
2.如果不是同一类型控件,控件组就无法使用,这时,我们还可以利用控件的 Tag 性,我们可以把每个控件设置一个 Tag 标志。在程序中,我们可以用下面代码来察看是否是我们需要的控件:
For I=0 To Controls.Count-1
If Controls(I).Tag = "MyTag" Then ……
Next I
输入限制确认
在某些应用程序中,我们需要限制在文本框或其它一些控件中只能输入数字或一些特定的字符,现在我们可以通过下面的一个函数来实现此功能:
Function ValiText(KeyIn As Integer, ValidateString As String, Editable As Boolean) As Integer
Dim ValidateList As String
Dim KeyOut As Integer
If Editable = True Then
ValidateList = Ucase(ValidateString) & Chr(8)
Else
ValidateList = Ucase(ValidateString)
End If
If InStr(1, ValidateList, Ucase(Chr(KeyIn)), 1) > 0 Then
KeyOut = KeyIn
Else
KeyOut = 0
Beep
End If
ValiText = KeyOut
End Function
在工程中加入此函数后,你就可以使用它了。
方法:在需要限制输入的控件的 KeyPress 加入以下代码:
KeyAscii=ValiText(Keyascii, "0123456789/-",True)
现在你就可以过虑掉你不希望的字符了。在此例中,我们只接受第二个参数提供的字符,即:"0123456789/-"
而此函数的第三个参数就决定了能否使用 [Backspace] 键。最后值得一提的是此函数对大小写是不敏感的。
浅谈VB6.0中的实用技巧2
Shift、Ctrl、Alt等键就不能产生Ascii码,所以就不会引发KeyPress事件,而数字、大小写字母等可打印的键盘字符、Enter、BackSpace、Esc和Tab等都可以。
【实例3.6】 编写程序,实现对于用户在文本框中输入的字母,不管大小写,始终以大写显示在文本框中。
打开代码编辑窗口,在其中输入如下代码:
Private Sub Text1_KeyPress(KeyAscii As Integer)
If KeyAscii >= 97 And KeyAscii <= 122 Then
KeyAscii = KeyAscii – 32
End If
End Sub
程序运行后,在文本框中输入大写字母或小写字母时,显示的都是大写字母,如图3-14所示。
图3-14 程序运行结果
2.鼠标事件
鼠标是目前图形界面平台下应用最广泛的输入控制设备。前面曾经介绍过应用于对象的鼠标的单击和双击事件,其实VB的对象除了能识别这两个鼠标事件外,还能识别鼠标的MouseDown、MouseMove和MouseUp事件。鼠标事件适用于窗体、文本框、命令按钮、选项按钮、复选框、列表框、图片框、标签和框架等对象。
(1)MouseDown和MouseUp事件
格式:
Private Sub对象名_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Private Sub对象名_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
(2)MouseMove事件
格式:
Private Sub 对象名_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
MouseDown、MouseUp与MouseMove事件中的参数都一样,这里统一进行说明:
l Shift、X、Y参数的含义同键盘事件。
l Button参数值是指此时按下或释放了哪个鼠标键,该参数是一个整数。对于MouseMove事件来说,button参数是指所有鼠标按键当前的状态。一个MouseMove事件可指示某些、全部或没有一个按钮被按下。对于MouseDown和MouseUp事件来说,button参数在每个事件精确地指示一个按键,即不能检查两个或三个键同时被按下或松开的情况,因此取值只能是下表中的前三种。参数具体取值如表3-13所示。
表3-13 Button参数取值
十进制 | 二进制 | 转换键按下情况 |
0 | 000 | 没有按下任何鼠标键 |
1 | 001 | 鼠标左键被按下 |
2 | 010 | 鼠标右键被按下 |
3 | 011 | 鼠标左、右键同时被按下 |
4 | 100 | 鼠标中间键被按下 |
5 | 101 | 鼠标中间、左键同时被按下 |
6 | 110 | 鼠标中间、右键同时被按下 |
7 | 111 | 鼠标三键同时被按下 |
l
MouseDown是三种鼠标事件中最常使用的事件。例如,在运行时可用它调整控件在窗体上的位置,也可用它实现某些图形效果。按下鼠标按钮时就可触发此事件。
l MouseMove事件伴随鼠标指针在对象间移动时连续不断地产生。除非有另一个对象捕获了鼠标,否则,当鼠标位置在对象的边界范围内时该对象就能接收MouseMove事件。
【实例3.7】 利用上述鼠标事件,在窗体上绘制图形。
要求:单击鼠标即开始绘制,并根据鼠标移动的位置进行绘制,释放鼠标则停止绘制。打开代码编辑窗口,在其中输入如下代码:
Dim draw As Boolean '设置绘制状态标志
Private Sub Form_Load()
DrawWidth = 15 '设置绘制笔刷的宽度
ForeColor = RGB(0, 0, 255) '设置绘制的颜色
End Sub
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
draw = True '表示开始下笔绘制
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If draw Then
PSet (X, Y) '根据目前鼠标移动的位置绘制点
End If
End Sub
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
draw = False '表示停笔
End Sub
程序运行后结果如图3-15所示。
图3-15 程序运行结果
3.3.2 数据的输出
1.Print方法
在VB中,可以使用Print方法实现数据输出。Print方法除了可以在窗体上输入文本字符串或表达式的值外,还可以在其他图形对象或打印机上输出信息。
格式:[对象名.]Print[表达式表]
说明:
(1)如果使用Print方法将数据输出到窗体,应该先使用Show方法,否则输入数据将不会显示出来。
(2)格式中的【对象名】可以是窗体、图片框或打印机。如果省略,则在当前窗体上直接输出。
(3)表达式表是一个或多个表示式,如果是数值表达式,则输出表达式的值;如果是字符串表达式,则按原样输出。输出数据时,数值数据前面有一个符号位,后面有一个空格,而字符串前后都没有空格。
(4)当输出多个表达式时,各表达式之间用分隔符逗号【,】或分号【;】隔开。
l 如果使用逗号分隔符,则各输出项按标准输出格式显示。
l 如果使用分号分隔符,则按紧凑格式输出。
【实例3.8】 用Print方法在窗体输出文本信息。
打开代码编辑窗口,在其中输入如下代码:
Private Sub Form_Click()
Print "3*5-2="; 3 * 5 - 2
Print "好好学习"
Print , "Visual Basic"
Print , , "编程技术"
Print "只要坚持不懈",
Print "你一定能称为VB编程高手"
End Sub
程序运行后,单击窗体的结果如图3-16所示。
图3-16 程序运行结果
2.Tab函数和Spc函数
VB还提供了两个与Print方法有关的函数:Tab和Spc。
(1)Tab函数
在Print方法中,可以使用Tab函数对输出进行定位。
格式:Tab(n);
说明:
l n为数值表达式,其值为一整数。Tab函数把显示或打印位置移到由参数n指定的列数,从此列开始输出数据。要输出的内容放在Tab函数后面,并用分号隔开。
l 当在一个Print方法中有多个Tab函数时,每个Tab函数对应因各输出项,各输出项之间用分号隔开。
(2)Spc函数
在Print方法中,还可以使用Spc函数来对输出进行定位,与Tab函数的区别是:Spc函数提供若干个空格。
格式:Spc(n);
说明:
l n为数值表达式,其值为一整数。表示在显示或打印下一个表示式之前插入的空格数。
l Spc函数与输出项之间用分号隔开。
3.4 使用对话框
为了便于和用户交互,VB提供了InputBox和MsgBox两个函数,简化界面设计。其中:
l InputBox(输入框):用来输入信息。
l MsgBox(消息框):用来显示信息。
下面分别进行讲解。
3.4.1 InputBox函数
InputBox函数用来接受通过键盘输入的数据,并返回在对话框中输入的信息。在调用InputBox函数时,屏幕上将产生一个带有提示信息的对话框,光标在输入对话框底部的输入文本框中闪烁,等待用户输入数据。按回车键或用鼠标单击【确定】或【OK】按钮,即可把输入文本框中输入的数据以字符串形式赋给变量;按Esc键或单击【取消】或【Cancel】按钮,则返回0值或空串。
格式:Var=InputBox(Prompt[,title][,defsult][,x,y][,helpfile,context])
说明:
(1)Var可以是变体变量或字符串型变量,也可以是数值型变量(若输入内容不可转换成数值型数据,将会产生运行错误)。
(2)Prompt:提示用的文字信息,字符串类型,其长度不能超过1024个字符;该参数不可缺省。在对话框内显示Prompt提示文字信息时,可以自动换行。若想按自己的要求换行,则可采用插入回车换行符,即Chr(13)+Chr(10)或vbCrLf来实现。
(3)title:对话框标题(字符型),缺省时,为空白。
(4)default:显示在用户编辑框中的缺省值(字符型),缺省时,返回空值。
(5)x,y:对话框在屏幕上显示时的位置,单位是特维,(x,y)是对话框左上角点的坐标。
(6)helpfile,context:帮助文件名及帮助主题号。有本选项时,在对话框中自动增加一个帮助按钮。
3.4.2 MsgBox函数和语句
MsgBox函数以信息框的形式用于向用户发布提示信息,并要求用户做出必要的响应。如图3-17所示。
图3-17 MsgBox对话框
MsgBox函数的格式:Var=MsgBox(Prompt[,button][,title][,helpfile,context])
说明:
(1)Prompt、title、helpfile,context参数的含义同InputBox函数。