主题:[转帖]标准控制的使用技巧(1998-1999收集整理)
凡尘
[专家分:9680] 发布于 2006-02-27 14:25:00
改变 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 Long
Private 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)
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
VB的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 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$可以供应用程序调用,其中包含驱动器名、目录和文件名。
回复列表 (共7个回复)
沙发
凡尘 [专家分:9680] 发布于 2006-02-27 11:47:00
VB网格中输入数据
山东 周庆斌
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
Visual Basic 中文本框处理技巧集萃
刘强
在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的联机帮助文件,这里就不一一赘述了。
防止文本控件中的部分滚动
谭 翁
Windows API的SendMessage函数可以用来向VisualBasic控件中发送消息,例如向文本框控件上发送消息。本文介绍如何利用该函数防止文本框控件中的部分文本滚动,即该控件中不能滚动的部分不能被用户看见。
板凳
凡尘 [专家分:9680] 发布于 2006-02-27 11:47:00
发送消息到文本框控件
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键来执行样例程序。在文本框控件中键入一些文本,可以使用水平和垂直滚动条来滚动文本,还可以改变文本的内容。单击命令按钮,用户仍然可以使用滚动条或是光标键来查看文本框控件的内容,但是不能编辑它。
3 楼
凡尘 [专家分:9680] 发布于 2006-02-27 11:48:00
巧用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控件控制显示不同的图象,形成简单的动画。
如何使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等。
在VB中使用数据窗体设计器插件
长沙 李德章
凡使用过VB4以上版本的用户都会发现,与VB3相比,它提供了一个称之为插件的新特征,一个插件实际上是一个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属性
●对于表中所选的数据库字段,增加一个有字段名的标签和相应的装订控件,装订控件的类型取决于字段的数据类型:
4 楼
凡尘 [专家分:9680] 发布于 2006-02-27 11:49:00
字段数据类型
装订控件类型
字符串、日期和数值
文本框
布尔
检查框
Memo域
多行文本框
二进制数据
OLE包容器
●增加四个命令按钮:增加、删除、刷新、更新和关闭,以执行不同的数据访问功能
为命令按钮和数据控件增加简单的程序代码和注释说明
当然,使用数据窗体设计器产生的数据访问窗体是非常简单的,但这个简单的窗体可以作为在应用程序中建立更复杂的数据访问功能的框架结构。
在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] 键。最后值得一提的是此函数对大小写是不敏感的。
5 楼
凡尘 [专家分:9680] 发布于 2006-02-27 11:49:00
如何让TextBox的输入具备overwrite(覆盖)的功能?
我 们 在 TextBox 中 所 输 入 的 字 符 , 一 律 会 被 TextBox 是 视 为在 光 标 处 插 入 (insert)新 的 字 符 , 如 果 想 以 输 入 的 字 符 overwrite(盖掉 ) 输 入 光 标 所 在 位 置 的 字 符 , 可 以 在 TextBox 的 KeyPress 物件 程 序 中 撰 写 以 下 程 序 :
Private Sub Text1_KeyPress(KeyAscii As Integer)
If KeyAscii <> vbKeyBack And KeyAscii <> vbKeyReturn Then
Text1.SelLength = 1
' 将 Text1 输入光标位置的字符变成「被选取的字符」
Text1.SelText = Chr(KeyAscii)
' 「被选取的字符」取代成为「输入的字符」
KeyAscii = 0
' 将此一字符吞掉,不再传给 TextBox
End If
End Sub
如 何 计 算 TextBox 之 中 的 行 数 ?
多 行 的 TextBox 是 以 vbCr+vbLf 两 个 字 符 来 断 行 的 , 因 此 检查 这 两 个 字 符 的 出 现 次 数 就 可 以 知 道 TextBox 的 行 数 , 但如 果 TextBox 之 中 的 资 料 很 多 , 检 查 行 数 的 执 行 效 能 就 低了 一 点 。
为 了 提 升 执 行 效 能 , 可 直 接 调 用 Windows API, 首 先 在 Form 的 (一 般 ) 声 明 以 下 的 常 数 及 API:
Const EM_GETLINECOUNT = &HBA
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
而 调 用 的 方 法 如 下 :
ret = SendMessageBynum(Text1.hwnd, EM_GETLINECOUNT, 0, 0&)
则 传 回 值 ret 即 等 于 TextBox 的 行 数 。
如何在输入光标进入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 的名称。
6 楼
凡尘 [专家分:9680] 发布于 2006-02-27 11:49:00
利用 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 起算。
在 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)
End Sub
7 楼
凡尘 [专家分:9680] 发布于 2006-02-27 11:50:00
在 RichTextBox 之中, 如何将被选取的内容(包含文字及图片) 复制到剪贴簿?
如果不是写程序, 那么就是按下键盘 Ctrl+C。
当使用者按下 Ctrl+C 时, RichTextBox 会对自己送出 WM_COPY 的信息, 而接着 RichTextBox 的窗口程序收到此一信息时, 便会将被选取的内容(包含文字及图片)复制到剪贴簿。
所以如果想要将 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&
我来回复