VB中动态创建控件.docx

上传人:b****8 文档编号:11494618 上传时间:2023-03-02 格式:DOCX 页数:9 大小:18.88KB
下载 相关 举报
VB中动态创建控件.docx_第1页
第1页 / 共9页
VB中动态创建控件.docx_第2页
第2页 / 共9页
VB中动态创建控件.docx_第3页
第3页 / 共9页
VB中动态创建控件.docx_第4页
第4页 / 共9页
VB中动态创建控件.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

VB中动态创建控件.docx

《VB中动态创建控件.docx》由会员分享,可在线阅读,更多相关《VB中动态创建控件.docx(9页珍藏版)》请在冰豆网上搜索。

VB中动态创建控件.docx

VB中动态创建控件

VB中动态创建控件

VB相关技术:

创建数据驱动窗体

所谓数据驱动窗体就是根据所请求的数据的不同生成相应的窗体。

举例来讲,假设你现在有一个数据库,其中有些字段必须根据登录者的身份加以显示,授权级别高的用户可以浏览并修改这些字段的内容;授权级别一般的用户只能浏览这些字段中的数据;授权级别低的用户则不能浏览这些字段中的内容。

要做到这一点就得利用VB动态添加控件的功能。

动态创建控件

无论你想要创建何种类型的数据驱动窗体,你必须知道如何在运行时动态地创建控件。

你可以通过控件数组做到这一点,但VB6的Controls集合所提供的Add方法,功能更强大,灵活性更高。

使用该方法,你不需要在设计时将控件的实例放在窗体上。

实际上,用Add方法你甚至可以创建程序在编译时根本不存在的控件。

这种方法的用法也很简单:

'声明一个窗体级的变量

DimWithEventstxtTotalAsTextBox

SubCreateTextbox()

'创建新的Textbox控件

SettxtTotal=Controls.Add("VB.TextBox","txtTotal")

'将控件移动到你所需要的地方

txtTotal.Move1000,800,1200,300

'创建时,所有的控件都是不可见的

txtTotal.Visible=True

EndSub

请注意Add方法的第二个参数:

分配给控件的名称。

从代码可读性出发,这个名称一般都与变量名相同。

你可以用这个名称从Controls集合中获取相应的控件或移除该控件。

例如:

Controls.Remove"txtTotal"

在变量声明时加上WithEvents关键字,即使在设计时窗体不存在该控件,你也可以为该控件的事件编写代码。

上面所讲的方法只适合解决VB内置的控件。

例如,当你要添加一个TreeView控件时,VB会要求你证明你已经得到了合法的授权来创建该控件的实例。

换句话说,VB要证明这个控件是买来的,而不是从其它附有该控件的程序中借来的。

要证明你经过了合法的授权有下面几种方法:

在窗体上放置一个控件。

这也是最简单的方法。

你完全没有必要将这个窗体显示出来。

将相关的控件添加到工具箱中,然后在“工程属性”对话框的“生成”标签页中取消选择“删除有关未使用的ActiveX控件的信息”这一项。

向Licenses集合添加一个元素。

例如:

Debug.PrintLicenses.Add("MSMask.MaskedEdBox")

仅仅创建了控件并不足够

要创建一个数据驱动窗体,仅仅知道动态创建控件还不够。

例如:

现在你要创建一个能根据数据库中表的不同字段自动生成控件的窗体。

该窗体可能会创建单行文本框,其长度随字段长度不同而不同;也可能会创建单选按钮或复选按钮以显示布尔型字段;甚至可能创建一个多行文本框显示备注型字段。

你需要解决的第一个问题是:

文本框控件的Multiline属性在运行时是只读的,只在设计时可用。

幸好,微软的MicrosoftWindowlessControls6.0可以解决这个问题。

这组控件集包括了轻量级的TextBox,ComboBox,ListBox,CheckBox,OptionButton,CommandButton和两个scrollbar控件。

这些控件与VB内置的相应的控件最大的区别在于:

这些控件的所有属性在运行时是可读写的。

在VB的安装光盘中的Common\Tools\VB\WinLess文件夹中可以找到这个控件组。

用下面的代码可以创建一个多行文本框:

DimWithEventstxtEditorAsMSWLess.WLText

PrivateSubCreateEditor()

SettxtEditor=Controls.Add("MSWLess.WLText","txtEditor")

txtEditor.Move0,0,4000,4000

txtEditor.MultiLine=True

txtEditor.ScrollBars=wlBoth

txtEditor.Visible=True

