学用VB控件编程(五)

软件世界

一、控件与API

VB提供的语句、函数、对象等等已经很多,但都是标准的,有时想玩些花样,通常就行不通。如列表框只有垂直滚动条,没有水平滚动条。怎么办?我们可以通过Windows API函数来实现。一句话,当VB没提供这样的功能,我们就可以调用API函数。
API是一个特大型函数集合,各个函数共同执行着Windows操作系统任务。例如,VB无论画图、保存文件还是分配内存给新的应用程序,都要访问API。VB的程序设计是以对象为核心,构成对象的三要素是属性、方法和事件,所以我一直强调控件编程必须掌握其属性、方法和事件,而对Windows 的程序设计,却是以消息为核心。VB控件对这些消息进行了封装,使之成为属性方法和事件。
通过下表列表框(ListBox)的消息我们可以与ListBox控件对比:
(图1)

图1
图1

几个ListBox没有对应的消息,
LB_SELECTSTRING 选取开头含有某字符串的选项
LB_FINDSTRING 搜寻开始含有某字符串的选项
LB_FINDSTRINGEXACT 搜寻完全相符的选项
LB_SETHORIZONTALEXTENT 设置水平滚动条
LB_ITEMFROMPOINT 检测鼠标所在位置的选项
我们可以通过使用这些消息来强化ListBox,实现一些特殊效果。
使用API函数首先要声明
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 LB_SETHORIZONTALEXTENT = &H194
将下代码放在程序中即可实现水平滚动条,运行图如((图2))。
图2
图2

SendMessage List1.hwnd, LB_SETHORIZONTALEXTENT, 300, ByVal 0&
举这个例子 ,不是叫我们以后都不用控件,而是在用VB控件编程时,这是应该了解的知识,也算是一种技巧吧。用VB编程,使用控件是最好的选择,当有些功能控件不能实现时,才使用API,把API作为编程的补充,这样,我们的程序功能才多样。

二、编写ActiveX控件

如果说VB有一个特性吸引了所有的开发人员,那就是人们第一次可以用一种简单、易学、好用的语言来建立ActiveX控件。在前面几篇所提到的控件,都是Windows或第三方厂商提供的,当我们遇到一个非常实用的程序,为了让它在多个应用程序中使用,我们就可以把它包装成ActiveX控件。一个优秀的VB程序员,不仅要熟练运用控件编程,而且还应根据实际要求,熟练地编写出能提高编程效率的ActiveX控件。
前面说过,利用ActiveX控件编程,必须要掌握该控件的属性、方法和事件,因此,我们在定制控件时,必须要设计好控件的这三个要素。VB中提供两种常用的方法建立定制控件。1.利用“ActiveX控件界面向导”。2.手工定制。考虑到篇幅的问题且利用向导简单易用,所以下面就介绍利用向导来建立ActiveX控件。
利用VB开发ActiveX控件与开发其他应用程序差不多,Microsoft很好地隐藏了ActiveX控件开发的大部分细节,ActiveX控件接口向导能负责常规代码的生成,产生一个工作框架,我们只要加进实现独特功能的代码即可。
下面就介绍一个简单的定时控件的编写过程。
在建立新的控件之前,要完成以下步骤:
1.运行VB6,选择ActiveX控件图标,把引入UserControl对象。VB会自动生成ActiveX控件工程,包含有一个自定义控件UserControl1,在属性窗中把它改为mytime。UserControl对象其实是一个窗体,在上面可以设计定制控件外观等,还可以把其他控件加入窗体中。
2.在菜单栏外接程序管理器中加载控件接口向导。
3.在窗体中放入一个Label(Tabel1)和一个Timer(Timer1)控件。Timer1初始属性Enabled=false ,Interval=1000,设计成如((图3))所示。

图3
图3

下面就可以利用向导建立控件了。

说明

打开向导程序,第一个窗体就是说明,将来可以通过“以后跳过本屏幕”复选框来跳过本说明((图4))。

图4
图4

选定接口成员

向导程序的下一个窗口提示选择控件的标准元素((图5))。左侧窗口可以放入自定义控件的一系列标准属性、方法和事件清单,右侧是一系列已选定的常用用户接口元素,是VB中建议用户应支持这些元素。可以用中间的按钮来增删接口元素。定时控件保留如(图4)的四个属性。

图5
图5

创建自定义接口成员

在该窗口中我们可以创建控件所特有的属性、方法和事件,即通过点击“新建”、“编辑”后出现添加自定义成员窗口来增加或编辑,如(图6)。定时控件创建了如图4的四个元素。

图6
图6

设置映射((图7))
图7
图7

