有一个activex控件,我原来是单独做的一个ocx,现在我把它拿到工程内部,现在我在form中用form.controls.add()添加这个对象,结果发现控件的left,top ,width ,height,tabindex这些属性通通不能用了,,我囧
请问大家知道怎么回事吗?

解决方案 »

  1.   

    控件好象不可以用form.controls.add()添加吧.添加方法有错.
      

  2.   

    控件当然可以用me.controls.add方法添加,在一个exe工程中加一个控件是不需要注册ocx的,也不需要引用什么控件对象
      

  3.   

    原来是做成单据ocx并编译的,现在我是内嵌在exe工程里,不过对这样内嵌的控件,我们定义一个控件变量以后不能读取他的left这些属性的,不信你可以试试看
      

  4.   

    dim ctl as control
    set ctl = me.controls.add(...)
    ctl.left = 120
      

  5.   

    我试了,可以的,.left属性是可以自动出现的。你是怎么“内嵌在exe工程里”的?不妨把你的工程资源管理器截图发上来。给你看看我的:这是我的测试代码:Private Sub Form_Load()
        '测试标准控件
        Dim myCmd As CommandButton
        Set myCmd = Me.Controls.Add("vb.commandbutton", "cmd1")
        myCmd.Caption = "vvvddvv"
        myCmd.Visible = True
        Debug.Print myCmd.Name, myCmd.Left
        
        '测试UserControl
        Dim mySl As ShapeLabel
        Set mySl = Me.Controls.Add("ControlDemo.ShapeLabel", "sl3")
        mySl.Caption = "asdfad"
        mySl.Visible = True
        Debug.Print mySl.Name, mySl.Left
    End Sub
      

  6.   

    注意,ActiveX Control的project要和你自己使用UserControl的project要分做两个Project,不能直接把UserControl的类文件加到你自己的工程里。
      

  7.   

    如果像这样做工程,那确实不会有left,top ,width ,height,tabindex这些属性,很奇怪。这时候只有把要添加的对象声明为control,才可以用上述属性,但是同时usercontrol特有的属性却丢失了。Private Sub Form_Load()
        '声明为UserControl类型,编译通不过
        Dim mySl As ShapeLabel
        Set mySl = Me.Controls.Add("ControlDemo.ShapeLabel", "sl3")
        mySl.Caption = "asdfad"
        mySl.Visible = True '以下各句都报编译错:没相应属性
        Debug.Print mySl.Name, mySl.Left
        
        '声明为Control,有extender的各种属性,但是没办法得到用户控件特有的属性
        Dim myCtl As Control
        Set myCtl = Me.Controls.Add("ControlDemo.ShapeLabel", "sl5")
        myCtl.Caption = "asdfad" '运行时错误,说没这个属性。
        myCtl.Visible = True
        Debug.Print myCtl.Left, myCtl.TabIndex, myCtl.Width '这句可以正常运行
    End Sub这是为什么呢?为什么会丢失这些属性?如何在这种模式下能让UserControl属性和Extender属性都正常得到?
      

  8.   

    可以简单理解为控件 ShapeLabel 即“继承”了 Control,又“继承”了类 ShapeLabel。注意两个同名的 ShapeLabel 是不同的,前面指你可以拖动到窗体上的最终实例,后面指你写代码的那个“类”。工程外使用,看到的是控件 ShapeLabel,所以有 Left 属性。
    工程内使用,为避免同名冲突,看到的只有类 ShapeLabel,所以没有 Left 属性。不要用“标准”的继承概念去套用,只是一个近似。
      

  9.   

    那么“如何在这种模式下能让UserControl属性和Extender属性都正常得到?”不然,在这种方式下如何能调试呢?要知道,MSDN里专门有一小节,说ActiveX Control的调试方法可以分为工程内作为私有控件和工程外作为公有控件两种。但是没说细节。前一种就是12楼的用法。
      

  10.   

    关键是在这种模式下用楼主那种controls.add方法添加控件的时候,不能同时得到UserControl属性和Extender属性。12楼代码的注释说明了这种情况。
      

  11.   

    我一般是做成OCX控件,然后使用Regsvr32注册一下,再在工程中引用,即可使用了。
      

  12.   

    slowgrace说出了我的全部问题,,谢谢,
      

  13.   

    可不可以在控件里面做一个public 函数,比如public sub ControlResize在这个里面去和控件的resize连接
    就是
    public sub controlresize
      me.left=30
    end sub
    类似的?
      

  14.   

    按照下面的方法在 UserControl 封装属性。
    Public Property Get Left() As Single
        Left = Extender.Left
    End PropertyPublic Property Let Right(ByVal RHS As Single)
        Extender.Left = RHS
    End Property
      

  15.   


    这是你自己的断言,不然还是微软说的???(不要在论谈里轻易下断言,有时这样很没面子:>)
    见鬼~~~我怎么记得,微软好象说:所有第三方OCX都要先在windows中注册后才能引用.前几日在网上看到过几篇不注册使用ActiveX DLL例子,看了真想哭~~~~~~(好麻烦的~~~~)我就想注册一下也没啥大不了了了了了了了了了~~~~~~~~~~~~~~~
      

  16.   


    是的,我是按照这样的方式实现所有的属性,不过会出现冲突,比如使用screetoclient这样的函数会出现问题,
    看来这个是非得编译一个单独的文件不可了
    不过编译成单独的文件更新起来真的很麻烦,更新组件就是一个超麻烦的事情。。
      

  17.   

    其实声明为 Control 类型变量再访问 Left 属性更具有通用性,完全可用做成通用函数。
      

  18.   


    你说的是7楼的用法么?你看12楼的第二段代码,用control的话,用户控件特有的属性无法访问。
      

  19.   


    sub MoveControl(byval ctl as control, _
                    byval Left as single, byval Top as single, _
                    byval Width as single, byval Height as single)
        ctl.Move Left, Top, Width, Height
    end subprivate sub Form_Load()
        dim ctl as MyControl
        set ctl = Me.Controls.Add(...)
        MoveControl ctl, 120,120, 600, 240
        ctl.属性1 = 1234
        ctl.属性2 = "abcd"
        ...
    end sub
      

  20.   

    比如我的控件叫MyControl,控件有个对外暴露的方法叫AskTigerZhao那在代码里这么写是编译通不过的:sub MoveControl(byval ctl as control, _
                    byval Left as single, byval Top as single, _
                    byval Width as single, byval Height as single)
        ctl.Move Left, Top, Width, Height
    end subprivate sub Form_Load()
        dim ctl as MyControl
        set ctl = Me.Controls.Add("MyOcx.MyControl"...)
        MoveControl ctl, 120,120, 600, 240
        ctl.属性1 = 1234
        ctl.属性2 = "abcd"
        Call ct1.AskTigerZhao()
        ...
    end sub
      

  21.   

    注意错误的位置
    Call ct1.AskTigerZhao()
      

  22.   


    是啊。我是说这里通不过。我和楼主都是没明白,在用Controls.Add方法加用户控件的时候,如何可以同时用extender和用户控件特有的属性方法
      

  23.   


    谢谢。不过,controls.add之后如何能用两个接口同时引用到同一个对象?你能代码示范一下么?
      

  24.   

    dim myCtl as MyControl
    dim ctl as Control
    set myCtl = Me.Controls.Add(...)
    set ctl = myCtl
      

  25.   

    动态增加的控件,其实不是你真正想要的那个控件,其中被包装起来了。
    Left,Width,Top,Height,这些属性不需要自己实现,是由容器对应自动赋予的属性。以下语句区别两者的区别,希望对你有用。dim myCtl As VBControlExtender
    dim ctl as ShapeLabel
    Set m_myCtl = Controls.Add("ControlDemo.ShapeLabel", "sl3")
    set ctl = myCtl.object
    'myCtl具有left等属性,
    '但要访问ShapeLabel的方法,只能通过ctl来访问
      

  26.   

    39楼的代码不行。运行时错误,set myCtl = Me.Controls.Add(...)这一句报“Type mismatch”.
      

  27.   


    谢谢。set ctl = myCtl.object
    这一句同样报运行时错误:Type mismatch
      

  28.   

    另外,40楼代码有个笔误:第3行m_myCtl -》myCtl
      

  29.   

    要反过来转换
    Option ExplicitPrivate Sub Form_Load()
        Dim myCtl As MyControl
        Dim ctl As Control
        
        Set ctl = Me.Controls.Add("Project1.MyControl", "ctl")
        ctl.Move 120, 120
        ctl.Visible = True
        
        Set myCtl = ctl
        myCtl.Caption = "hello"
    End Sub
      

  30.   

    Tiger_Zhao的这个方案是可行的
    我的测试:
    1,新建一个exe工程,添加一个用户控件
    用户控件代码Option Explicit'事件调用
    Public Event Hit()
    Private mblnDead    As BooleanPublic Sub Test()
        MsgBox "小伙子果然有些来头,竟然找到这里来了!看我灭了你!"
        RaiseEvent Hit
    End SubPrivate Sub UserControl_Show()
        '设置上颜色,好区别
        With UserControl
            .BackColor = vbBlue
            .Width = 1200
            .Height = 300
        End With
        
    End Sub
    Public Property Get Dead() As Boolean
        Dead = mblnDeadEnd Property
    '测试属性调用
    Public Property Let Dead(ByVal NewValue As Boolean)
        mblnDead = NewValue
        MsgBox "哎呀,CSDN果然厉害!30年后我还会再回来的~!"
    End Property
    Exe工程中添加按钮
    Option ExplicitPrivate WithEvents mobjTest  As UserControl1
    Private mobjCtl              As ControlPrivate Sub Command1_Click()
        Call mobjTest.Test
    End SubPrivate Sub Form_Load()
        Set mobjCtl = Me.Controls.Add("工程1.usercontrol1", "ctl1")
        mobjCtl.Move 120, 120
        mobjCtl.Visible = True
        Set mobjTest = mobjCtl
    End SubPrivate Sub mobjTest_Hit()
        MsgBox "哼,想杀我,问问我手上的家伙答应不答应吧!"
        mobjTest.Dead = True
    End Sub
    测试完全通过
      

  31.   

    45楼仍然报错:Set myCtl = ctl
    运行时错误:Type mismatch
      

  32.   

    bloom8848,把你46楼测试的时候的工程浏览器截图给我看看,我才信你。
      

  33.   

    我已经上传到这里了,请下载
    http://bloom8848.download.csdn.net/
      

  34.   

    我弄错了,现在我也可以通过了。我原来是这样加控件的:    Set ctl = Me.Controls.Add("ControlDemo.ShapeLabel", "sl3")现在改成这样就可以了:
        Set ctl = Me.Controls.Add("Project1.ShapeLabel", "sl3")工程设置是这样的:
    我原来是创立的ControlDemo.ShapeLabel控件,要把它赋给Project1.ShapeLabel类型的变量,所以报Tyoe Mismatch。可能是这样解释吧?
      

  35.   

    像51楼那样用对Class String之后,40楼的办法也可以通过。39楼的代码还是不行,不过这回是报错在set ctl = myctl.小结:
    (1)controls.add的返回值可以赋给control类型的变量,也可以赋给UserControl类型的变量。
    (2)可以用UserControl类型的变量去引用control类型的变量,反之却不行。为什么?照我直观的理解,应该反过来才对。
      

  36.   

    可以用UserControl类型的变量去引用control类型的变量,反之却不行。为什么?Option ExplicitPrivate Sub Form_Load()
        Dim myCtl As MyControl
        Dim ctl As Control
        
    '*****这个可以
        Set ctl = Me.Controls.Add("Project1.MyControl", "ctl")  
        Set myCtl = ctl'*****这个不可以
        Set myCtl = Me.Controls.Add("Project1.MyControl", "ct2")  
        Set ctl = myCtl '这一句运行时错误:Type mismatch.End Sub
      

  37.   

    因为不是按照通常意义的“继承”实现的,MyControl 是单一接口,Control 是“混合”接口。
      

  38.   

    当我们使用set的时候,实际上是发生了类型转换的吧?