EndSub

另外一个问题比较复杂:

在事先不知道要创建多少个控件的情况下,如何给每个对新创建的控件的引用分配唯一的带WithEvents关键字的变量。

换句话说就是要对新创建的控件的事件进行编程,前提是你在设计时不知道程序会创建多少个控件。

使用对象数组显然不行,因为不能用WithEvents关键字声明一个对象数组;更坏的情况是,资一个变量定义为AsControl或AsObject也不行,因为还是不能用WithEvents。

问题源自于我们无法在运行时捕获一个对象数组事件。

所以我们只能采取曲线救国的办法。

所要的编写的代码可能比你想象的多,不过这个解决方法很有趣,值得我们这样去做。

我们需要两个辅助类模块来捕获事件,分别取名为ControlItems和ControlItem。

ControlItems是一个集合类,其中保存了ControlItem对象及其数量。

该数量等于你所要对之编程的控件的数量。

ControlItem类的每一份实例捕获控件产生的事件,然后调用在其所属的ControlItems集合类中的过程,最后由ControlItems在窗体中触发事件并执行事件中的代码。

整个过程如下图所示:

捕获多个控件的事件

为简单起见,假设你要捕获来自所有的动态添加到窗体上去的控件的Validate事件。

为完成这个工作,ControlItems集合类必须向父窗体展示该事件,并随时准备接收来自其子ControlItem类的通知以触发事件。

代码如下:

EventValidate(CtrlItemAsControlItem,CancelAsBoolean)

Privatem_ControlItemsAsNewCollection

'向集合中添加一个新的ControlItem项目

FunctionAdd(ctrlAsControl)AsControlItem

DimnewItemAsNewControlItem

newItem.Initctrl,Me

'添加到私有类

m_ControlItems.AddnewItem

'返回新项目给调用者

SetAdd=newItem

EndFunction

FriendSubNotify_Validate(ItemAsControlItem,CancelAsBoolean)

RaiseEventValidate(Item,Cancel)

EndSub

ControlItem类必须捕获来自动态添加到窗体中的控件的事件,并通知其所属的ControlItems集合类。

很显然,ControlItem类必须有一个用WithEvents关键字定义的变量来引用真正的控件。

这意味着你不能将变量声明为AsControl或AsObject。

如果你决定在窗体中所动态添加的控件不使用VB内置的控件的话,这个问题的解决办法相当的简单。

你只需要将变量声明为VBControlExtender类型就行了。

对于创建数据驱动窗体来讲,不使用VB内置的控件并不是一件大不了的事。

将变量声明为VBControlExtender,并加上WithEvents关键字,你就能直接捕获Validate,GotFocus,LostFocus,DragDrop和DragOver这几个事件了。

如果要捕获其它更多的事件,你可以使用ObjectEvent。

下面是ControlItem类模块中的代码:

PublicWithEventsCtrlAsVBControlExtender

'所属的ControlItems对象

Dimm_ParentAsControlItems

SubInit(ctlAsObject,parntAsControlItems)

SetCtrl=ctl

Setm_Parent=parnt

EndSub

PrivateSubCtrl_Validate(CancelAsBoolean)

'通知所属的ControlItems类

m_Parent.Notify_ValidateMe,Cancel

EndSub

将下面的代码放入窗体中,就可以捕获动态添加的控件所产生的事件了:

DimWithEventsCtrlItemsAsNewControlItems

PrivateSubcmdCreateControls_Click()

DimctrlAsControl

'创建两个文本框并将它们添加到ControlItems集合?

Setctrl=Controls.Add("MSWLess.WLText","One")

ctrl.Move100,200,1000,300

ctrl.Visible=True

CtrlItems.Addctrl

'注意你可以使用同一个变量

Setctrl=Controls.Add("MSWLess.WLText","Two")

ctrl.Move100,800,1000,300

ctrl.Visible=True

CtrlItems.Addctrl

EndSub

PrivateSubCtrlItems_Validate(CtrlItemAsControlItem,CancelAsBoolean)

'拒绝空字符串-注意如何引用控件的属?

IfCtrlItem.Ctrl.Text=""

ThenCancel=True

EndSub

现在解决了最困难的部分,要创建一个数据驱动窗体就变得简单了

**************************************************************

****************************************************************

动态添加控件

VB6有一个新功能,可以动态添加控件,不用控件数组:

object.Add(ProgID,name,container)

参数说明

Object必需的。

一个对象表达式,其值是“应用于”列表中的一个对象。

