VB6.0 ActiveX 控件开发详解 [第三章:属性的设计,属性映射,属性的初始化,属性的保存]

7 篇文章 4 订阅
4 篇文章 0 订阅

 这里是《VB6.0 ActiveX 控件开发详解》的第三章,介绍如何布局用户控件设计器的界面,和如何初始化控件。如果你没有看过第一章,建议你先去看看:VB6.0 ActiveX 控件开发详解 [第二章:布局界面与初始化] 

第三章:属性的设计,属性映射,属性的初始化,属性的保存

第一节:属性的设计

       废话不多说,前文再续,书接上一回。上回说到,如何对界面进行布置和写动态修改控件大小的代码;这一回,我来介绍一下如何设计属性,这是难点。

       启动我们上次做好的工程,我们需要想想,我们这个控件需要些什么属性?既然是图片框架控件,那么我们就需要一个Picture属性,同时,在以前的代码里,没有调整图片框控件大小的代码,不知道你是否有留意。所以,我们就需要2个自定义的属性,来调整图片框的大小,暂且定为PicHeight属性和PicWidth属性。

       首先,打开用户控件设计器的代码窗口,选择【工具】菜单下的【添加过程】菜单项,在【名称】文本框里输入“PicHeight”,在【类型】那里选择“属性”,然后单击确定,就会出现如下属性过程:

在默认的情况下,每一个属性都是变体类型的,然而,有很多时候,我们的属性不拘泥于变体类型,而是可以是其他类型。在VB6.0的度量单位中,对象的长(Width)和宽(或说高,Height)使用单精度类型(Single)衡量的,于是我们对上述的过程作出更改,将原来的变体改成单精度类型。修改好后如下图所示:

        因为不能在Let过程里对属性进行赋值,所以我们需要先建立一个变量来保存取得得值。(如果到这里不能理解的,就证明你不了解属性过程的运作机制。本文另附一片专门介绍属性过程的文章,请先去看VB6.0属性过程详解(Property过程)》,看完第一章就可以回来了。)

        所以,我们在上面的属性过程中添加如下代码:

VB代码开始:

Dim gPicHeight As Single

Public Property Get PicHeight() As Single
PicHeight = gPicHeight
End Property

Public Property Let PicHeight(ByVal vNewValue As Single)
gPicHeight = vNewValue
End Property

VB代码结束

一般,我们以g加属性名称来命名这个变量,而且必须将这个变量声明成与属性相同的类型。

       在上面,我们先将由Let过程取回的新属性值保存到gPicHeight变量中,等到需要取得属性值时,才在Get过程当中由变量将值赋给属性。

       到这里,一个属性的基本运作代码已经完成,尽管这个属性没有任何的功能,但他已经具备了一个属性的所有特征,例如:写入检测(Let过程),取回新属性值(Let过程的vNewValue参数),读取属性值(Get过程)。这是设计一个属性必须要的步骤,无论设置什么属性(除了只读和只写的属性,这两种我会在以后说到),统统复制这种格式一定不会错,所以,尽管设计一个控件所编写的代码有50%甚至更多的代码是在属性过程这里,但是属性过程的代码却有80%甚至更多是大同小异的,所以,复制粘贴是很好的方法。大笑

第二节:属性的映射

       这一节,主要说一下怎么给属性设计一些功能,上面的属性是用来修改图片框的高度的,我们先来回忆一下,图片框如果要改变它的高度,应该用它的什么属性?这个不用我说,可是,我们又应该在那里添加代码以修改图片框的高度呢,因为有两个属性过程~~。那么,我就得先问你,你是想更改立即生效呢,还是等到下一次这个属性被读取时才生效?说到这里,我想认真看过我那篇附属文章的人已经明白了一半了。

      如果要立即生效,就应该加在Let过程里,而要等到下一次属性被读取时才生效,那么就应该加到Get过程里。于是,我们在上述的代码中再加入一句代码,因为我们向我们对图片框的大小的修改能立即显示出来,让我们能立即确定现在的数值是我们需要的,所以,我们在Let过程里添加代码,添加的代码如下:

VB代码开始:

