声明:
Private WithEvents tmpControl As VBControlExtender加载:Set tmpControl= frmmain.Controls.Add("VB.Text", "tmpControl", Me)    With tmpControl
        .Top = 0
        .Left = 0
        .ZOrder 0
        .Visible = True
    End With事件过程:
Private Sub tmpControl_ObjectEvent(Info As EventInfo)
  
    Select Case Info.Name
        Case "ActionComplete":
            If Info.EventParameters("Change").Value = False Then
            End If 
            frmmain.Controls.Remove "tmpControl"
            Set tmpControl= Nothing
    End Select
    
End Sub

解决方案 »

  1.   

    熟悉VB的朋友对使用ActiveX控件一定不会陌生,众多控件极大地方便了编程,但 
    唯一的缺陷是不能动态加载控件,必须在设计时通过引用,将控件放置在窗体上。 
    VB6.0已能够解决该问题,只是帮助中没有明确说明,并且没有描述到一些关键功能, 
    由于以前的版本中可以动态创建进程外服务:如果对象是外部可创建的,可在 Set 语 
    句中用 New 关键字、CreateObject 或 GetObject 从部件外面将对象引用赋予变量。 
    如果对象是从属对象,则需使用高层对象的方法,在 Set 语句中指定一个对象引用: Dim xlApp1 As Excel.Application 
    Set xlApp1 = New Excel.Application 
    或 
    Dim xlApp As Object '定义存放引用对象的变量。 
    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 '窗体级变量 
    注意:这里声明为Object对象类型 
    Private Sub LoadControl() 
    Set oControl = Controls.Add 
    ("VB.CommandButton", "MyButton") 
    oControl.Left = 10 
    oControl.Top = 10 
    oControl.Visible = True '使控件可见 
    End Sub ---- 这是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 
    End Sub 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 
    End Sub ---- 当然对微软提供的标准控件能采用该方法添加,大家都不会怀疑,但自己开发的 
    控件也能吗?答案是肯定的,我们可以用一个实际的例子进行说明。 三、实例描述 ---- 假设一个本地网络的监控系统,需要在原理图与实物示意图间切换,原理图包括 
    组网结构、传输资源、监控主机等,而实物示意图包括路由器、设备、采集器等,当然 
    两种图的事件要一致,如双击某个设备图形将显示给设备的实时数据等,为了简化维 
    护,将原理图与实物示意图封装成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 Then 
    '首先判断对象是否存在,若存在则卸载 
    Controls.Remove("MapView") 
    '卸载控件,此操作非常重要 
    End If 
    If intType = 0 Then 
    Set oControl = Controls.Add 
    ("CTheory. Theory", "MapView") 
    Else 
    Set oControl = Controls.Add 
    ("CFact.Fact", "MapView") 
    End If oControl.Height = 3500 
    oControl.Width = 6500 
    oControl.Top = 100 
    oControl.Visible = True 
    End Function Private Sub Form_Load() 
    mblnTheory = True 
    End Sub ---- 3、为按钮cmdLoadOcx编写代码 
    Private Sub cmdLoadOCX_Click() 
    If mblnTheory Then 
    Call LoadControl(0) 
    mblnTheory = False 
    cmdLoadOCX.Caption = "实物图" 
    Else 
    Call LoadControl(1) 
    mblnTheory = True 
    cmdLoadOCX.Caption = "原理图" 
    End If 
    End Sub ---- 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 
    End Sub 
    ---- 注意: EventInfo的参数EventParamters集合中是以1开始的,一般来说,微软新 
    的集合一般是以1开始的,而旧的是以0开始的,如RdoErrors.Item(0)。 
    ---- 5、关闭窗口前卸载控件 Private Sub Form_Unload(Cancel As Integer) 
    Controls.Remove("MapView") 
    Set oControl = Nothing 
    End Sub ---- 6、特别注意 
    ---- 通过Controls.Add方法添加的ActiveX控件一定不能在该工程中有该控件的任何引 
    用,否则系统将出错。 四、小结 ---- 通过使用动态加载ActiveX控件使用庞大的应用程序变得很小,将不同的ActiveX 
    控件进行各种组合,使应用程序更加灵活多变,如您的应用系统要处理三十种门禁,而 
    某个具体的用户可能只有一种或两种门禁,根本没必要首先将所有门禁包含到应用中, 
    可将各个门禁独立封装,只安装注册需要的组件,就象Windows的自定义安装一样。
      

  2.   

    holydiablo(鱼头) 说的很有道理!