在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属性 ●对于表中所选的数据库字段,增加一个有字段名的标签和相应的装订控件,装订控件的类型取决于字段的数据类型:
|
|
字段数据类型 |
|
装订控件类型 |
|
|
|
字符串、日期和数值 |
|
文本框 |
|
|
|
布尔 |
|
检查框 |
|
|
|
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] 键。最后值得一提的是此函数对大小写是不敏感的。
|
| 如何让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
|
|
在含有卷动轴的 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 秒, 所以可以用来解决上述的问题,细节如下: |