VB中动态创建控件
VB相关技术:创建数据驱动窗体
所谓数据驱动窗体确实是依照所请求的数据的不同生成相应的窗体。举例来讲,假设你此刻有一个数据库,其中有些字段必需依照登录者的身份加以显示,授权级别高的用户能够阅读并修改这些字段的内容;授权级别一样的用户只能阅读这些字段中的数据;授权级别低的用户那么不能阅读这些字段中的内容。要做到这一点就得利用VB动态添加控件的功能。
动态创建控件
不管你想要创建何种类型的数据驱动窗体,你必需明白如安在运行时动态地创建控件。你能够通过控件数组做到这一点,但VB6的Controls集合所提供的Add 方式,功能更壮大,灵活性更高。利用该方式,你不需要在设计时将控件的实例放在窗体上。事实上,用Add方式你乃至能够创建程序在编译时全然不存在的控件。这种方式的用法也很简单:
' 声明一个窗体级的变量
Dim WithEvents txtTotal As TextBox
Sub CreateTextbox()
' 创建新的Textbox控件
Set txtTotal = ("", "txtTotal")
' 将控件移动到你所需要的地方
1000, 800, 1200, 300
' 创建时,所有的控件都是不可见的
= True
End Sub
请注意Add方法的第二个参数:分配给控件的名称。从代码可读性出发,这个名称一般都与变量名相同。你可以用这个名称从Controls集合中获取相应的控件或移除该控件。例如:
"txtTotal"
在变量声明时加上WithEvents关键字,即便在设计时窗体不存在该控件,你也能够为该控件的事件编写代码。
上面所讲的方式只适合解决VB内置的控件。例如,当你要添加一个TreeView
控件时,VB会要求你证明你已经取得了合法的授权来创建该控件的实例。换句话说,VB要证明那个控件是买来的,而不是从其它附有该控件的程序中借来的。
要证明你通过了合法的授权有下面几种方式:
在窗体上放置一个控件。这也是最简单的方式。你完全没有必要将那个窗体显示出来。
将相关的控件添加到工具箱中,然后在“工程属性”对话框的“生成”标签页中取消选择“删除有关未使用的ActiveX控件的信息”这一项。
向Licenses集合添加一个元素。例如: ("")
仅仅创建了控件并不足够
要创建一个数据驱动窗体,仅仅明白动态创建控件还不够。例如:此刻你要创建一个能依照数据库中表的不同字段自动生成控件的窗体。该窗体可能会创建单行文本框,其长度随字段长度不同而不同;也可能会创建单项选择按钮或复选按钮以显示布尔型字段;乃至可能创建一个多行文本框显示备注型字段。
你需要解决的第一个问题是:文本框控件的Multiline属性在运行时是只读的,只在设计时可用。幸亏,微软的Microsoft Windowless Controls 能够解决那个问题。这组控件集包括了轻量级的
TextBox,ComboBox,ListBox,CheckBox,OptionButton,CommandButton和两个scrollbar控件。这些控件与VB内置的相应的控件最大的区别在于:这些控件的所有属性在运行时是可读写的。在VB的安装光盘中的
Common\Tools\VB\WinLess文件夹中能够到那个控件组。用下面的代码能够创建一个多行文本框:
Dim WithEvents txtEditor As
Private Sub CreateEditor()
Set txtEditor = ( "", "txtEditor")
0, 0, 4000, 4000
= True
= wlBoth
activex 控件
= True
End Sub
另外一个问题比较复杂:在事先不知道要创建多少个控件的情况下,如何给每个对新创建的控件的引用分配唯一的带WithEvents关键字的变量。换句话说就是要对新创建的控件的事件进行编程,前提是你在设计时不知道程序会创建多少个控件。使用对象数组显然不行,因为不能用WithEvents关键字声明一个对象数组;更坏的情况是,资一个变量定义为As Control或As Object也不行,因为还是不能用WithEvents。
问题源自于咱们无法在运行时捕捉一个对象数组事件。因此咱们只能采取曲线救国的方法。所要的编写的代码可能比你想象的多,只是那个解决方式很有趣,值得咱们如此去做。
咱们需要两个辅助类模块来捕捉事件,别离取名为ControlItems和ControlItem。ControlItems是一个集合类,其中保留了ControlItem对象及其数量。该数量等于你所要对之编程的控件的数量。ControlItem类的每一份实例捕捉控件产生的事件,然后挪用在其所属的ControlItems集合类中的进程,最后由ControlItems在窗体中触发事件并执行事件中的代码。整个进程如以下图所示:
捕捉多个控件的事件
为简单起见,假设你要捕捉来自所有的动态添加到窗体上去的控件的Validate 事件。为完成那个工作,ControlItems集合类必需向父窗体展现该事件,并随时预备接收来自其子ControlItem类的通知以触发事件。代码如下:
Event Validate(CtrlItem As ControlItem, Cancel As Boolean)
Private m_ControlItems As New Collection
' 向集合中添加一个新的ControlItem项目
Function Add(ctrl As Control) As ControlItem
Dim newItem As New ControlItem
ctrl, Me
' 添加到私有类
newItem
' 返回新项目给调用者
Set Add = newItem
End Function
Friend Sub Notify_Validate(Item As ControlItem, Cancel As Boolean)
RaiseEvent Validate(Item, Cancel)
End Sub
ControlItem类必须捕获来自动态添加到窗体中的控件的事件,并通知其所属的ControlItems集合类。很显然,ControlItem类必须有一个用WithEvents关键字定义的变量来引用真正的控件。这意味着你不能将变量声明为As Control或As Object。如果你决定在窗体中所动态添加的控件不使用VB内置的控件的话,这个问题的解决办法相当的简单。你只需要将变量声明为VBControlExtender
类型就行了。对于创建数据驱动窗体来讲,不使用VB内置的控件并不是一件大不了的事。
将变量声明为VBControlExtender,并加上WithEvents关键字,你就能够直接捕捉Validate,GotFocus,LostFocus,DragDrop和DragOver这几个事件了。若是要捕捉其它更多的事件,你能够利用ObjectEvent。下面是ControlItem类模块中的代码:
Public WithEvents Ctrl As VBControlExtender
' 所属的ControlItems对象
Dim m_Parent As ControlItems
Sub Init(ctl As Object, parnt As ControlItems)
Set Ctrl = ctl
Set m_Parent = parnt
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论