用户控件详解.docx
- 文档编号:5400045
- 上传时间:2022-12-15
- 格式:DOCX
- 页数:20
- 大小:33.17KB
用户控件详解.docx
《用户控件详解.docx》由会员分享,可在线阅读,更多相关《用户控件详解.docx(20页珍藏版)》请在冰豆网上搜索。
用户控件详解
VB6.0用户控件的制作教程
本文摘自
如今OCX控件在编程中已占领了很重要的地位,我们可以利用OCX控件完成一些相当复杂的编程操作.同时OCX控件还有利于主程序的简单化、功能的重用、隐常程序实现细节、便于升级、传播方便等优点。
现在我们可以利用VB5.0方便的制作出自己的OCX控件供我们在编程中使用同时还可以把它送给你周围喜欢编程的朋友!
下面列出制作OCX控件的步骤:
一:
新建OCX
打开VB5.0选择新建工程在对话框中选择ActiveX控件,打开后会见一空的文档这就是OCX控件的初始界面。
想看一看空OCX控件的效果吗?
选择“添加工程”选中标准EXE,这时你就可以像调用其它控件一样在左边的工具栏里选择刚才新建的OCX控件图标放在标准的EXE文档中看一看有什么效果!
(什么也没有!
)自然因为刚才的OCX文档是空的嘛(废话太多,数个痰盂向我飞来)!
二:
创建界面
一般我们用VB创建OCX控件都是在我们的控件里添加其它的控件来组合成一个完整的控件(也可以让它只完成某种算法)比如:
你可以在上面添加一按钮、编辑框这时你再用第一部的方法看一看效果,是不是控件上多了一个按钮和一个编辑框。
三:
OCX属性
一个OCX控件有许多的属性,比如控件背景是否透明(BackStyle),控件是否可以获得焦点
(CanGetFocus)等。
这些属性都可以在控件的“属性框”中找到。
四:
添加事件
一个控件有很多事件如:
Click、MouseDown、MouseUp、MouseMove等。
要触发这些事件都需要你加入代码。
在控件的声明处加入PublicEventClick()事件名(参数)。
五:
用户属性
一个控件应有许多属性供用户设置如:
控件的背景色、控件要显示的图形等。
它们通常用PropertyGet和PropertyLet两条语句来完成。
前者表示给用户显示一个属性的值,后者表示用户设置一个属性的值。
六:
保存属性和读取属性
当属性被用户更改后需要将该属性值保存,以便控件运行时读取更改后的属性值。
它们分别用ReadProperty和WriteProperty两种方法来完成。
前者表示读取一个属性值,后者表示写入一个属性值。
好了一个简单的OCX控件制作方法大概就需要以上几步就可完成。
下面本人将编写一个简单的OCX控件供大家参考。
此控件的功能是在控件中显示一个圆,当鼠标移到控件上的时候控件上的圆便会在鼠标不离开控件的前提下跟随鼠标移动。
新建一OCX控件,将控件的BorderStyle属性改为1,再加入一SHAPE控件将其形状改为Circle(如图二(map2.gif))
添加以下代码:
PublicEventClick()'定义该控件要产生的事件
DimCircleXAsInteger,CircleYAsInteger
PrivateSubUserControl_Click()
RaiseEventClick'触发Click事件
EndSub
PrivateSubUserControl_Initialize()
CircleX=Shape1.Width/2
CircleY=Shape1.Height/2
EndSub
PrivateSubUserControl_MouseDown(ButtonAsInteger,ShiftAsInteger,X
AsSingle,YAsSingle)
Shape1.BackColor=RGB(0,0,255)
EndSub
PrivateSubUserControl_MouseMove(ButtonAsInteger,ShiftAsInteger,X
AsSingle,YAsSingle)
DimMoveXAsInteger,MoveYAsInteger
MoveX=X-Shape1.Width/2
MoveY=Y-Shape1.Height/2
If(MoveX<0)Or(MoveX+Shape1.Width>UserControl.ScaleWidth)Or_
(MoveY<0)Or(MoveY+Shape1.Height>UserControl.ScaleHeight)Then
ExitSub
Shape1.MoveMoveX,MoveY
EndSub
PrivateSubUserControl_MouseUp(ButtonAsInteger,ShiftAsInteger,XAs
Single,YAsSingle)
Shape1.BackColor=RGB(255,0,0)
EndSub
PropertyGetPosX()AsInteger'取得CircleX的值显示给用户
PosX=CircleX
EndProperty
PropertyLetPosX(ByValNew_XAsInteger)'把用户写入的值设置到OCX控件内部
If(New_X (New_X>UserControl.ScaleWidth-Shape1.Width/2)Then MsgBox("圆的X值超出界限了") Else CircleX=New_X CallUserControl_Resize EndIf EndProperty PropertyGetPosY()AsInteger PosY=CircleY EndProperty PropertyLetPosY(ByValNew_YAsInteger) If(New_Y (New_Y>UserControl.ScaleHeight-Shape1.Height/2)Then MsgBox("圆的Y值超出界限了") Else CircleY=New_Y CallUserControl_Resize EndIf EndProperty PrivateSubUserControl_ReadProperties(PropBagAsPropertyBag) CircleX=PropBag.ReadProperty("CircleX",Shape1.Width/2)'将用户设置的值读出来 CircleY=PropBag.ReadProperty("CircleY",Shape1.Height/2)'同上 CallUserControl_Resize EndSub PrivateSubUserControl_Resize() Shape1.MoveCircleX,CircleY EndSub PrivateSubUserControl_WriteProperties(PropBagAsPropertyBag) CallPropBag.WriteProperty("CircleX",CircleX,Shape1.Width/2) '将用户设置的值保存 CallPropBag.WriteProperty("CircleY",CircleY,Shape1.Height/2)'同上 EndSub 本次准备的实例共有18个,包括: 三个时钟控件,两个标签控件,一个图片特技控件,一个混合四 则运算控件,四个进度条控件,一个消息框控件,一个按纽控件,一个选项卡控件,三个菜单控件以及 一个立体字制作控件。 实例中有六个控件不是我的原创,但我都进行了重大更改(研究别人的代码也许比自己编写代码更 费时费力),所以我对它们至少应拥有30%的“股份”,呵呵。 实例中的有些控件其实是不需要制作成控件的,在窗体代码中实现这些功能也许更简单,但笔者的 目的是: 1.让初学者多做试验,尽快掌握制作用户控件的方法;2.以此说明,只要你愿意,窗体代码的 功能有很多是能够制作成用户控件的,不要把制作用户控件看成畏途,世上无难事,只要肯钻研。 本讲解要是能解决你制作用户控件时的某些困惑,请给点鲜花和掌声,要是发现了讲解中的错误, 恳请指出而不要扔砖头和臭鸡蛋,一言为定呵! 如果你从来没有制作过用户控件,请同时参阅我的旧贴《打造自己的多风格按纽--用户控件制作 详解》。 好了,开场白道过,下面要言归正传了,还是老习惯,把编写代码的程序员称为中间用户,把使用 程序的用户称为最终用户。 上篇 (附件中包括以下控件的工程文件: 时钟控件、四则运算控件、标签控件、图片特技控件、按纽控件共 计8个控件) 制作用户控件,主要就是进行以下三项代码编写工作: 1.定义控件的属性、事件和方法,其中属性是最常使用的。 2.保存和读取中间用户设置的属性值。 3.为达到你的预定目的而调用的各种技术手段。 在用户控件中定义的属性、事件、方法,其性质都必须是公用的,也就是说,只有用Public来定 义,这样你才能在主程序代码中使用这些事件和方法,以及设置或获取这些属性值,也只有公用的属性 才会在窗体页面相关控件的属性窗口显示出来。 一、属性 属性是用户控件最基本的东东,用户控件可以没有事件,可以没有方法,但不能没有属性(当然, 技术上来说是可以没有属性的,但这样的控件使中间用户无法进行任何设置,是没有什么意义的)。 那 么,如何定义用户控件的属性呢? 为用户控件添加属性有两种办法: 1.公用变量法: public变量名称as类型 这里的变量名称就是属性名称。 这样定义的属性一般不会保存属性值,所以常常用作只读属性,在 笔者的用户控件中,用于对主程序返回一个必要的值。 例如“四则运算”控件中的“ComputeAnswer” 属性: PublicComputeAnswerAsString 它返回的是计算结果,而计算结果是不需要保存在控件中的,所以把它用公用变量法定义。 再例如 消息框控件中的FeedValue属性: PublicFeedValueAsInteger'返回值 它返回最终用户选中的消息框按纽的编号,这个编号也只需要在主程序中处理,而无需保存在控件 中,所以也用公用变量法定义成只读属性。 2.property过程法: publicpropertyGet过程名称() as类型 …… endproperty publicpropertyLet过程名称(new值as类型) …… endproperty 这里的过程名称就是属性名称。 而property过程法又有两种: 一种是如上所述的标准过程法,另一种就是枚举法。 ㈠标准过程法 这是用得最多的一种属性定义方法。 在用户控件的代码页面选中“工具→添加过程”,会跳出一个 对话框,然后在单选按纽中选择“属性”,再在“名称”栏中输入属性名,点击确定,VB就会自动生成 上述的几行代码,你将“类型”改为你所需要的,再输入相关代码即可。 标准过程法中,Get过程和Let过程一般是成对出现的。 例如“闪烁标签”控件中定义闪烁时的 前景颜色FlickerForeColor属性的代码: PublicPropertyGetFlickerForeColor()AsOLE_COLOR'闪烁时的文字色 FlickerForeColor=mGlintForeColor EndProperty PublicPropertyLetFlickerForeColor(ByValnewColorAsOLE_COLOR) mGlintForeColor=newColor PropertyChanged"FlickerForeColor" EndProperty 这两段代码中的“OLE_COLOR”是颜色数据类型,实质上也是长整形的数据类型,但它会自动调出 颜色对话框。 “FlickerForeColor”是属性名称,在窗体界面相关控件的属性窗口中显示的就这个属性 名称。 而“mGlintForeColor”是中间变量,中间变量是私用的,用Dim定义即可。 在用过程法定义属 性时通常都需要中间变量。 中间变量的身份是“代表”(代表属性名),作用有两个,一是上传下达, 在Get/Let过程与ReadProperties/WriteProperties过程中充当“邮递员”;二是参与,在许多别 的过程中都要与中间变量打交道。 Get过程的作用是获取相关的属性值,并将属性名称和属性值显示在属性窗口(如果你去掉这个过 程,在属性窗口就不会出现相关的属性名称和属性值了)。 它在三种情况下被激活: ①中间用户在窗体 页面刚刚把焦点移到窗体上的控件时(例如点击该控件),在属性窗口显示出原先设置的属性值;②中 间用户在属性窗口修改了属性值,在属性窗口显示出修改后的属性值;③程序运行中用代码获取属性值 时,假设窗体代码有这么一句: RGB=Cipher.BackColor,那么也会激活该过程。 Let过程的作用是设置相关的属性值,它在两种情况下被激活: ①中间用户在属性窗口修改了控件 的属性值(执行顺序是: Get过程→Let过程→Get过程);②程序运行中用代码设置新的属性值时, 例如: Cipher.BackColor=RGB。 变量NewValue是被赋的新值(这个变量名是可以改变的),你可以 把得到的NewValue的值按自己的需求作任何用途。 要注意的是,如果这个属性是一个对象,那么就不能用Let过程而必须用Set过程了,这是因为 保存在控件内部的对象变量,保存的并不是对象的拷贝,而只是对象的引用(也就是一个内存地址)。 所以在它的Get和Set两个属性过程中,均须在等式的前面加上“Set”关键字。 来看看“四则运算” 控件中的有关代码: PublicPropertyGetFont()AsFont SetFont=Text1.Font EndProperty PublicPropertySetFont(ByValnewFontAsFont) SetText1.Font=newFont PropertyChanged"Font" EndProperty 这是设置文本框的Font属性的,而Font本身也是一个对象,所以必须使用Set了。 还有Picture属性也是如此,它也必须使用Set过程。 然而,它这个对象却有一点特殊之处: 如 果你想在程序运行当中使用LoadPicture语句动态加载图片的话,你就必须给它增加一个Let过程, 否则,你将只能在设计模式时在属性窗口加入图片。 而新增的Let过程中不需要任何代码,只要一个注 释符就行了。 以“酷时钟”控件中的Picture属性为例: PublicPropertyGetPicture()AsPicture SetPicture=UserControl.Picture EndProperty PublicPropertySetPicture(ByValNewPicAsPicture) SetUserControl.Picture=NewPic PropertyChanged"Picture" EndProperty PublicPropertyLetPicture(ByValNewPictureAsPicture) ' EndProperty ㈡枚举法 枚举是一种很常见的的方式,它提供了一个下拉列表和若干选项让用户选择。 这样既方便了用户的 操作,又不用考虑过多的兼容性和错误处理问题,简化了属性设置,而且更加安全。 要实现枚举法,首先必须建立一个枚举结构,放在声明部分,然后在结构中给出一系列的常量和对 应的字符串。 后面的常量值必须是比前面常量值大的整数。 如果没有给出常量,那么VB会自动为其赋 值,第一个字符串赋值为零,其它的值则为前面一个数加一。 例如在“特效标签”控件中,字体打印特 技的枚举结构声明: PublicEnumcTxtEffect 雕刻 '自动赋值=0 立体 '自动赋值=1 浮雕 '自动赋值=2 EndEnum 如果你要为项目赋值为从1开始,也是可以的(当然有关代码要改一下): PublicEnumcTxtEffect 雕刻=1 立体=2 浮雕=3 EndEnum 要实现枚举属性,还必须创建一个带有Let和Get属性过程的标准属性,但必须将属性的类型声 明为枚举类型。 仍以“特效标签”控件为例,你还必须有这样两个过程: PublicPropertyGetTxtEffect()AscTxtEffect TxtEffect=mTxtEffect EndProperty PublicPropertyLetTxtEffect(ByValNewValueAscTxtEffect) mTxtEffect=NewValue PropertyChanged"TxtEffect" EndProperty 注意这两个过程中的数据类型都改为了cTxtEffect。 枚举属性的读、写、保存和检索,都和标准属性是一样的。 3.保存或读取属性值 上述的Let过程中的PropertyChanged方法是用户控件特有的方法,其作用是,通知系统某个属 性发生了改变,系统根据具体情况决定是否将改变后的属性值保存到属性包(或.frm文件)中。 所谓 具体情况是指: 在设计模式(正在被中间用户使用)就保存,在运行模式(正在被最终用户使用)就不 保存。 比如你的程序代码中有这么一句: Cipher.BackColor=RGB,那么运行该程序到这一句时,就会 将Cipher控件的背景色改变为RGB所代表的颜色,但不会将这个RGB值保存到属性包中,所以,下 次你运行程序时,只要没有运行到这一句,Cipher控件的背景色依然是你设计时的颜色。 保存属性值是由WriteProperties事件过程执行的,在销毁创建的控件之前,该事件会根据Prop ertyChanged方法的提示,以及当时的运行模式,来决定是否通知PropertyBag对象把数据写入属性包 (或.frm文件)中。 保存时,所有在该事件过程中的属性值都会同时保存,而不仅仅是保存某一个提示 改变的属性值。 读取属性值是由ReadProperties事件过程执行的,在创建控件之前,该事件会通知PropertyBag 对象从属性包(或.frm文件)中把保存的所有属性值都同时读取出来,读出的数据由Get过程使用。 PropertyBag对象是具体实施保存或读取功能的,它有两个方法: WriteProperty方法用来写属性 值,ReadProperty方法用来读属性值。 特别提醒: 对于新手来说,一定要搞清楚cTxtEffect、mTxtEffect、TxtEffect和“TxtEffect” 这四个东东的意义: cTxtEffect: 是结构名。 mTxtEffect: 是代表cTxtEffect结构中某个项目值的中间变量,如果没有枚举结构,则是代表属 性值的中间变量,它是模块级的变量。 TxtEffect: 是属性名,它会出现在窗体页面的属性窗口中。 “TxtEffect”: 是保存到属性包时所用的名称,笔者为了方便,把它与属性TxtEffect取了同一 个名称,但并不是同一个概念,它只出现以下在三个方法中: PropertyChanged方法、ReadProperty方 法以及WriteProperty方法中,你完全可以另外取个名,但在这三个方法中必须是完全同名的。 你可以 这样理解: “TxtEffect”是一个文件名,而mTxtEffect则是一个变量,你要从“TxtEffect”中读出 文件内容并赋值给mcTxtEffect,或者你要将赋了值的mcTxtEffect保存到“TxtEffect”去。 还有一个需要注意的地方: 使用ReadProperty/WriteProperty方法读写数据时,被读写的变量不 能是数组。 例如,在MyMenu菜单控件中,mCaption是一维数组,但"sCaption"不可能是数组,所以你 不能这样编写代码: Fori=1TomItemSum: .WriteProperty"sCaption"(i),mCaption(i),"": Next 而只能这样: Fori=1TomItemSum: .WriteProperty"sCaption"&i,mCaption(i),"": Next 实际上就是: .WriteProperty"sCaption1",mCaption (1),"" .WriteProperty"sCaption2",mCaption (2),"" …… .WriteProperty"sCaptionN",mCaption(N),"" 'N=mItemSum 对于另一个菜单控件muchMenu控件来说,mCaption是二维数组,所以只能这样编写: Forj=1TosRep Fori=1TomItemSum(j) .WriteProperty"sCaption"&j*10&i,mCaption(j,i),"" Next Next 实际上就是: .WriteProperty"sCaption101",mCaption(1,1),"" .WriteProperty"sCaption102",mCaption(1,2),"" …… .WriteProperty"sCaption10N",mCaption(1,N),"" 'N=mItemSum(j) .WriteProperty"sCaption201",mCaption(2,1),"" .WriteProperty"sCaption202",mCaption(2,2),"" …… .WriteProperty"sCaption20N",mCaption(2,N),"" …… .WriteProperty"sCaptionM01",mCaption(M,1),"" 'M=sRep .WriteProperty"sCapti
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 用户 控件 详解
![提示](https://static.bdocx.com/images/bang_tan.gif)