VB列表的jsp 列表动态加载组件如何实现?

VB动态添加控件和事件响应
熟悉VB的朋友对使用ActiveX控件一定不会陌生,众多控件极大地方便了编程,但唯一的缺陷是不能动态加载控件,必须在设计时通过引用,将控件放置在窗体上。VB6.0已能够解决该问题,只是帮助中没有明确说明,并且没有描述到一些关键功能,由于以前的版本中可以动态创建进程外服务:如果对象是外部可创建的,可在
Set 语句中用 New 关键字、CreateObject 或 GetObject
从部件外面将对象引用赋予变量。如果对象是从属对象,则需使用高层对象的方法,在 Set 语句中指定一个对象引用:
Dim xlApp1 As Excel.Application
Set xlApp1 = New Excel.Application
Dim xlApp As
'定义存放引用对象的变量。
Set xlApp = CreateObject("excel.application")
xlApp.Visible = True
这些语法很容易造成误导,以为动态加载ActiveX控件也是此方法,可能有朋友也象我一样利用CreateObject尝试了无数次,却无功而返,不知微软公司是出于何种考虑,动态加载ActiveX控件是扩展控件集合的方式实现,通过实际摸索,终于就如何实现动态ActiveX控件找出了一条切实可行的方法,下面以一个具体的实例来详细说明。
---- 一、ActiveX控件
---- ActiveX 控件是 Visual Basic 工具箱的扩充部分。使用 ActiveX
控件的方法与使用其它标准内装的控件,如 CheckBox 控件,完全一样。在程序中加入 ActiveX
控件后,它将成为开发和运行环境的一部分,并为应用程序提供新的功能。
---- ActiveX 部件通过客户端/服务器关系与应用程序— 及与部件相互之间—
交互作用。客户端是使用部件功能的应用程序代码或部件。服务器是部件及其关联的对象。例如,假设应用程序使用 ActiveX
控件来提供一个标准的雇员窗体,供公司的多种应用程序使用。提供雇员窗体的 ActiveX
控件就是服务器,使用这个控件的应用程序就是服务器的客户端。
---- 二、加载方法
---- VB6.0中对Controls 集合进行了扩展,以前版本中Controls
集合在窗体上列举出已加载的控件,这在迭代过程中是很有用的。Controls 集合标识一个叫做 Controls
的内在窗体级变量。如果忽略可选的 object 所在处的整数,则关键字 Controls
必须包括在内。我们通常在窗口中使用如下代码:
Text1.Text="Hello, world"
其实也可以使用如下代码达到同一目的:
Controls(1).Text="Hello, world"
---- 在VB6.0中除了原来的Clear、Remove
方法外(很奇怪,为什么微软在VB5.0中只提供这两种方法,而没有提供Add方法,因为没有Add,这两种方法也就没什么用处),增加了Add方法,该方法就是用于动态加载控件的:
Controls.Add(progid as String, Name as String);
progid: ActiveX部件的ProgID,如:"VB.CheckBox";
Name:ActiveX部件加载后的名称,如: "MyCheckBox";
若要在窗体上添加一个名为MyButton的按钮,可以使用:
dim oControl as
'窗体级变量
注意:这里声明为Object对象类型
Private Sub LoadControl()
Set oControl = Controls.Add
("VB.CommandButton", "MyButton")
oControl.Left = 10
oControl.Top = 10
oControl.Visible =
'使控件可见
这是VB6.0的标准语法,它在例程中也是如此演示的,不过该方法虽然现实了控件的动态加载,按钮显示在窗体上,可以象普通按钮一样按下去,但加载的控件不能预先设计响应事件代码,如:事件Sub
MyButton_Click()将是非法的,当然,可以将要响应的事件封装在控件内部。就编程的观点来看该方法没什么大的用处,开发ActiveX控件的目的是为了资源共享,为了被其他开发人员利用,所以要提供必要的事件接口,显然利用该方法不行,通过分析VBControls等相关对象,找出VBControlExtender对象与EventInfo相结合能提供事件陷井捕捉,VBControlExtender对象对动态添加控件特别有用,它提供了一套通用的属性、方法、事件给开发人员,它的一个突出特点是能编程设计控件的事件,熟习类编程的朋友对带事件的对象声明一定不会陌生:
---- Dim WithEvents objElemt as
CElemtVBControlExtender也不例外,声明的语法一样,只不过它有个特殊的事件ObjectEvent(Info As
EventInfo),它能捕捉到对象使用RaiseEvent产生的所有事件,EventInfo数据结构映射了事件的名称、参数个数和参数的值。VBControlExtender和
EventInfo相结合,采用Select Case
就可以预先将不同类对象的事件放置一起,各自独立运作。将上面的代码改写一下就能提供Click事件了:
---- Dim WithEvents oControl As VBControlExtender
'带事件声明声明之后您就可以在代码窗口的左上角的对象下拉框中发现该对象出现了,也就是说,该对象有了事件或方法了,它的事件有DragDrop,DragOver
,LostFocus ,GotFocus
,ObjectEvent和Validate,其中ObjectEvent是通用的事件捕捉。
Private Sub LoadControl()
Set oControl = Controls.Add
("VB. CommandButton", "MyButton")
oControl.Visible = True
Private Sub oControl_ObjectEvent(Info As EventInfo)
Select Case Info.Name
Case "Click" 'Click事件
'您可以添加处理Click事件代码
&&& MsgBox
"您按了MyButton!"
Case Else ' 其他事件
' Handle unknown events here.
End Select
当然对微软提供的标准控件能采用该方法添加,大家都不会怀疑,但自己开发的控件也能吗?答案是肯定的,我们可以用一个实际的例子进行说明。
---- 三、实例描述
假设一个本地网络的监控系统,需要在原理图与实物示意图间切换,原理图包括组网结构、传输资源、监控主机等,而实物示意图包括路由器、设备、采集器等,当然两种图的事件要一致,如双击某个设备图形将显示给设备的实时数据等,为了简化维护,将原理图与实物示意图封装成ActiveX控件,由于每种图需要加载许多图形控件,消耗资源较大,不能同时加载,需要将其分解为两个控件,在切换时首先卸载一个控件,然后加载另一个控件,所以要实现动态加载ActiveX控件。
---- 原理图控件为--Theory.ocx ,对应工程为CTheory;
---- 实物图控件为---Fact.ocx ,对应工程为CFact;
---- 注意:为了简化,在设计控件时不设置许可证关键字。
实物图控件上的图形对象可以被拖动,拖动后的位置信息通过事件ChangePosition来通知拥有该控件的窗体,以便下次加载能显示在最后位置,实物图和原理图控件都有双击事件完成的工作相同,其他事件此处忽略。
---- 四、具体示例
---- 1、准备工作
---- 对控件Theory.ocx 、Fact.ocx 进行注册(利用Regsvr32.exe注册);
---- 建立窗体frmTest.frm ,在窗体上放置按钮cmdLoadOcx—“原理图”
---- 2、声明窗体级变量与加载函数LoadControl
Dim WithEvents oControl As VBControlExtender
'地图仿真控件对象
Dim mblnTheory As Boolean '是否显示原理图
Private Function LoadControl(intType As Integer)
If Not oControl Is Nothing
'首先判断对象是否存在,若存在则卸载
Controls.Remove("MapView")&&&
'卸载控件,此操作非常重要
If intType = 0 Then
Set oControl = Controls.Add
("CTheory. Theory", "MapView")
Set oControl = Controls.Add
("CFact.Fact", "MapView")
oControl.Height = 3500
oControl.Width = 6500
oControl.Top = 100
oControl.Visible = True
End Function
Private Sub Form_Load()
mblnTheory = True
---- 3、为按钮cmdLoadOcx编写代码
Private Sub cmdLoadOCX_Click()
If mblnTheory Then
Call LoadControl(0)
mblnTheory = False
cmdLoadOCX.Caption = "实物图"
Call LoadControl(1)
mblnTheory = True
cmdLoadOCX.Caption = "原理图"
---- 4、为事件ChangePosition编写代码
Private Sub oControl_ObjectEvent
(Info As EventInfo)
Select Case Info.Name
Case "ChangePosition"
MsgBox CStr(Info.EventParamters.Item(
1).Value) + ":" +
CStr(Info.EventParamters.Item(2).Value)
Case "DbClick"
'双击处理代码
Case Else '
End Select
---- 注意:
EventInfo的参数EventParamters集合中是以1开始的,一般来说,微软新的集合一般是以1开始的,而旧的是以0开始的,如RdoErrors.Item(0)。
---- 5、关闭窗口前卸载控件
Private Sub Form_Unload(Cancel As Integer)
Controls.Remove("MapView")
Set oControl = Nothing
---- 6、特别注意
---- 通过Controls.Add方法添加的ActiveX控件一定不能在该工程中有该控件的任何引用,否则系统将出错。
---- 四、小结
通过使用动态加载ActiveX控件使用庞大的应用程序变得很小,将不同的ActiveX控件进行各种组合,使应用程序更加灵活多变,如您的应用系统要处理三十种门禁,而某个具体的用户可能只有一种或两种门禁,根本没必要首先将所有门禁包含到应用中,可将各个门禁独立封装,只安装注册需要的组件,就象Windows的自定义安装一样。微软的未来技术基础是分布式的组件技术(DCOM),将会把代码的重用发挥得淋漓尽致。您不妨试一试动态加载,也许会产生令您惊喜的效果!
---- 本代码在Win98、VB6.0(英文版)上编译、运行。
&&&&&&&&&&&&&&&&&&&&&&&&&
创建数据驱动窗体
所谓数据驱动窗体就是根据所请求的数据的不同生成相应的窗体。举例来讲,假设你现在有一个数据库,其中有些字段必须根据登录者的身份加以显示,授权级别高的用户可以浏览并修改这些字段的内容;授权级别一般的用户只能浏览这些字段中的数据;授权级别低的用户则不能浏览这些字段中的内容。要做到这一点就得利用VB动态添加控件的功能。
动态创建控件
无论你想要创建何种类型的数据驱动窗体,你必须知道如何在运行时动态地创建控件。你可以通过控件数组做到这一点,但VB6的Controls集合所提供的Add方法,功能更强大,灵活性更高。使用该方法,你不需要在设计时将控件的实例放在窗体上。实际上,用Add方法你甚至可以创建程序在编译时根本不存在的控件。这种方法的用法也很简单:
' 声明一个窗体级的变量
Dim WithEvents txtTotal As TextBox
Sub CreateTextbox()
创建新的Textbox控件
&&& Set txtTotal
= Controls.Add("VB.TextBox", "txtTotal")
将控件移动到你所需要的地方
txtTotal.Move ,
创建时,所有的控件都是不可见的
txtTotal.Visible = True
请注意Add方法的第二个参数:分配给控件的名称。从代码可读性出发,这个名称一般都与变量名相同。你可以用这个名称从Controls集合中获取相应的控件或移除该控件。例如:
Controls.Remove "txtTotal"
在变量声明时加上WithEvents关键字,即使在设计时窗体不存在该控件,你也可以为该控件的事件编写代码。
上面所讲的方法只适合解决VB内置的控件。例如,当你要添加一个TreeView控件时,VB会要求你证明你已经得到了合法的授权来创建该控件的实例。换句话说,VB要证明这个控件是买来的,而不是从其它附有该控件的程序中借来的。
要证明你经过了合法的授权有下面几种方法:
在窗体上放置一个控件。这也是最简单的方法。你完全没有必要将这个窗体显示出来。
将相关的控件添加到工具箱中,然后在"工程属性"对话框的"生成"标签页中取消选择"删除有关未使用的ActiveX控件的信息"这一项。
向Licenses集合添加一个元素。例如:Debug.Print
Licenses.Add("MSMask.MaskedEdBox")
仅仅创建了控件并不足够
要创建一个数据驱动窗体,仅仅知道动态创建控件还不够。例如:现在你要创建一个能根据数据库中表的不同字段自动生成控件的窗体。该窗体可能会创建单行文本框,其长度随字段长度不同而不同;也可能会创建单选按钮或复选按钮以显示布尔型字段;甚至可能创建一个多行文本框显示备注型字段。
你需要解决的第一个问题是:文本框控件的Multiline属性在运行时是只读的,只在设计时可用。幸好,微软的Microsoft
Windowless Controls
6.0可以解决这个问题。这组控件集包括了轻量级的TextBox,ComboBox,ListBox,CheckBox,OptionButton,CommandButton和两个scrollbar控件。这些控件与VB内置的相应的控件最大的区别在于:这些控件的所有属性在运行时是可读写的。在VB的安装光盘中的Common/Tools/VB/WinLess文件夹中可以找到这个控件组。用下面的代码可以创建一个多行文本框:
Dim WithEvents txtEditor As&&
MSWLess.WLText
Private Sub CreateEditor()
txtEditor = Controls.Add( "MSWLess.WLText", "txtEditor")
txtEditor.Move 0, 0,
txtEditor.MultiLine = True
txtEditor.ScrollBars = wlBoth
txtEditor.Visible = True
另外一个问题比较复杂:在事先不知道要创建多少个控件的情况下,如何给每个对新创建的控件的引用分配唯一的带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
&&& newItem.Init
添加到私有类
m_ControlItems.Add newItem
返回新项目给调用者
&&& Set Add =
End Function
Friend Sub Notify_Validate(Item As ControlItem, Cancel As
&&& RaiseEvent
Validate(Item, Cancel)
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 =
&&& Set m_Parent
Private Sub Ctrl_Validate(Cancel As Boolean)
通知所属的ControlItems类
m_Parent.Notify_Validate Me, Cancel
将下面的代码放入窗体中,就可以捕获动态添加的控件所产生的事件了:
Dim WithEvents CtrlItems As New ControlItems
Private Sub cmdCreateControls_Click()
&&& Dim ctrl As
创建两个文本框并将它们添加到ControlItems集合?&&&
Set ctrl = Controls.Add("MSWLess.WLText", "One")
&&& ctrl.Move
&&& ctrl.Visible
CtrlItems.Add ctrl
注意你可以使用同一个变量
&&& Set ctrl =
Controls.Add("MSWLess.WLText", "Two")
&&& ctrl.Move
&&& ctrl.Visible
CtrlItems.Add ctrl
Private Sub CtrlItems_Validate( CtrlItem As ControlItem, Cancel As
&&& ' 拒绝空字符串 -
注意如何引用控件的属?&&&
If CtrlItem.Ctrl.Text = ""
Cancel=True
现在解决了最困难的部分,要创建一个数据驱动窗体就变得简单了
**************************************************************
****************************************************************
动态添加控件
VB6有一个新功能,可以动态添加控件,不用控件数组:
object.Add (ProgID, name, container)
参数说明&&
Object 必需的。一个对象表达式,其值是"应用于"列表中的一个对象。
ProgID 必需的。一个标识控件的字符串。大多数控件的 ProgID 都可通过查看对象浏览器来决定。控件的 ProgID
是由控件的库和类组成的。
例如,CommandButton 控件的 ProgID 是 VB.CommandButton。在ProgID
与对象浏览器中所显示的不一样的情况下,Visual Basic
将显示一个包括正确 ProgId 的错误信息。
name 必要的。一个字符串,用来标识集合的成员。
container 可选的。一个对象引用,它指定控件的容器。如果没有指定或为NULL,缺省值为 Controls
集合所属的容器。通过指定该参数,可以把一个控件放置在任何现存的容器控件(如 Frame 控件)中。用户控件或 ActiveX
文档也可以作为一个容器。
举例: //在picture1上面添加一个commandbutton
Private Sub Form_Load()
Form1.Controls.Add "VB.CommandButton", "cmdOk", Picture1
With Form1!cmdOk
.Visible = True
.Width = 500
.Caption = "确认(&Y)"
  重点:当您添加一个未引用的需要许可证的控件到一个现存的(已部署好的)应用程序时,在使用 Add
方法之前您必须也添加这个控件的许可证关键字。
在运行时添加未引用的控件:
  您也可以利用 Add 方法来动态添加一个在工程中没有被引用的控件。("未引用的"控件是不出现在 Toolbox
中的控件)。为此,您必须也把控件的License 关键字添加到 Licenses
集合中。下面的示例中在添加控件本身之前添加了控件的许可证关键字:
Option Explicit
Private WithEvents extCtl As VBControlExtender
Private Sub Form_Load()
Licenses.Add "prjWeeks.WeeksCtl", "xydsfasfjewfe"
Set extCtl = Form1.Controls.Add("prjWeeks.WeeksCtl", "ctl1")
extCtl.Visible = True ' The control is invisible by default.
  但是,为了编程这样一个未引用控件的事件,您必须使用 WithEvents
关键字声明一个对象变量为VBControlExtender 对象(如上),并且设置该对象变量到Add
方法返回的引用上。然后,利用VBControlExtender 对象的
ObjectEvent事件来编程该控件的事件。下面是一个简单的例子。
Option Explicit
Dim WithEvents objExt As VBControlExtender '声明 Extender 变量
Private Sub LoadControl()
Licenses.Add "Project1.Control1", "xydsfasfjewfe"
Set objExt = Controls.Add("Project1.Control1", "myCtl")
objExt.Visible = True
Private Sub extObj_ObjectEvent(Info As EventInfo)
'使用 Select Case 编程控件的事件。
Select Case Info.Name
Case "Click"
'这里处理 Click 事件。
'现在显示其他的 case
Case Else '未知事件
'这里处理未知事件。
End Select
Note: 不能把一个固有的控件指定给这个 VBControlExtender 变量; 任何这种试图将引起类型不匹配错误。
  但是,您也可以通过使用 WithEvents
关键字声明一个对象变量,并且设置该方法返回的引用为该变量,从而编程一个动态添加控件的事件,如下所示。
Option Explicit
'声明对象变量为 CommandButton 。
Private WithEvents cmdObject As CommandButton
Private Sub Form_Load()
Set cmdObject = Form1.Controls.Add("VB.CommandButton",
cmdObject.Visible = True
cmdObject.Caption = "Dynamic CommandButton"
Private Sub cmdObject_Click()
Print "This is a dynamically added control"
  如果希望添加一个用户控件或任何 ActiveX 控件到您的窗体,必须或者把这个控件添加到"工具箱",或者把控件的 License
关键字添加到 Licenses集合中。有关详细信息请参阅"增加方法 (Licenses 集合)"。
  注意:如果您添加一个 ActiveX 或用户控件到您的工程,但是没有在窗体中使用它,您也必须不要选定"工程属性"对话框的"生成"
选项卡上的"删除有关未使用的 ActiveX 控件"选项。如果您的应用程序试图添加该控件,那么该 Add
方法将失败,因为必需的信息已经被丢弃。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。vb动态加载的控件不显示?_百度知道
vb动态加载的控件不显示?
提问者采纳
width=text1(0); 调整text1(1)的宽度使之能够呆在窗体里面end iftext1(1);调整text1(1)的高度使之能够呆在窗体里面end ifif text1(1),先创建控件数组text1(index).height+50if text1(1);=form1.width then
&#39,出了窗体什么控件都是看不到的.top+text1(1),窗体是控件的容器.top=text1(0),至少要有一个text1(0).widthtext1(1).left=text1(0).lefttext1(1). visible =true说了这么多就是告诉你在显示之前一定要确保新控件的位置不会被什么东西盖住或者跑到窗体之外;=form1,然后load(text1(1))text1(1)以textbox为例.height&gt.heighttext1(1).height=text1(1).width&gt.top+text1(0).left+text1(1).height then
提问者评价
其他类似问题
为您推荐:
其他2条回答
你要把控件设为可见的,还有控件的位置可能不在窗体内
vb动态加载的控件不显示
大哥你怎么也要把你的控件说下吧 什么控件呀 你要做什么 我们不是神仙呀 看不到你的错误 怎么给你解决呀 对不
您可能关注的推广回答者:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
第一章 ASP.NET 教程 (基础)
第二章 ASP.NET 教程(高级)VB动态创建控件
创建数据驱动窗体
所谓数据驱动窗体就是根据所请求的数据的不同生成相应的窗体。举例来讲,假设你现在有一个数据库,其中有些字段必须根据登录者的身份加以显示,授权级别高的用户可以浏览并修改这些字段的内容;授权级别一般的用户只能浏览这些字段中的数据;授权级别低的用户则不能浏览这些字段中的内容。要做到这一点就得利用VB动态添加控件的功能。
动态创建控件
无论你想要创建何种类型的数据驱动窗体,你必须知道如何在运行时动态地创建控件。你可以通过控件数组做到这一点,但VB6的Controls集合所提供的Add方法,功能更强大,灵活性更高。使用该方法,你不需要在设计时将控件的实例放在窗体上。实际上,用Add方法你甚至可以创建程序在编译时根本不存在的控件。这种方法的用法也很简单:
' 声明一个窗体级的变量
Dim WithEvents txtTotal As TextBox
Sub CreateTextbox()
' 创建新的Textbox控件
Set txtTotal = Controls.Add("VB.TextBox", "txtTotal")
' 将控件移动到你所需要的地方
txtTotal.Move ,
' 创建时,所有的控件都是不可见的
txtTotal.Visible = True
请注意Add方法的第二个参数:分配给控件的名称。从代码可读性出发,这个名称一般都与变量名相同。你可以用这个名称从Controls集合中获取相应的控件或移除该控件。例如:
Controls.Remove "txtTotal"
在变量声明时加上WithEvents关键字,即使在设计时窗体不存在该控件,你也可以为该控件的事件编写代码。
上面所讲的方法只适合解决VB内置的控件。例如,当你要添加一个TreeView控件时,VB会要求你证明你已经得到了合法的授权来创建该控件的实例。换句话说,VB要证明这个控件是买来的,而不是从其它附有该控件的程序中借来的。
要证明你经过了合法的授权有下面几种方法:
在窗体上放置一个控件。这也是最简单的方法。你完全没有必要将这个窗体显示出来。
将相关的控件添加到工具箱中,然后在“工程属性”对话框的“生成”标签页中取消选择“删除有关未使用的ActiveX控件的信息”这一项。
向Licenses集合添加一个元素。例如:Debug.Print
Licenses.Add("MSMask.MaskedEdBox")
仅仅创建了控件并不足够
要创建一个数据驱动窗体,仅仅知道动态创建控件还不够。例如:现在你要创建一个能根据数据库中表的不同字段自动生成控件的窗体。该窗体可能会创建单行文本框,其长度随字段长度不同而不同;也可能会创建单选按钮或复选按钮以显示布尔型字段;甚至可能创建一个多行文本框显示备注型字段。
你需要解决的第一个问题是:文本框控件的Multiline属性在运行时是只读的,只在设计时可用。幸好,微软的Microsoft
Windowless Controls
6.0可以解决这个问题。这组控件集包括了轻量级的TextBox,ComboBox,ListBox,CheckBox,OptionButton,CommandButton和两个scrollbar控件。这些控件与VB内置的相应的控件最大的区别在于:这些控件的所有属性在运行时是可读写的。在VB的安装光盘中的Common\Tools\VB\WinLess文件夹中可以找到这个控件组。用下面的代码可以创建一个多行文本框:
Dim WithEvents txtEditor As MSWLess.WLText
Private Sub CreateEditor()
Set txtEditor = Controls.Add( "MSWLess.WLText", "txtEditor")
txtEditor.Move 0, 0,
txtEditor.MultiLine = True
txtEditor.ScrollBars = wlBoth
txtEditor.Visible = True
另外一个问题比较复杂:在事先不知道要创建多少个控件的情况下,如何给每个对新创建的控件的引用分配唯一的带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
newItem.Init ctrl, Me
' 添加到私有类
m_ControlItems.Add newItem
' 返回新项目给调用者
Set Add = newItem
End Function
Friend Sub Notify_Validate(Item As ControlItem, Cancel As
RaiseEvent Validate(Item, Cancel)
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
Private Sub Ctrl_Validate(Cancel As Boolean)
' 通知所属的ControlItems类
m_Parent.Notify_Validate Me, Cancel
将下面的代码放入窗体中,就可以捕获动态添加的控件所产生的事件了:
Dim WithEvents CtrlItems As New ControlItems
Private Sub cmdCreateControls_Click()
Dim ctrl As Control
' 创建两个文本框并将它们添加到ControlItems集合? Set ctrl =
Controls.Add("MSWLess.WLText", "One")
ctrl.Move 100, 200,
ctrl.Visible = True
CtrlItems.Add ctrl
' 注意你可以使用同一个变量
Set ctrl = Controls.Add("MSWLess.WLText", "Two")
ctrl.Move 100, 800,
ctrl.Visible = True
CtrlItems.Add ctrl
Private Sub CtrlItems_Validate( CtrlItem As ControlItem, Cancel
As Boolean)
' 拒绝空字符串 - 注意如何引用控件的属? If CtrlItem.Ctrl.Text = ""
Then Cancel=True
现在解决了最困难的部分,要创建一个数据驱动窗体就变得简单了
****************************************************************
动态添加控件
VB6有一个新功能,可以动态添加控件,不用控件数组:
object.Add (ProgID, name, container)
Object 必需的。一个对象表达式,其值是“应用于”列表中的一个对象。
ProgID 必需的。一个标识控件的字符串。大多数控件的 ProgID 都可通过查看对象浏览器来决定。控件的 ProgID
是由控件的库和类组成的。
例如,CommandButton 控件的 ProgID 是 VB.CommandButton。在ProgID
与对象浏览器中所显示的不一样的情况下,Visual Basic
将显示一个包括正确 ProgId 的错误信息。
name 必要的。一个字符串,用来标识集合的成员。
container 可选的。一个对象引用,它指定控件的容器。如果没有指定或为NULL,缺省值为 Controls
集合所属的容器。通过指定该参数,可以把一个控件放置在任何现存的容器控件(如 Frame 控件)中。用户控件或 ActiveX
文档也可以作为一个容器。
举例: //在picture1上面添加一个commandbutton
Private Sub Form_Load()
Form1.Controls.Add "VB.CommandButton", "cmdOk", Picture1
With Form1!cmdOk
.Visible = True
.Width = 500
.Caption = "确认(&Y)"
  重点:当您添加一个未引用的需要许可证的控件到一个现存的(已部署好的)应用程序时,在使用 Add
方法之前您必须也添加这个控件的许可证关键字。
在运行时添加未引用的控件:
  您也可以利用 Add 方法来动态添加一个在工程中没有被引用的控件。(“未引用的”控件是不出现在 Toolbox
中的控件)。为此,您必须也把控件的License 关键字添加到 Licenses
集合中。下面的示例中在添加控件本身之前添加了控件的许可证关键字:
Option Explicit
Private WithEvents extCtl As VBControlExtender
Private Sub Form_Load()
Licenses.Add "prjWeeks.WeeksCtl", "xydsfasfjewfe"
Set extCtl = Form1.Controls.Add("prjWeeks.WeeksCtl", "ctl1")
extCtl.Visible = True ' The control is invisible by default.
  但是,为了编程这样一个未引用控件的事件,您必须使用 WithEvents
关键字声明一个对象变量为VBControlExtender 对象(如上),并且设置该对象变量到Add
方法返回的引用上。然后,利用VBControlExtender 对象的
ObjectEvent事件来编程该控件的事件。下面是一个简单的例子。
Option Explicit
Dim WithEvents objExt As VBControlExtender '声明 Extender 变量
Private Sub LoadControl()
Licenses.Add "Project1.Control1", "xydsfasfjewfe"
Set objExt = Controls.Add("Project1.Control1", "myCtl")
objExt.Visible = True
Private Sub extObj_ObjectEvent(Info As EventInfo)
'使用 Select Case 编程控件的事件。
Select Case Info.Name
Case "Click"
'这里处理 Click 事件。
'现在显示其他的 case
Case Else '未知事件
'这里处理未知事件。
End Select
Note: 不能把一个固有的控件指定给这个 VBControlExtender 变量;
任何这种试图将引起类型不匹配错误。
  但是,您也可以通过使用 WithEvents
关键字声明一个对象变量,并且设置该方法返回的引用为该变量,从而编程一个动态添加控件的事件,如下所示。
Option Explicit
'声明对象变量为 CommandButton 。
Private WithEvents cmdObject As CommandButton
Private Sub Form_Load()
Set cmdObject = Form1.Controls.Add("VB.CommandButton",
cmdObject.Visible = True
cmdObject.Caption = "Dynamic CommandButton"
Private Sub cmdObject_Click()
Print "This is a dynamically added control"
  如果希望添加一个用户控件或任何 ActiveX 控件到您的窗体,必须或者把这个控件添加到“工具箱”,或者把控件的 License
关键字添加到 Licenses集合中。有关详细信息请参阅“增加方法 (Licenses 集合)”。
  注意:如果您添加一个 ActiveX
或用户控件到您的工程,但是没有在窗体中使用它,您也必须不要选定“工程属性”对话框的“生成” 选项卡上的“删除有关未使用的
ActiveX 控件”选项。如果您的应用程序试图添加该控件,那么该 Add 方法将失败,因为必需的信息已经被丢弃。
&&&&&&&&&&&&&&&&&&&&&&&&&
在VB中动态添加可响应消息的控件
在VB编程中,经常要根据不同的情况在运行时向窗口中添加或者删除控件,而各个控件还要
响应各种事件。在一般的情况下是首先在设计时将控件加入到窗口中,在它们的各个事件中写入
代码,然后将它们的Visible属性设置为False。在运行时再使控件显示出来,但是这样既不方便
同时也因为在设计时在窗口中加入太多的控件而使得程序的运行速度变慢。下面我向大家介绍一
种通过编程在运行时动态添加和删除控件的方法
首先建立一个工程文件,然后在Form1中加入以下的代码:
Dim & WithEvents & cmdMyCommand
& As & VB.CommandButton
Option & Explicit
'在下面的定义中,程序定义了一个TextBox控件、一个CommandButton控件
'和一个附加控件。
Dim & WithEvents & ctlDynamic
& As & VBControlExtender
Dim & WithEvents & ctlText
& As & VB.TextBox
Dim & WithEvents & ctlCommand
& As & VB.CommandButton
Dim & WithEvents & ctlCommandDel
& As & VB.CommandButton
Private & Sub &
ctlCommandDel_Click()
Dim & i & As &
'将控件的许可证信息删除
Licenses.Remove & "MSComctlLib.TreeCtrl "
If & MsgBox( "是否删除所有控件 ", &
vbYesNo) & = & vbYes
For & i & = & 1
& To & Form1.Controls.Count
Controls.Remove & 0
Private & Sub &
ctlCommand_Click()
ctlText.Text & = & "你点击的是控制按钮
Private & Sub &
ctlDynamic_ObjectEvent(Info & As
& EventInfo)
'当点击树形控件的某一个条目后,在ctlText中显示条目。
If & Info.Name & =
& "Click " & Then
ctlText.Text & = & "你点击的条目是
ctlDynamic.object.selecteditem.Text
Private & Sub & Form_Load()
Dim & i & As &
' & 将树形控件的许可证信息加入到许可证集合中
' & 如果许可证已经存在,则会返回错误信息732
Licenses.Add & "MSComctlLib.TreeCtrl "
' & 在Form中动态的加入一个树形控件,如果你想树形控件建立到不同的
'容器中,象一个Frame控件或者PictureBox控件,你只要将Controls.Add
'函数的第三个参数改为特定的容器名就可以了
Set & ctlDynamic & =
& Controls.Add( "MSComctlLib.TreeCtrl ",
"myctl ", & Form1)
'设置树形控件的位置和尺寸
ctlDynamic.Move & 1, & 1,
& 2500, & 3500
'在树形控件中加入10个节点
For & i & = & 1
ctlDynamic.object.nodes.Add & Key:= "Test "
& & & Str(i),
Text:= "Test " & &
ctlDynamic.object.nodes.Add & Relative:= "Test "
& & & Str(i),
Relationship:=4, & Text:= "TestChild "
'使树形控件可见
ctlDynamic.Visible & = &
'加入一个TextBox
Set & ctlText & =
& Controls.Add( "VB.TextBox ", &
"ctlText1 ", & Form1)
'设置TextBox的位置和尺寸
ctlText.Move & (ctlDynamic.Left &
+ & ctlDynamic.Width & +
& 50), & _
1, & 2500, & 100
'将textBox的背景色设置为蓝色并将前景色设置为白色
ctlText.BackColor & = &
ctlText.ForeColor & = &
'使TextBox可见
ctlText.Visible & = & True
'加入一个CommandButton
Set & ctlCommand & =
& Controls.Add( "VB.CommandButton ",
"ctlCommand1 ", & Form1)
'设置CommandButton的位置和尺寸
ctlCommand.Move & (ctlDynamic.Left
& + & ctlDynamic.Width
& + & 50), &
ctlText.Height & + & 50,
& 1500, & 500
'设置CommandButton的标题
ctlCommand.Caption & = & "点击
'使CommandButton可见
ctlCommand.Visible & = &
'建立一个删除按钮
Set & ctlCommandDel & =
& Controls.Add( "VB.CommandButton ",
"ctlCommand2 ", & Form1)
ctlCommandDel.Move & (ctlDynamic.Left
& + & ctlDynamic.Width
& + & 50), &
ctlText.Height & + & 650,
& 1500, & 500
ctlCommandDel.Caption & = &
"删除所有控件 "
ctlCommandDel.Visible & = &
运行上面的程序,可以看到程序在窗口中加入了三个VB标准控件:一个TextBox和两个
CommandButton还加入了一个扩展的ActiveX控件:树形控件。这些控件还可以响应消息,
点击树形控件中的项目或者“点击”按钮就可以在文本框中显示相应的内容。点击“删除
所有控件”按钮就可以删除加入的所有控件了。
通过上面的程序可以看到,通过WithEvents可以定义带事件相应的控件,对于标准的VB
控件(例如CommandButton、TextBox等)可以通过VB.XXX来定义,其中XXX是控件的类的名称
,而对于扩展的ActiveX控件,可以通过VBControlExtender来定义,在装载扩展控件以前,
首先要使用Licenses对象加入控件的许可证信息。
上面的程序在VB6,WIN98中文版下运行通过。
&&&&&&&&&&&&&
Dim & WithEvents & ctlCommand
& As & VB.CommandButton
Private & Sub &
Command1_Click()
For & Each & CTL
& In & Me.Controls
& If & CTL.Name
& = & "ctlCommand1 "
& & Controls.Remove
& ctlCommand
& End & If
Private & Sub & Form_Load()
Set & ctlCommand & =
& Controls.Add( "VB.CommandButton ",
& "ctlCommand1 ", & Me)
'设置CommandButton的位置和尺寸
ctlCommand & = & 400
ctlCommand.Left & = & 20
'设置CommandButton的标题
ctlCommand.Caption & = & "点击
'使CommandButton可见
ctlCommand.Visible & = &
&&&&&&&&&&&&&&&&&&
动态创建和删除VB控件
摘要:介绍在Visual
Basic环境中利用动态创建和删除控件的方法,比较了两者异同,阐述了在实际应用中,Active
X控件在程序运行时动态加载和删除的方法。
关键词:Visual
Basic 6.0;控件;控件集合;控件数组;属性;Active X
在使用Visual Basic
进行程序设计的过程中,如果能在运行时刻动态地创建和删除控件,可以极大地丰富界面的处理和变化。本人在设计网络监控系统时,需要在原理图与实物示意图间切换。切换的过程采用本文介绍控件的动态创建和删除来实现,有效地节省了系统资源,同时也有利于简化界面的维护。下面将就Visual
Basic 6.0中的控件在运行时刻的创建和删除的两种方法——控件数组和控件集合作详细的阐述。
2.基于控件数组的动态控件的创建与删除
VB中的控件数组实际上也是一种数组,其中的每个控件具有相同的Name属性,但具有不同的Index属性,在这里Name属性类似于数组的名字,而Index属性类似于数组的下标。同时,控件数组也支持普通VBA数组的LBound
、UBound和Count方法,控件数组中的控件可以共享一个事件过程,便于代码的编写和集中处理,这正是使用控件数组的最大的理由。
但是控件数组与普通的数组并非完全一样,它不需要定义大小,只有这样我们才可以动态的扩展它。
下面给出利用Load命令动态添加控件和Unload命令动态删除控件的一般方法:
(1)首先在窗体上放置一个TextBox,其Name属性设置为Text1,Index属性设置为0,这样我们就创建了一个TextBox控件数组,其中有一个成员。
(2)在窗体上放置一个命令按钮Command1,在其Click事件中添加如下的代码:
Load Text1(1)
Text1(1).left=0
Text1(1).visible=true
(3)在窗体上放置一个命令按钮Command2,在其Click事件中添加如下的代码:
Unload Text1(1)
(4)运行。单击命令按钮Command1,窗体上会出现一个新的文本框;单击命令按钮Command2,窗体上刚出现的新的文本框就被删除。
需要注意的是:Load命令创建的控件Text1(1)与设计时已经放在窗体上的控件Text1(0)有完全相同的属性,也包括大小和位置等属性,例外的就是Index属性不一样,Visible属性默认为False,所以必须在Load方法执行之后,执行调整控件位置的语句,并把其Visible属性设置为True,以便在窗体上可见。Unload命令只能删除动态加载的控件,若删除设计时创建的控件会产生错误。
另外,利用上面提到的数组的一些方法,可以有效的简化代码的编写。以下的代码可以删除所有动态创建的Text1控件数组中的控件:
Text1.Count&1
&&&&Unload
Text1(Text1.Ubound)
需要说明的是,菜单数组是控件数组的一种特殊的形式,只是它是在菜单编辑器中设置相应的Name和Index属性,而且要求一个菜单控件数组中的菜单项必须是同一级菜单,但是不能创建新的顶级菜单。而动态创建和删除菜单项的方法也使用Load和Unload方法,只是默认情况下其Visible属性是True,而且不用重新设置相应的位置。
3.基于控件集合的动态控件的创建与删除
VB中提供一个Controls集合,用以包含当前窗体中的所有的控件,这对于实现一些功能相对复杂的操作相当有好处。而且Controls集合也是集合的一种,它支持一般集合的Count等方法和相应的检索机制。以下两例就是利用这个控件集合的巧妙实现。
要清空当前窗体上的所有的文本框,可以如下实现:
Dim Ctl as Control
For Each Ctl in Controls
Typeof Ctl is Textbox then
&&&&&&&&Ctl.Text=””
也可以利用集合的Count方法如下实现:
To&&Controls.Count-1
Typeof Ctl is TextBox
&&&&&&&&Controls(i).Text=””
当然,控件集合毕竟是一种特殊的集合,下面给出利用Add方法动态添加控件,Remove方法动态删除控件的一般方法:
(1)Controls集合的Add方法
其语法格式为:
Set mycontrol = controld.Add(ProgId,
Name, [Container])
在这里,mycontrol是一个自定义的控件对象,若需要新创建的控件对事件做出反应,还要再定义该对象时增加WithEvents关键字。
ProgId是库名.控件名形式的控件类的名字,ToolBox
中的控件一般具有类似于<mandButton这样的形式。而Active
X控件的形式则有所差别,比如若使用Windowless控件库中的控件一般具有类似于MsWless.WlText的形式。
Name参数是想赋给控件的名字,与控件的Name属性相对应。
Container参数是可选的,它代表欲放置控件的容器,默认情况下是放置在窗体上。
下例是在窗体上动态创建一个命令按钮,然后单击命令按钮时,执行相应的动作:
Dim WithEvents mycontrol As
CommandButton
Private Sub Form_Load()
Set mycontrol =
Controls.Add("VB.commandbutton", "mycontrol")
mycontrol.Left = 0
mycontrol.Caption = "my"
mycontrol.Visible = True
Private Sub
mycontrol_click()
"You click me!", vbExclamation
需要注意,动态创建的控件必须指定相应的属性,而且在默认情况下,其Visible属性是False。
(2)Controls集合的Remove方法
利用Controls集合的Remove方法可以删除用Add方法动态创建的控件。其语法格式为:
Controls.Remove “控件名”
比如以上创建的mycontrol要删除可以使用如下的命令:
&&Controls.Remove
"mycontrol"
同样应该注意,不能删除一个不存在或者在设计时创建的控件。
X控件的动态创建和删除
以上论述的方法适合于控件在应用程序工具箱(TOOLBOX)中的情况,而Active
X控件一般在应用程序运行机器上,但没有在工具箱中,这种情况则需要先进行注册,方法是利用Regsvr32在Windows环境中注册,或者在VB代码中进行注册,方法如下:
Shell(Systempath & “regsvr32.exe
/s /I" & MyControlName,
其中Systempath是Regsvr32.exe所在的路径,
MyControlName是控件名字(包括路径)
若要撤销,可以如下操作:
Shell(Systempath & “regsvr32.exe
/s /U" & MyControlName,
下面讨论注册但是未出现在工具箱(TOOLBOX)中的Active
X控件的情况,这其中也包括VB自带的一些Active
X控件的使用。具体的方法就是利用VBControlExtender对象。VBControlExtender对象与EventInfo相结合能提供事件陷井捕捉,它提供了一套通用的属性、方法、事件给开发人员,它的一个突出特点是能编程设计控件的事件,声明时若使用WithEvents关键字,则会有个特殊的事件ObjectEvent(Info
EventInfo),它能捕捉到对象使用RaiseEvent产生的所有事件,EventInfo数据结构映射了事件的名称、参数个数和参数的值。VBControlExtender和
EventInfo相结合,采用Select Case
就可以预先将不同类对象的事件放置一起,各自独立运作。
下面的例子是使用未在工具箱(TOOLBOX)中出现的RichTextBox的方法,其他的Active
X控件的使用方法与此类似:
Dim WithEvents myControl As
VBControlExtender
Private Sub Form_Load()
Licenses.Add
"RichText.RichTextctrl.1"
Set myControl =
Controls.Add("RichText.RichTextctrl.1", "mycontrol")
myControl.Left = 0
myControl.Visible = True
Private Sub myControl_ObjectEvent(Info
As EventInfo)
Select Case Info.Name
Case "MouseDown"
MsgBox "mousedown"
End Select
需要注意,Licenses.Add
"RichText.RichTextctrl.1"是响应控件的对象编号在VB中的注册,若此控件已经出现在工具箱(TOOLBOX)中,则会出错。
另外,若Active
X控件已经出现在TOOLBOX中,需要动态建立控件,则应该作如下的处理:首先去掉Licenses.Add
"RichText.RichTextctrl.1"这一句,然后,在“工程属性窗口”的“Make”页面下,确保“remove
information about unused ActiveX controls”不被选中即可。
还有,若Active
X控件已经出现在TOOLBOX中,需要动态建立控件,还可以用类似于前面介绍的控件集合的方法,比如上面示范的RichTextBox的例子还可以如下实现(只是这种方法不再支持ObjectEvent事件):
Dim WithEvents myControl As
RichTextLib.RichTextBox
Private Sub Form_Load()
Set myControl =
Controls.Add("RichText.RichTextctrl.1", "mycontrol")
myControl.Left = 0
myControl.Visible = True
Private Sub
myControl_Click()
通过以上对Visual
Basic中的控件动态建立和删除进行了讨论,我们了解到控件数组适合于应用程序中需要该控件,但需要控件实例的具体数量不定的情况;而控件集合则适合于为了完成不同的任务,制作了多个不同功能的控件,在特定条件下只需要一个或几个控件的情况。对于Active
X控件,若没有添加到VB工具箱中,当应用程序执行时,可以根据需要由程序自动加载或者删除。总之,合理地选择使用以上的各种方法,对于提高编程的效率和代码的运行效率都是大有裨益的。
以上有关的代码都已在Windows 2000
Professional 和 Visual Basic 6.0
企业版环境下测试通过。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 ajax动态加载下拉列表 的文章

 

随机推荐