这个窗口是用于将自定义控件的某些属性映射到所谓固有控件(如本例的Label1)的属性,如将自定义控件的ForeColor属性映射到Label1的ForeColor属性。当用户对自定义控件的ForeColor属性进行操作时,实际上是对Label1的ForeColor属性进行操作。

设置属性((图8))
图8
图8

可以设置新元素的属性,如运行时或设计时是只读还是可读写等等。向导程序将所有新属性都声明为变体Variant。

完成((图9))
图9
图9

这样就生成了一个简单的定时控件,该控件具有属性:BackColor,BackStyle,BorderStyle,ForeColor,方法:startTimer,stopTimer,事件:timeout,并且自动生成了若干代码。我们在代码窗中分析控件代码,可以发现,属性可以用公用的Property Let 和Get过程来加入,方法就是公用过程(函数或子程序),事件通过Event来声明。
也许我们会问,控件的事件是怎么触发的呢,在编程中我们是可以在需要的地方通过RaiseEvent来触发相应的事件的。
我们补充一些功能代码到其中。
‘开始定时
Public Function startTimer() As Boolean
Timer1.Enabled = True
End Function
‘AlarmTime属性必须要日期类型,所以在Let过程中要做判断。
Public Property Let alarmTime(ByVal New_alarmTime As Date)
If IsDate(New_alarmTime) Then
m_alarmTime = New_alarmTime
PropertyChanged "alarmTime"
End If
End Property
Public Property Get alarmTime() As Date
alarmTime = m_alarmTime
End Property
Public Property Get BackStyle() As integer
BackStyle = Label1.BackStyle
End Property
Public Property Let BackStyle(ByVal New_BackStyle As integer)
Label1.BackStyle() = New_BackStyle
PropertyChanged "BackStyle"
End Property
‘停止定时
Public Function stopTimer() As Boolean
Timer1.Enabled = False
End Function
‘通过Timer来显示时间,并把当前时间与定时时间相比,如果相等,则产生timeout事件
Private Sub Timer1_Timer()
Label1.Caption = Format(Now,"hh:mm:ss")
If Time = alarmTime Then
RaiseEvent timeout
End If
End Sub
自定义控件设计完成,必须进行测试,要在测试过程当中不断改进。
要测试新的ActiveX控件,一般通过生成一个OCX文件,然后开始一个新项目,把自定义控件放在窗体上进行测试。VB也允许将新项目加在现在的项目上,这样,用户就可以测试或修改控件,而不必每次都要设计新项目。我常用后者,下面是我常用的几个步骤。
1.在控件工程中,文件→添加工程→标准EXE。
2.关闭自定义控件设计窗口和代码窗口。
3.把自定义控件引入新添加的工程。
4.设计界面,添加代码,测试。
5.返回自定义控件设计窗口和代码窗口并进行修改。
6.反复测试,直至成1功。
7.设置属性页
测试时注意必须关闭自定义控件的设计和代码窗口,否则,该控件不能引入测试工程窗口的。按(图10)设计窗体。Label1主要用来显示当前时间。

图10
图10

代码如下:
Private Sub Command1_Click()
If IsDate(Text1.Text) Then mytime1.alarmTime = Text1.Text
mytime1.startTimer
End Sub
Private Sub Command2_Click()
mytime1.stopTimer
End Sub
Private Sub mytime1_timeout()
MsgBox "时间到"
End Sub
当时间走到定时的时间时,产生timeout事件,该事件只是弹出一个 “时间到” 对话框((图11)0)。
图11
图11

属性页

最后,还应该要设计属性页,很多控件都有自己的属性页。与属性窗口相比,属性页更加美观,易于操作。通过属性页向导,我们可以很方便设计属性页。

枚举属性

在运行控件编程时,我们会发现有很多控件的某个属性可以下拉选择,而我们使用控件向导时无法实现这样的选择。此时,我们需要一些修改一下程序,使用枚举类型。
在控件代码中增加:
Enum bstyle
border
norborder
transparent
End Enum
把BackStyle属性的Let和Get过程改为:
Public Property Get BackStyle() As bstyle
BackStyle = Label1.BackStyle
End Property
Public Property Let BackStyle(ByVal New_BackStyle As bstyle)
Label1.BackStyle() = New_BackStyle
PropertyChanged "BackStyle"
End Property
这样BackStyle属性有了三种选择0-border,1- norborder,2-transparent。
编后:经过了几周的学习,大家对控件编程也有了更深的了解,但是要想成为高手,还必须多多实践。罗马不是一天建成的,编程是个日积月累的过程。相信大家通过不断的努力,定会成为程序设计高手。我们也会在今后不定期给大家提供一些好的控件资源。