visual basic类模块做控件.docx
《visual basic类模块做控件.docx》由会员分享,可在线阅读,更多相关《visual basic类模块做控件.docx(13页珍藏版)》请在冰豆网上搜索。
visualbasic类模块做控件
我们可以利用VB6里的类模块实现对控件的特殊控制和事件响应。
本文介绍使用类模块把普通的Label控件变成窗体动态分割条。
图1带分隔条的窗体
初识类模块
类模块其实是一个对象的定义,封装了一些属性和方法,使用前需要生成一个实例:
’生成类模块clsTest的一个实例test
DimtestasnewclsTest
然后可以使用类模块的方法:
test.DoSomthing()’调用test的方法DoSomthing()
一个简单的例子
做一个鼠标移上去后自动获得焦点并将内容选中的“聪明”编辑框。
1、新建一工程,在[工程]菜单中,选择[添加类模块],添加一个类模块,更改其名称为clsTest。
2、进入类模块编辑界面(如图2)。
图2编辑类模块
在左边的下拉框中选择“通用”,键入以下代码:
’定义一个带事件的文本框变量
DimWithEventsMyTextAsTextBox
’保存文本框是否获得焦点的布尔变量
DimbSettedAsBoolean
’自己定义的类模块的方法,传入参数是文本框。
PublicSubBindText(tAsTextBox)
’将文本框变量设置为传入的文本框,即是对传入文本框的引用
SetMyText=t
EndSub
3、在左边的下拉框中选择“Class”,在右边下拉框中选择Initialize,这是类模块的初始化事件,可以在这里写自己的初始化代码。
VB会自动为我们添加一个事件子程序。
我们要做的就是在其中添上自己的代码。
其实这一步略过也没什么影响,不过对变量进行初始化是一个好习惯。
PrivateSubClass_Initialize()
’将文本框变量初始化Nothing
SetMyText=Nothing
bSetted=False
EndSub
4、在左边的下拉框中选择“MyText”,注意到了吗,它就是我们在第2步定义的带事件的文本框变量。
VB把它加进来了,再到右边下拉框中点击下拉按钮,呵呵,看到什么了?
原来是我们熟悉的TextBox的所有事件!
只不过这里的MyText文本框并不实际存在,只是一个代
号,等着你给它指定一个实际的文本框呢。
添加事件响应代码,这就不用我说了吧。
PrivateSubMyText_GotFocus()
bSetted=True
EndSub
PrivateSubMyText_LostFocus()
bSetted=False
EndSub
’鼠标在控件上移动时,如果还没设置焦点,将它设为焦点,
’并将内容选中
PrivateSubMyText_MouseMove(ButtonAsInteger,ShiftAsInteger,XAsSingle,YAsSingle)If(NotbSetted)Then
MyText.SetFocus
MyText.SelStart=0
MyText.SelLength=9999
EndIf
EndSub
到此,类模块宣告完毕,保存它(.cls文件)。
5、下面就是类模块的使用,非常简单。
现在一个窗体上放3个TextBox控件,名称分别为Text1、Text2、Text3。
图3测试类模块
在通用部分键入以下代码:
’定义类模块的实例,因为有3个TextBox所以定义3个实例
Dimt1AsNewclsTest
Dimt2AsNewclsTest
Dimt3AsNewclsTest
在窗体的Load事件中键入以下代码:
PrivateSubForm_Load()
’调用类模块的方法BindText参数是窗体上的TextBox们
t1.BindTextText1
t2.BindTextText2
t3.BindTextText3
EndSub
6、运行程序,鼠标在不同的文本框上移动时,可以看到相应的文本框自动获得焦点,并将内容选中。
7、在其他程序里怎么用?
也很简单,在其它工程中,到[工程]菜单,选择[添加文件],选择你以前保存的.cls文件(建议先将此文件拷到工程目录下,以便于管理)说到这里您一定对类模块有了一个大概的了解,发挥自己的想象力,可以作出更好的东西!
一个复杂点的例子
——窗体动态分割条
总体思路
可以用现成的控件来做分割条,如Label。
一个分割条分割窗体实际上是把窗体上的控件根据分割条的位置来重新安排。
要实现这个功能,首先鼠标要能移动分割条,其次分割条要知道它两侧分别有哪些控件,可以随时根据它自身的位置来计算两侧控件的新位置。
详细思路
分割条分为水平和垂直,水平分割条是水平移动,它自己是垂直的,控件在它的左右。
垂直分割条则相反。
因此要有一个变量保存分割条的类型。
1、鼠标移动分割条
当鼠标在Label控件上按下时,表明移动开始,当鼠标移动时,用API函数得到鼠标在屏幕上的位置,转换为窗体上的坐标,水平分割条则设置Label控件的水平位置为鼠标水平位置,垂直位置不变,垂直分割条则设置Label控件的垂直位置为鼠标垂直位置,水平位置不变,
执行步骤3,鼠标键松开,表明移动结束。
2、让分割条知道它两侧有哪些控件
每个分割条都有一个数组,该数组保存了对分割条两侧控件的引用,同时还有该控件相对分割条的位置(左、右、上、下),水平分割条只有左右,垂直分割条只有上下。
3、控件位置的计算
(1)水平分割条:
控件在左侧:
控件宽度=分割条左侧位置-控件左侧位置-控件与分割条间隔控件在右侧:
控件左侧位置=分割条左侧位置+分割条宽度+控件与分割条间隔
控件宽度=窗体宽度-分割条左侧位置-分割条
宽度-控件与分割条间隔
另外:
如果控件是位于窗体最下方的控件,应将控件填满窗体下方,
控件高度=分割条顶部位置+分割条高度-控件顶部位置
(2)垂直分割条控件位置:
控件在上方:
控件高度=分割条顶部位置-控件顶部位置-控件与分割条间隔
控件在下方:
控件顶部位置=分割条顶部位置+分割条高度+控件与分割条间隔
控件高度=窗体高度-分割条顶部位置-分割条
高度-控件与分割条间隔
另外:
如果控件是位于窗体最右方的控件,应将控件填满窗体右方:
控件宽度=分割条左侧位置+分割条宽度-控件左侧位置
编码
1、通用部分
OptionExplicit’强制变量声明
’API与数据类型定义:
’点数据类型POINTAPI的定义
PrivateTypePOINTAPI
XAsLong
YAsLong
EndType
’将屏幕坐标转化为窗体坐标
PrivateDeclareFunctionScreenToClientLib"user32"(ByVal
hwndAsLong,lpPointAsPOINTAPI)AsLong
’将窗体坐标转化为屏幕坐标
PrivateDeclareFunctionClientToScreenLib"user32"(ByVal
hwndAsLong,lpPointAsPOINTAPI)AsLong
’设置鼠标捕捉
PrivateDeclareFunctionSetCaptureLib"user32"(ByVal
hwndAsLong)AsLong
’释放鼠标捕捉
PrivateDeclareFunctionReleaseCaptureLib"user32"()
AsLong
’获得鼠标在屏幕上的位置
PrivateDeclareFunctionGetCursorPosLib"user32"(lpPoint
AsPOINTAPI)AsLong
’设置鼠标在屏幕上的位置
PrivateDeclareFunctionSetCursorPosLib"user32"(ByVal
XAsLong,ByValYAsLong)AsLong
2、自定义数据类型
’分割条类型:
0水平,1垂直
DimHorVAsInteger
’窗体变量引用当前的窗体
DimmFormAsForm
’控件数组类型
PrivateTypeBindControl
binControlAsControl’控件
’控件位置:
0左侧,1右侧,2上方,3下方
posAsInteger
EndType
’控件数组定义了10个控件的容量可以根据实际需要增减
DimmyBindControls(10)AsBindControl
’控件数组中已有元素的数量
DimnumControlsAsInteger
’鼠标位置点
DimpotAsPOINTAPI
’鼠标是否在移动分割条
DimResizingAsBoolean
’分割条的最小位置和最大位置
DimiMinAsInteger
DimiMaxAsInteger
’带事件的控件定义这里我们选用Label
DimWithEventsSplitBarAsLabel
3、类模块方法
’给分割条控件指定所在的窗体、Label控件、分割条类型等
PublicSubAttach(fAsForm,spAsLabel,hvAsInteger,minAsLong,maxAsLong)
SetmForm=f’设置窗体变量
’设置分割条控件变量为传入的Label控件
SetSplitBar=sp
’给分割条做个标记,表明这个Label是分割条
SplitBar.Tag="SPLIT"
Ifhv=0Then’如果是水平分割条
HorV=0’设置分割条类型
’设置Label控件的鼠标光标为左右箭头
SplitBar.MousePointer=9’最小位置与最大位置设置
Ifmax iMin=100
iMax=mForm.ScaleWidth-SplitBar.Width-100
Else
iMin=min
iMax=max
EndIf
Else
HorV=1’如果是水平分割条
’设置Label控件的鼠标光标为上下箭头
SplitBar.MousePointer=7
Ifmax iMin=100
iMax=mForm.ScaleWidth-SplitBar.Height-100
Else
iMin=min
iMax=max
EndIf
EndIf
EndSub
’添加分割条左侧的控件如果不是水平分割条则退出
PublicSubSetLeftBind(cAsControl)
IfHorV=1ThenExitSub
AddBindControlc,1
EndSub
’添加分割条上方的控件如果不是垂直分割条则退出
PublicSubSetUpBind(cAsControl)
IfHorV=0ThenExitSub
AddBindControlc,2
EndSub
’添加分割条下方的控件如果不是垂直分割条则退出
PublicSubSetDownBind(cAsControl)
IfHorV=0ThenExitSub
AddBindControlc,3
EndSub
’帮助函数私有往控件数组里加入一个控件
PrivateSubAddBindControl(cAsControl,iposAsInteger)
IfnumControls<10Then’确保控件数组不溢出
numControls=numControls+1
SetmyBindControls(numControls-1).binControl=c
myBindControls(numControls-1).pos=ipos
EndIf
EndSub
’计算控件位置
PublicSubArrangePosition()
OnErrorGoToerr
DimiAsInteger
IfHorV=0Then
’水平分割条设置高度为窗体的高度
SplitBar.Height=mForm.ScaleHeight-_
SplitBar.Top-10
Else
’垂直分割条设置宽度为窗体的宽度如果要将垂直分割条嵌入水平分割条中则将此分支去掉(见本文例图)
’SplitBar.Width=mForm.ScaleWidth-SplitBar.
Left-10
EndIf
Dimi1AsInteger
Dimi2AsInteger
Dimlf1AsInteger’控件右侧或底部的边界
Dimlf2AsInteger’控件右侧或底部的边界
’垂直分割找到最右端的控件上方为i1,下方为i2
IfHorV=1Then
Fori=0TonumControls-1
WithmyBindControls(i)
If.pos=2Then
If.binControl.Left+.binControl.Width>lf1Then
lf1=.binControl.Left+.binControl.Width
i1=i
EndIf
ElseIf.pos=3Then
If.binControl.Left+.binControl.Width>lf2Then
lf2=.binControl.Left+.binControl.Width
i2=i
EndIf
EndIf
EndWith
Nexti
Else’水平分割找到最底部的控件左边为i1,右边为i2
Fori=0TonumControls-1
WithmyBindControls(i)
If.pos=0Then
If.binControl.Top+.binControl.Height>lf1Then
lf1=.binControl.Top+.binControl.Height
i1=i
EndIf
ElseIf.pos=1Then
If.binControl.Top+.binControl.Height>lf2Thenlf2=.binControl.Top+.binControl.Height
i2=i
EndIf
EndIf
EndWith
Nexti
EndIf
’遍历控件数组进行位置计算
Fori=0TonumControls-1
WithmyBindControls(i).binControl
SelectCasemyBindControls(i).pos
Case0’左侧控件
.Width=SplitBar.Left-.Left-10
Ifi=i1Then’如果是最底部的控件
.Height=SplitBar.Top+SplitBar.Height-.Top
EndIf
Case1’右侧控件
.Left=SplitBar.Left+SplitBar.Width+10
.Width=mForm.ScaleWidth-SplitBar.Left-SplitBar.Width-10
Ifi=i2Then’如果是最底部的控件
.Height=SplitBar.Top+SplitBar.Height-.Top
EndIf
Case2’上方控件
.Height=SplitBar.Top-.Top-10
Ifi=i1Then’如果是最右侧的控件
.Width=SplitBar.Left+SplitBar.Width-.Left
EndIf
Case3’下方控件
.Top=SplitBar.Top+SplitBar.Height+10
.Height=mForm.ScaleHeight-SplitBar.Top-SplitBar.Height-10
Ifi=i2Then’如果是最右侧的控件
.Width=SplitBar.Left+SplitBar.Width-.Left
EndIf
EndSelect
EndWith
Nexti
err:
EndSub
4、类模块及控件事件
’类模块初始化
PrivateSubClass_Initialize()
numControls=0’控件数设为0
Resizing=False’鼠标调整设为假
EndSub
’鼠标在Label控件上按下左键,开始调整
PrivateSubSplitBar_MouseDown(ButtonAsInteger,Shift
AsInteger,XAsSingle,YAsSingle)
IfButton=vbLeftButtonThenResizing=True
EndSub
’鼠标在Label控件上抬起左键,结束调整
PrivateSubSplitBar_MouseUp(ButtonAsInteger,ShiftAs
Integer,XAsSingle,YAsSingle)
IfButton=vbLeftButtonThenResizing=False
EndSub
’鼠标移动事件
PrivateSubSplitBar_MouseMove(ButtonAsInteger,ShiftAsInteger,XAsSingle,YAsSingle)
’得到鼠标位置
GetCursorPospot
’屏幕坐标转为窗体坐标
ScreenToClientmForm.hwnd,pot
’如果鼠标不在调整则退出
IfNotResizingThenExitSub
IfHorV=0Then’如果是水平分割条
’如果鼠标在窗体上的水平位置超过最小值
Ifpot.X*Screen.TwipsPerPixelX ’设置鼠标位置为窗体上水平位置最小值退出
pot.X=iMin/Screen.TwipsPerPixelX
ClientToScreenmForm.hwnd,pot
SetCursorPospot.X,pot.Y
ExitSub
’如果鼠标在窗体上的水平位置超过最大值
ElseIfpot.X*Screen.TwipsPerPixelX>iMaxThen
’设置鼠标位置为窗体上水平位置最大值退出
pot.X=iMax/Screen.TwipsPerPixelX
ClientToScreenmForm.hwnd,pot
SetCursorPospot.X,pot.YExitSub
Else
’设置分割条的左侧位置为鼠标水平位置减去
’分割条宽度的二分之一
SplitBar.Left=pot.X*Screen.TwipsPerPixelXSplitBar.Width/2
EndIf
Else’如果是垂直分割条
’如果鼠标在窗体上的水平位置超过最小值
Ifpot.Y*Screen.TwipsPerPixelY ’设置鼠标位置为窗体上水平位置最小值退出
pot.Y=iMin/Screen.TwipsPerPixelY
ClientToScreenmForm.hwnd,pot
SetCursorPospot.X,pot.Y
ExitSub
’如果鼠标在窗体上的水平位置超过最大值
ElseIfpot.Y*Screen.TwipsPerPixelY>iMaxThen
’设置鼠标位置为窗体上水平位置最大值退出
pot.Y=iMax/Screen.TwipsPerPixelY
ClientToScreenmForm.hwnd,pot
SetCursorPospot.X,pot.Y
ExitSub
Else
’设置分割条的顶部位置为鼠标垂直位置
’减去分割条高度的二分之一
SplitBar.Top=pot.Y*Screen.TwipsPerPixelY-SplitBar.Height/2
EndIf
EndIf
’调用子程序计算控件位置
ArrangePositio