Picture1.Height = vNewValue '调整图片框的高度(vNewValue是新的属性值)
VB代码结束

      这样,我们就能在修改属性的瞬间同时修改图片框的高度。然而,这种修改,你知道,客户看得到,但是作为控件的容器却不知道,有不少时候容器自身的属性需要根据你的变化而变化,这时候,我们就需要一种机制来通知容器。其实,这并不麻烦,因为Visual  Basic 6.0提供了一个名为PropertyChanged的方法,使到容器可以知道是哪个属性作出了更改,并因而调整自己。所以,我们在Let过程(必须是Let过程,因为无论你的属性修改是否立即生效,属性的值都已经更改)当中加入如下代码:

VB代码开始:

PropertyChanged "PicHeight"

VB代码结束

PropertyChanged方法的语法是

object.PropertyChanged PropertyName

其中object是可以省略的(尽管MSDN没说),而PropertyName是属性名称,字符串。

       通知容器某属性值已变更后,容器就可以用对象的新属性值同步自身的属性窗口。如果不通知容器某个属性值已经变更,容器就不知道某个对象的实例是否需要保存(通过产生 WriteProperties 事件)。一般,我们将PropertyChanged方法的调用发到Let过程的最后。

第三节:属性的初始化

       很多属性都需要初始化,别提到初始化就以为是很专业的事,其实,说属性的初始化很简单,就是为属性赋一个初值。

       在一个控件一次的生命周期中,Initialize事件首先发生,用最先发生,紧接着是ReadProperties事件;如果该控件是首次被创建,在执行了Initialize事件后还会执行InitProperties事件,而这个事件正是给我们用来做初始化的。

       我们需要在控件创建的时候给属性PicHeight赋一个值,否则在控件创建好后,PicHeight属性的值依然为空(为空相当于为0),那么,很自然,图片框的高度就变成了0。因此,我们需要在InitProperties事件中加入代码。以PicHeight属性为例,加入的代码如下:

VB代码开始:

PicHeight = 375

VB代码结束

这时候的属性可以看成是一个变量,直接给它赋值就可以了,因为在这个赋值语句执行后,接着的就是这个属性的Let过程被执行,这样我们就达到了为图片框的高度的设定一个初值的目的。

第四节:属性的保存

        其实,属性是很容易丢失的。因为,在一个控件的一生中,它被无数次的创建,加载,初始化,使用,卸载,接着重复,就在我们将Visual Basic由设计模式进入运行模式时,我们的控件就已经经历了上述的过程。别以为我们在设计模式时将控件拖入窗口,它就一直在那呆着,其实,在我们按下运行按钮的一瞬间,在窗口上的控件已经执行了Terminate事件并完成卸载,然后在执行Initialize事件被重新加载,就在这一个动作的背后,如果不将属性保存下来,就会让我么在设计模式下设置好的属性值统统丢失。

       我们需要使用WriteProperties和ReadProperties事件来保存和读取属性值。在执行Terminate事件之前,还有一个事件被执行,那就是WriteProperties事件,这个事件提供了一个对象,PropBag对象(PropertyBag类的实例)来为我们将属性保存下来。在WriteProperties和ReadProperties事件中都有PropBag对象,但是在不同的是建立我们用这个对象的不同方法来实现不同的功能。

       PropBag对象的WriteProperty方法用作保存属性值,应用于WriteProperties事件事件中。PropBag对象的ReadProperty方法用作读取属性值,应用于ReadProperties事件事件中。他们的语法是:

object.ReadProperty(DataName[,DefaultValue])

object.WriteProperty(DataName,Value[,DefaultValue])

这里的Object不能省略,它必须是一个PropBag对象;DataName是属性的名称,字符串类型(String,就是有双引号);DefaultValue是默认值,如果属性写入/读出的值是空的,就会用这个值写入/读出,这个参数可省略;Value是属性值一般是属性名称(不带双引号)。同样,以PicHeight属性为例:

VB代码开始:
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
PropBag.WriteProperty "PicHeight", PicHeight, 375

' "PicHeight"是DataName(属性名称),PicHeight是Value(属性值),请务必区分,一个有双引号,一个没有

