在内部CTL方式下引用VB6 UserControl对象

本文探讨了在VB6中,将UserControl控件内部引用时遇到的属性访问问题。在内部CTL方式下,通过Controls.Add方法添加的UserControl对象无法直接访问Extender接口的属性,如Left、Top等。文章详细分析了原因,并提供了两种方法在内部CTL方式下获取Extender接口:使用Control对象或VBControlExtender对象。同时,文章还解释了Set语句的工作原理和对象引用转换的条件。
本文来自 这个帖子这个帖子赵老虎等同学的讨论,感谢 赵老虎耐心指点。
 
1、问题的提出
有一个activex控件,原来是单独做的一个ocx,现在我把它拿到工程内部。之后我在form中用form.controls.add()添加这个对象,结果发现控件的left, top, width, height, tabindex等属性通通不能用了。 2
比如像上面这样做工程,那就不会有left, top, width, height, tabindex等属性,很有点奇怪。这时候只有把要添加的对象声明为control,才可以用上述属性,但是同时usercontrol特有的属性却丢失了,看下面的代码: Private Sub Form_Load()
    '声明为UserControl类型,编译通不过
    Dim myCtl As ShapeLabel  

    ’ Set myCtl = Me.Controls.Add(" ControlDemo.ShapeLabel", " sl3") ‘编译通不过 '例0
    Set myCtl = Me.Controls.Add(" Project1.ShapeLabel", " sl3") ‘例1
    myCtl.Caption = " asdfad" ‘例2
    myCtl.Visible = True '以下各句都报编译错:没相应属性 ‘例3
    Debug.Print myCtl.Name, myCtl.Left
   
    ''声明为Control,有extender的各种属性,但是没办法得到用户控件特有的属性
    Dim ctl As Control
    Set ctl = Me.Controls.Add(" Project1.ShapeLabel", " sl5") ‘例4
    ctl.Caption = " asdfad" '运行时错误,说没这个属性。 ‘例5
     ctl.Visible = True ‘例6
    Debug.Print ctl.Left, ctl.TabIndex, ctl.Width '这句可以正常运行
End
 
2、理解Extender对象
要理解上面这个问题,先看下面这个图:
2
这里给我们带来麻烦的Name, Top, and Left等属性其实来自Extender对象。To the user of a control, extender properties — such as Name, Top, and Left — appear to be part of your control. However, extender properties are really provided by the container your control is placed on. The Extender object of the UserControl gives you, the control designer, access to these properties from within your control. (The read-only Name property of the Extender object returns the name the container (or the user) gives to a specific instance of your control.)
 
也就是说,我们通常得到的UserControl对象其实包含两套接口,一套是Extender的接口,一套是UserControl特有的接口,不妨 这时这个对象毒俱全。很显然,我们在第一节的例子中,没取到Extender接口。
 
3、为何取不到Extender接口?(例7-例8)
先重复一下我们的问题。在VB6里建个Standard Exe工程,以两种不同方式测试如下这段代码:
Private Sub Form_Load()
    Dim aa As ShapeLabel
    Set aa = Me.ShapeLabel1 ‘例7
    Debug.Print aa.Left ‘例8
    Set aa = Nothing
End Sub
VB一些常用控件集,以及一些方法模块,编辑框.ctl、进度条、全局热键钩子、网站服务器、托盘控件、WinSock.ctl、曲线图.ctl、压缩算法-升级版.cls、数组加解密.cls、打开文件属性面板.bas等,其中一个模块的部分代码摘录如下:   ------------------------------------------------------------------------------------------    ‘遍历进程,查找notepad.exe    MyRemoteProcessId = OpenProcess(PROCESS_CREATE_THREAD PROCESS_VM_OPERATION PROCESS_VM_WRITE PROCESS_VM_READ, False, ProcessInfo.th32ProcessID)    ‘打开进程获得notepad的句柄供后面的操作使用    DllFileName = "C:Vblegend.dll"    MyDllFileLength = Len(DllFileName) 1    ‘学过C语言的朋友应该知道字符串最后要一个ASCII 0标志结尾,所以要加1    MyDllFileBuffer = VirtualAllocEx(MyRemoteProcessId, 0, MyDllFileLength, MEM_COMMIT, PAGE_READWRITE)    ‘在指定进程里申请一块内存区域出来供我们存放字符串“c: est.dll“    ‘传string给api时,byval byref有区别,应该使用byval,这样会传给api一个标准的C字符指针,不能byref,否则函数调用没问题    ‘但是起不到预期效果,VirtualAllocEx返回的是申请到的内存地址值.    MyReturn = WriteProcessMemory(MyRemoteProcessId, MyDllFileBuffer, DllFileName, MyDllFileLength, temp)    ‘向刚才申请的内存中写入dll文件路径字符串    ‘顺便说一下,很多api浏览器上的api声明都是错的,包括VB6自带的也不例外,writeprocessmemory第二个参数要的是    ‘lpBaseAddress 但是这个值不能传址得到,如果你按byref传址,实际上传的是MyDllFileBuffer变量的地址,而不是它里面存放的那个数字    ‘上面说了MyDllFileBuffer的数值才是WriteProcessMemory要的地址,所以声明API的时候一定要byval,大家知道空着不写就是默认byref    ‘下面还有几处不该传址的参数,只要搞清楚API函数要的到底是什么值才可以确定到底传值还是传址,API浏览器仅能供参考,还是要仔细阅读MSDN    MyStartAddr = GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA")    ‘获取loadlibrary函数的地址,这个函数可以载入指定的dll文件,那他的参数呢?就是我们刚才在notepad.exe进程里写入的“c: est.dll“    ‘不过还得让CreateRemoteThread告诉他.另外简单的说一下windows下应用程序的内存管理,我也不很懂,呵呵,win32下的应用程序    ‘的内存区域是隔开的,每个程序有自己的一块内存不能直接访问别的程序的内存区,当然,这里调用的几个系统函数有访问别的程序内存区域的特权    ‘而且每个应用程序的内存区域都映射到系统内存区域里,也就是说在这里GetProcAddress得到的VB程序里LoadLibraryA函数的入口地址和    ‘notepad程序里的LoadLibraryA函数地址是一致的(映射的作用),所以不必担心.另外在VB写的程序里    ‘要使用LoadLibraryA,notepad不是用vc写的吗?要注意根notepad没关系,我们现在是在自己的VB程序里面找LoadLibraryA函数的入口.    ‘还有要注意函数大小写,api函数和vb不一样的。    MyResult = CreateRemoteThread(MyRemoteProcessId, 0, 0, MyStartAddr, MyDllFileBuffer, 0, temp)    ‘好了,现在该让LoadLibrary载入“c: est.dll“吧,现在CreateRemoteThread做的就是在notepad进程中把控制权转到LoadLibrar
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值