ProgID必需的。

一个标识控件的字符串。

大多数控件的ProgID都可通过查看对象浏览器来决定。

控件的ProgID是由控件的库和类组成的。

例如,CommandButton控件的ProgID是VB.CommandButton。

在ProgID与对象浏览器中所显示的不一样的情况下,VisualBasic

将显示一个包括正确ProgId的错误信息。

name必要的。

一个字符串,用来标识集合的成员。

container可选的。

一个对象引用,它指定控件的容器。

如果没有指定或为NULL,缺省值为Controls集合所属的容器。

通过指定该参数,可以把一个控件放置在任何现存的容器控件(如Frame控件)中。

用户控件或ActiveX文档也可以作为一个容器。

 

举例:

//在picture1上面添加一个commandbutton

PrivateSubForm_Load()

Form1.Controls.Add"VB.CommandButton","cmdOk",Picture1

WithForm1!

cmdOk

.Visible=True

.Width=500

.Caption="确认(&Y)"

EndWith

EndSub

  重点:

当您添加一个未引用的需要许可证的控件到一个现存的(已部署好的)应用程序时,在使用Add方法之前您必须也添加这个控件的许可证关键字。

在运行时添加未引用的控件:

  您也可以利用Add方法来动态添加一个在工程中没有被引用的控件。

(“未引用的”控件是不出现在Toolbox中的控件)。

为此,您必须也把控件的License关键字添加到Licenses集合中。

下面的示例中在添加控件本身之前添加了控件的许可证关键字:

OptionExplicit

PrivateWithEventsextCtlAsVBControlExtender

PrivateSubForm_Load()

Licenses.Add"prjWeeks.WeeksCtl","xydsfasfjewfe"

SetextCtl=Form1.Controls.Add("prjWeeks.WeeksCtl","ctl1")

extCtl.Visible=True'Thecontrolisinvisiblebydefault.

EndSub

  但是,为了编程这样一个未引用控件的事件,您必须使用WithEvents关键字声明一个对象变量为VBControlExtender对象(如上),并且设置该对象变量到Add方法返回的引用上。

然后,利用VBControlExtender对象的ObjectEvent事件来编程该控件的事件。

下面是一个简单的例子。

OptionExplicit

DimWithEventsobjExtAsVBControlExtender'声明Extender变量

PrivateSubLoadControl()

Licenses.Add"Project1.Control1","xydsfasfjewfe"

SetobjExt=Controls.Add("Project1.Control1","myCtl")

objExt.Visible=True

EndSub

PrivateSubextObj_ObjectEvent(InfoAsEventInfo)

'使用SelectCase编程控件的事件。

SelectCaseInfo.Name

Case"Click"

'这里处理Click事件。

'现在显示其他的case

CaseElse'未知事件

'这里处理未知事件。

EndSelect

EndSub

Note:

不能把一个固有的控件指定给这个VBControlExtender变量;任何这种试图将引起类型不匹配错误。

  但是,您也可以通过使用WithEvents关键字声明一个对象变量,并且设置该方法返回的引用为该变量,从而编程一个动态添加控件的事件,如下所示。

OptionExplicit

'声明对象变量为CommandButton。

PrivateWithEventscmdObjectAsCommandButton

PrivateSubForm_Load()

SetcmdObject=Form1.Controls.Add("VB.CommandButton","cmdOne")

cmdObject.Visible=True

cmdObject.Caption="DynamicCommandButton"

EndSub

PrivateSubcmdObject_Click()

Print"Thisisadynamicallyaddedcontrol"

EndSub

  如果希望添加一个用户控件或任何ActiveX控件到您的窗体,必须或者把这个控件添加到“工具箱”,或者把控件的License关键字添加到Licenses集合中。

有关详细信息请参阅“增加方法(Licenses集合)”。

  注意:

如果您添加一个ActiveX或用户控件到您的工程,但是没有在窗体中使用它,您也必须不要选定“工程属性”对话框的“生成”选项卡上的“删除有关未使用的ActiveX控件”选项。

如果您的应用程序试图添加该控件,那么该Add方法将失败,因为必需的信息已经被丢弃。

问题一:

可先手工画一个按钮作为母控件,把它的Index设置为0

代码如下:

DimiAsInteger

Fori=1To5

LoadCommand1(i)

Command1(i).Top=Command1(i-1).Top

Command1(i).Left=command1(i-1).Left+command1(i-1).Width

command1(i).Visible=True

Next

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 高考

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1