' 375是DefaultValue(默认值)。WriteProperty 是一个方法,它没有返回值
End Sub

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
PicHeight = PropBag.ReadProperty("PicHeight", 375)
' 同样的,只是这一次不是写入,而是读出(对属性进行赋值)

' 而ReadProperty是一个函数,它有返回值,而返回值就是它的参数中描述的那个属性,这里是PicHeight 属性的值

End Sub

VB代码结束

然而,需要注意的是,只读与只写的属性都不需要使用这个,因为这些属性大多是每一次都会变化的(如hwnd属性,hdc属性),还有一些就是随用户而定的,只需写入,而不需要读出的属性。

第五节:设置默认属性

      在VB中,我们可以很简单地为一个控件设置一个默认的属性,不需要编写任何的代码,只需做一下设置即可。设置也很简单。将鼠标移动到某个属性的属性过程内,选择【工具】菜单的【过程属性】菜单项,你就会再出现的对话框上部见到当前属性的名称:

这里当前的属性就是PicHeight。单击【高级】按钮。在过程标识符里面选择“(缺省)”,如下图所示:

       这样我们就将PicHeight属性设定成我们PicFrame控件的默认属性。

第六节:添加属性描述

       然而,像PicHeight这样自定义的属性,客户并不知道其作用,我们就必须告诉用户,因此,我们需要一些描述来解释这个属性的用途。我们在属性窗口和对象浏览器里面都能看到大多数的属性的描述,这些描述不是系统生成的,而是要我们自己输入的。在上面的对话框里,有一个标为【描述】的文本框,在哪里,我们可以输入属性的描述。

       输入如下文字:“这个属性能够设置图片框架控件(PicFrame)里的图片框的高度。”后,单击“应用”,再单击“确认”,我们就能在属性窗口和对象浏览器里看到这个描述:

属性窗口下方关于PicHeight属性的描述

        在对象浏览器中,选择UPicFrame库,这是我们控件工程的名字。在PicFrame类中(这个类就是用户控件设计器,每一个控件除了有其自身的图形界面,控件本身的代码构成了一个与控件名称一样的类),我们就能够找到PicHeight属性,然后在下面看到“UPicFrame.PicFrame 的缺省成员”和关于这个属性的描述。

第七节:设置不在属性窗口里显示的属性

       在一般情况下,属性都可以在属性窗口显示,但是,如果某个属性只是在运行模式下才有效(例如hwnd属性,只读,在运行时有效,它返回对象的句柄),那么他就不需要在属性窗口里出现了,我们同样可以在上面的【过程属性】对话框中进行设置。在对话框中部,有一复选框,写着“在属性浏览器中不显示”,选上它,就能让当先属性不在属性窗口中显示了。

第八节:设置Picture属性,Font属性(重点,难点啊)

       这个问题嘛,我就不多说了。既然是重点难点,当然是要去找专业点的啦,又是去看我那篇附属文章的时候了:VB6.0属性过程详解(Property过程)[第二章:属性Set过程的应用(设计如字体属性的具有弹出式对话框的属性)]

第九节:枚举属性,在普通框架和图片框架之间切换

        我们都知道ButtonBox有个Style属性,能够让这个客户选择是否可以显示图片,或是两样都有。同样,我们也可以设计一个,但是我们必须考虑一下,这个属性有三种情况:显示着图片(默认情况);不显示图片,显示文字(跟普通框架一样);两样都有,既有图片,又有文字。也就是只有这三种情况,但是如果用户输入了出这三种情况之外的值呢(假设我们以0,1,2三个数字代表上面的三种情况,而用户却输入了3)?于是我们就需要一种方式来限制用户的输入,这就是枚举属性。铺垫就说完了,还是劳烦转跳一下,去看看对应的附属文章吧:《VB6.0属性过程详解(Property过程)[第三章:枚举属性和OLE_COLOR类型(设计限定输入的属性,如DragMode属性)]

 

到这里,属性方面的内容就基本结束了,的确的重点难点啊。期待下一章,《VB6.0 ActiveX 控件开发详解 [第四章:事件的设计与引发]》

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值