一、新建一个ActiveX DLL工程,名字:全局函数测试;
添加一个类模块,名字cls全局,它的Instancing设置为GloabalMultiUse, 代码:
Public Ages as long
Public sub InitClass(byval paraAges as long)
Ages=paraAges
End sub
Public Function ReadAges() As Long
ReadAges= Ages
End Function
编译工程为: 全局函数测试.DLL
二、 再建一个Active Dll 工程,名字 : 业务对象测试,工程引用 全局函数测试.DLL;
添加一个类模块,名字 cls业务,instancing设置为MultiUse,代码:
Public Function TellMyAges() As Long
TellMyAges= ReadAges()
End Function
编译工程为: 业务对象测试.DLL
三、新建一个exe工程,名字 :测试,启动设置为form1,工程引用 全局函数测试.DLL文件和全局函数测试.DLL;
添加一个form1,再窗口里面添加两个按钮 Command1和Command2,form1代码如下:
Private Sub Form_Load()
InitClass 28
End sub
Private Sub Command1_Click()
Msgbox "直接访问,我的年龄是:" & ReadAges()
End Sub
Private Sub Command2_Click()
dim tmp业务对象 as object
Set tmp业务对象= New cls业务
Msgbox "通过外部Dll访问,我的年龄是:" & tmp业务对象.TellMyAges()
End Sub
编译,运行,按钮1运行的结果为28,而按钮2运行的结果为0,
请问结果为什么不是预期的都是28?要怎么修改才能达到预期的28?
37 个解决方案
#1
我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
对于数值类型的变量,在VB6中自然就是0。
你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。
对于数值类型的变量,在VB6中自然就是0。
你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。
#2
两者在运行时是在同一进程中的,业务对象已经new过了,也没有数据需要初始化的,初始化在自定义全局函数 InitClass中
#3
我认为,虽然是“在同一进程中”,但是:
在Form_Load( )调用 InitClass时,会创建一个“全局函数测试”对象;
在“业务对象测试”中,它肯定New了另一个“全局函数测试”对象。
#4
类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了
#5
类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了
globalmultiuse的类,不显式执行new,会执行Class_Initialize()?
#6
我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
对于数值类型的变量,在VB6中自然就是0。
你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。
两者在运行时是在同一进程中的,业务对象已经new过了,也没有数据需要初始化的,初始化在自定义全局函数 InitClass中
我认为,虽然是“在同一进程中”,但是:
在Form_Load( )调用 InitClass时,会创建一个“全局函数测试”对象;
在“业务对象测试”中,它肯定New了另一个“全局函数测试”对象。
它执行globalmultiuse的Class_Initialize()不?
#7
楼上两位大神,按照上面的例子,如果要两个按钮都输出28,只修改 全局函数测试.vbp文件的话,该怎么修改?
#8
肯定会执行啊。
只是你没有“实现”,它会创建一个“空操作”的接口。
说到这个,如果你实现了“cls全局”的 Class_Initialize(),并在它里面对 Ages赋一个非0的初值(比如15),
然后,你在 Command2_Click() 中看到的返回值,应该就是你给它赋的“初值”了。
只是你没有“实现”,它会创建一个“空操作”的接口。
说到这个,如果你实现了“cls全局”的 Class_Initialize(),并在它里面对 Ages赋一个非0的初值(比如15),
然后,你在 Command2_Click() 中看到的返回值,应该就是你给它赋的“初值”了。
#9
楼上两位大神,按照上面的例子,如果要两个按钮都输出28,只修改 全局函数测试.vbp文件的话,该怎么修改?
在VB6中,我还真不知道如何处理。
因为所有类的“构造函数”,VB6并没有“交给我们”来控制。
如果象C++那种,应该就很容易了。
另外还有一种方法,不知道对你是否适用:
参考我这个帖子:https://bbs.csdn.net/topics/392318790
用“自己创建对象”的方法(类对象不能New、只能通过自己的“创建对象的接口函数”来创建)。
这样,在调用“创建接口”时,如果没有创建,则创建一个; 如果已经创建,则返回已创建的“公共对象”的引用。
#10
刚才做了个试验,通过“对象创建时间”,可以明确的判断出:
你的EXE工程中,在Command1_Click() 和Command2_Click() 中使用的“cls全局”实例是独立的两个!
你的EXE工程中,在Command1_Click() 和Command2_Click() 中使用的“cls全局”实例是独立的两个!
' 第1个 ActiveX Dll 中增加1个成员变量和两个函数/过程
Private strTime As String
Public Function GetCreateTime() As String
GetCreateTime = strTime
End Function
Private Sub Class_Initialize()
strTime = Time$ ' 类对象初始化
End Sub
' 第2个 ActiveX Dll 中增加1个接口函数
Public Function GetObjTime() As String
GetObjTime = GetCreateTime()
End Function
' EXE工程中的修改:
Private Sub Command1_Click()
MsgBox "直接访问,我的年龄是:" & ReadAges()
' 增加下面这句,可以看到“时间”是 “启动程序”的时间
MsgBox "直接访问,对象创建时间:" & GetCreateTime()
End Sub
Private Sub Command2_Click()
Dim tmp业务对象 As Object
Set tmp业务对象 = New cls业务
MsgBox "通过外部Dll访问,我的年龄是:" & tmp业务对象.TellMyAges()
' 增加下面这句,可以看到“时间”是 “点击Command2”的时间
MsgBox "外部Dll访问,对象创建时间:" & tmp业务对象.GetObjTime()
End Sub
#11
类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了
globalmultiuse的类,不显式执行new,会执行Class_Initialize()?
VB里Class_Initialize 就是类的构造函数。
#12
楼上两位大神,按照上面的例子,如果要两个按钮都输出28,只修改 全局函数测试.vbp文件的话,该怎么修改?
这里涉及到一个问题,VB类的构造函数是不能带参数的,所以说 光一个new 或者 CreateObject 是没有办法把初始值传给这个类实例的,除非有个第三方数据源,使用某种约定的方式访问数据。
#13
看讨论得那么热闹,按照楼主的步骤一步一步建立了工程和工程组。
运行的结果是
两个按钮出来的都是28!!!!
运行环境:win10
运行的结果是
两个按钮出来的都是28!!!!
运行环境:win10
#14
看讨论得那么热闹,按照楼主的步骤一步一步建立了工程和工程组。
运行的结果是
两个按钮出来的都是28!!!!
运行环境:win10
我也win10 照做了,一个28,一个0
#15
Win10中,能“正常”???
我是在WinXP的虚拟机中试的,但我觉得这个“运行机制”应该跟Win版本无关吧。
(编译ActiveX DLL会“注册”一些垃圾信息,我没在真机上试。反正安装的虚拟机都是用来做测试的,无所谓了。)
有空我也得在Win10中试试。
另外,我觉得VB6的 Class_Initialize 应该不能算是“类构造函数”,
我觉得它的实质就是: VB6通知你,你的“对象”已经按默认规则构建好了,你还想做点什么修改吗?
我是在WinXP的虚拟机中试的,但我觉得这个“运行机制”应该跟Win版本无关吧。
(编译ActiveX DLL会“注册”一些垃圾信息,我没在真机上试。反正安装的虚拟机都是用来做测试的,无所谓了。)
有空我也得在Win10中试试。
另外,我觉得VB6的 Class_Initialize 应该不能算是“类构造函数”,
我觉得它的实质就是: VB6通知你,你的“对象”已经按默认规则构建好了,你还想做点什么修改吗?
#16
怀疑你引用的是之前编译的旧版本DLL。
仔细看看你各个工程的设置,按顺序进行以下操作看能否解决你的问题。
1、检查全局函数测试 的工程属性里“部件”tab页是否设置了 版本兼容。点选二进制兼容,然后兼容目标指向你编译的DLL
2、业务对象测工程试引用 指向 全局函数测试编译出的DLL
3、业务对象测试工程属性与步骤1一样设置对自身编译结果的二进制兼容
4、EXE工程引用指向两个编译的DLL结果。
然后重新编译两个DLL
仔细看看你各个工程的设置,按顺序进行以下操作看能否解决你的问题。
1、检查全局函数测试 的工程属性里“部件”tab页是否设置了 版本兼容。点选二进制兼容,然后兼容目标指向你编译的DLL
2、业务对象测工程试引用 指向 全局函数测试编译出的DLL
3、业务对象测试工程属性与步骤1一样设置对自身编译结果的二进制兼容
4、EXE工程引用指向两个编译的DLL结果。
然后重新编译两个DLL
#17
在64位Windows下:
64位exe和dll在目录c:\windows\sys tem32目录下;
32位exe和dll在目录c:\windows\sys wow64目录下;
所以要注意:
在win64位系统下注册32位ocx或dll需要将32位ocx或dll拷贝到c:\windows\syswow64\目录下。
且注册要用c:\windows\syswow64\regsvr32 xxxxxxx.ocx或dll
64 位 Windows 平台注意点之文件系统重定向 http://www.cnblogs.com/jiake/p/4981555.html
64 位 Windows 平台注意点之注册表重定向 http://www.cnblogs.com/jiake/p/4956218.html
64位exe和dll在目录c:\windows\sys tem32目录下;
32位exe和dll在目录c:\windows\sys wow64目录下;
所以要注意:
在win64位系统下注册32位ocx或dll需要将32位ocx或dll拷贝到c:\windows\syswow64\目录下。
且注册要用c:\windows\syswow64\regsvr32 xxxxxxx.ocx或dll
64 位 Windows 平台注意点之文件系统重定向 http://www.cnblogs.com/jiake/p/4981555.html
64 位 Windows 平台注意点之注册表重定向 http://www.cnblogs.com/jiake/p/4956218.html
#18
对全局工程稍作改造
Public Ages As Long
Public strTime As String
Public Sub InitClass(ByVal paraAges As Long)
Ages = paraAges
strTime = Now() '保存创建时间,用以区分实例
MsgBox strTime & Str(Ages)
End Sub
Public Function ReadAges() As Long
ReadAges = Ages
MsgBox strTime '每次调用的时候显示本实例创建时间。
End Function
然后在form_load那加一个断点。
启动后,进入断点,但并没有弹窗,说明并不在整个进程启动的时候就加载这个全局对象。继续往下一步,对全局公共变量进行了赋值,这时候发生了弹窗,说明对象被加载了。弹窗出来的内容可以看出,公共变量已经被赋值了,再进入initialize的。所以并不是4楼所说的原因。
记下弹窗显示的时间。
此后点击两个按钮都会发生弹窗。弹窗显示的都是同一个时间。也就是说两个按钮调用的都是同一个实例,并不是10楼所说的原因
#19
在64位Windows下:
64位exe和dll在目录c:\windows\sys tem32目录下;
32位exe和dll在目录c:\windows\sys wow64目录下;
所以要注意:
在win64位系统下注册32位ocx或dll需要将32位ocx或dll拷贝到c:\windows\syswow64\目录下。
且注册要用c:\windows\syswow64\regsvr32 xxxxxxx.ocx或dll
64 位 Windows 平台注意点之文件系统重定向 http://www.cnblogs.com/jiake/p/4981555.html
64 位 Windows 平台注意点之注册表重定向 http://www.cnblogs.com/jiake/p/4956218.html
所有的一切都不涉及外部组件的调用,关你这个32位64位啥事啊,就算要灌水,好歹也仔细看看楼主的诉求以及前面的讨论。啥都不看,直接随机粘贴你的文本,起码的尊重都没有
#20
对全局工程稍作改造
Public Ages As Long
Public strTime As String
Public Sub InitClass(ByVal paraAges As Long)
Ages = paraAges
strTime = Now() '保存创建时间,用以区分实例
MsgBox strTime & Str(Ages)
End Sub
Public Function ReadAges() As Long
ReadAges = Ages
MsgBox strTime '每次调用的时候显示本实例创建时间。
End Function
然后在form_load那加一个断点。
启动后,进入断点,但并没有弹窗,说明并不在整个进程启动的时候就加载这个全局对象。继续往下一步,对全局公共变量进行了赋值,这时候发生了弹窗,说明对象被加载了。弹窗出来的内容可以看出,公共变量已经被赋值了,再进入initialize的。所以并不是4楼所说的原因。
记下弹窗显示的时间。
此后点击两个按钮都会发生弹窗。弹窗显示的都是同一个时间。也就是说两个按钮调用的都是同一个实例,并不是10楼所说的原因
就以你这“改造”后的代码,连 Class_Initialize( )过程都没有,
真无法明白:你“对全局公共变量进行了赋值”(哪个变量?是Ages,还是strTime?)的时候,如何能引起“弹窗”的?
#21
难道“大雪糕”的Windows系统是定制的?
对象管理机制,跟我们用的系统都不一样…………
对象管理机制,跟我们用的系统都不一样…………
#22
对全局工程稍作改造
Public Ages As Long
Public strTime As String
Public Sub InitClass(ByVal paraAges As Long)
Ages = paraAges
strTime = Now() '保存创建时间,用以区分实例
MsgBox strTime & Str(Ages)
End Sub
Public Function ReadAges() As Long
ReadAges = Ages
MsgBox strTime '每次调用的时候显示本实例创建时间。
End Function
然后在form_load那加一个断点。
启动后,进入断点,但并没有弹窗,说明并不在整个进程启动的时候就加载这个全局对象。继续往下一步,对全局公共变量进行了赋值,这时候发生了弹窗,说明对象被加载了。弹窗出来的内容可以看出,公共变量已经被赋值了,再进入initialize的。所以并不是4楼所说的原因。
记下弹窗显示的时间。
此后点击两个按钮都会发生弹窗。弹窗显示的都是同一个时间。也就是说两个按钮调用的都是同一个实例,并不是10楼所说的原因
就以你这“改造”后的代码,连 Class_Initialize( )过程都没有,
真无法明白:你“对全局公共变量进行了赋值”(哪个变量?是Ages,还是strTime?)的时候,如何能引起“弹窗”的?
我所说的“对全局公共变量进行了赋值” 是说form里面的那行 ,好吧我看错了,不是对变量赋值,是直接调用initialize 。
嗯,丢人了。
不过我这的确是两个28。但至少能说明两个按钮调用的是同一个实例吧
Microsoft Windows [版本 10.0.16299.192]
#23
. . . . . . .
. . . . . . . . . .
不过我这的确是两个28。但至少能说明两个按钮调用的是同一个实例吧
Microsoft Windows [版本 10.0.16299.192]
我在WinXP虚拟机中试的,两个时间是不一样的(如我在10代码中的注释)。
并且“Command2_Click()”的是动态时间:什么时候点的按钮、就是什么时间。
Command1_Click()则不会变,始终是程序启动的那个时间。
从我的测试结果来看,它们就是两个不相关的对象。
14楼“笨狗先飞”也说了,他的是Win10系统,照样是一个28、一个0。
并且,我们的“试验环境”,根本不存在你在16楼说的那种“版本冲突”问题,因为都是“全新的”。
#24
在Win10系统中,运行WinXP上的老代码、老模块出莫名其妙的兼容性问题很正常。个人意见。
#25
也许楼主要做的只是在资源管理器中要运行的exe文件上点鼠标右键、兼容性、设置以Windows XP (SP 3或4)兼容模式运行,以管理员身份运行。
#26
工程组运行的时候是两个28,
按楼主说的,编译引用后就是28,0
按楼主说的,编译引用后就是28,0
#27
嗯,我运行的时候,两个DLL都是编译好的。
VB6中只有一个EXE工程。
不懂就不要瞎说…………
VB6中只有一个EXE工程。
在Win10系统中,运行WinXP上的老代码、老模块出莫名其妙的兼容性问题很正常。个人意见。
不懂就不要瞎说…………
#28
我觉得,在IDE里的时候,两个DLL,其实各创建了一个实例
但是在EXE运行的时候
EXE中创建了一个 cls全局实例,和一个cls业务
但在创建cls业务的时候在 业务对象测试.dll 中有一个cls全局实例
28其实存在于这个实例中,但是EXE访问不到,他访问到的那个cls全局实例 并不是dll里那个。
但是在EXE运行的时候
EXE中创建了一个 cls全局实例,和一个cls业务
但在创建cls业务的时候在 业务对象测试.dll 中有一个cls全局实例
28其实存在于这个实例中,但是EXE访问不到,他访问到的那个cls全局实例 并不是dll里那个。
#29
大概就这么个意思吧
#30
“28”是在EXE的全局实例中,不是在“业务”创建的“全局”实例中。
#31
估计要对 业务对象测试.vbp来改造才行
#32
#33
我觉得,如果要“共享”唯一的全局对象,但VB6又无法“阻止乱New全局类对象”,那么应该改变“管理方式”:
应该由 EXE启动时,New一个“全局”对象;
其它的“业务对象”不能再自己去New,而应该提供一个“获取对象”的接口函数(过程);
在EXE启动后,创建其它“业务对象”时,调用其接口,把“全局”对象传递给它(当然是“对象引用”)。
在“业务对象”中,都是通过这个“获得的对象引用”来操作“全局对象”。
应该由 EXE启动时,New一个“全局”对象;
其它的“业务对象”不能再自己去New,而应该提供一个“获取对象”的接口函数(过程);
在EXE启动后,创建其它“业务对象”时,调用其接口,把“全局”对象传递给它(当然是“对象引用”)。
在“业务对象”中,都是通过这个“获得的对象引用”来操作“全局对象”。
#34
把全局对象挪到SQL数据库中。
#35
把全局对象挪到SQL数据库中。
怎么不说“把数据写到文本文件中”了…………
#36
为了描述我的问题,我写成了测试代码,并运行过:
一、新建一个ActiveX DLL工程,名字:全局函数测试;
添加一个类模块,名字cls全局,它的Instancing设置为GloabalMultiUse, 代码:
。。。。
把它的Instancing设置为 PublicNotCreate
#37
为了描述我的问题,我写成了测试代码,并运行过:
一、新建一个ActiveX DLL工程,名字:全局函数测试;
添加一个类模块,名字cls全局,它的Instancing设置为GloabalMultiUse, 代码:
。。。。
把它的Instancing设置为 PublicNotCreate
一改编译不出来了
#1
我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
对于数值类型的变量,在VB6中自然就是0。
你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。
对于数值类型的变量,在VB6中自然就是0。
你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。
#2
我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
对于数值类型的变量,在VB6中自然就是0。
你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。
两者在运行时是在同一进程中的,业务对象已经new过了,也没有数据需要初始化的,初始化在自定义全局函数 InitClass中
#3
我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
对于数值类型的变量,在VB6中自然就是0。
你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。
两者在运行时是在同一进程中的,业务对象已经new过了,也没有数据需要初始化的,初始化在自定义全局函数 InitClass中
我认为,虽然是“在同一进程中”,但是:
在Form_Load( )调用 InitClass时,会创建一个“全局函数测试”对象;
在“业务对象测试”中,它肯定New了另一个“全局函数测试”对象。
#4
类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了
#5
类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了
globalmultiuse的类,不显式执行new,会执行Class_Initialize()?
#6
我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
对于数值类型的变量,在VB6中自然就是0。
你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。
两者在运行时是在同一进程中的,业务对象已经new过了,也没有数据需要初始化的,初始化在自定义全局函数 InitClass中
我认为,虽然是“在同一进程中”,但是:
在Form_Load( )调用 InitClass时,会创建一个“全局函数测试”对象;
在“业务对象测试”中,它肯定New了另一个“全局函数测试”对象。
它执行globalmultiuse的Class_Initialize()不?
#7
楼上两位大神,按照上面的例子,如果要两个按钮都输出28,只修改 全局函数测试.vbp文件的话,该怎么修改?
#8
肯定会执行啊。
只是你没有“实现”,它会创建一个“空操作”的接口。
说到这个,如果你实现了“cls全局”的 Class_Initialize(),并在它里面对 Ages赋一个非0的初值(比如15),
然后,你在 Command2_Click() 中看到的返回值,应该就是你给它赋的“初值”了。
只是你没有“实现”,它会创建一个“空操作”的接口。
说到这个,如果你实现了“cls全局”的 Class_Initialize(),并在它里面对 Ages赋一个非0的初值(比如15),
然后,你在 Command2_Click() 中看到的返回值,应该就是你给它赋的“初值”了。
#9
楼上两位大神,按照上面的例子,如果要两个按钮都输出28,只修改 全局函数测试.vbp文件的话,该怎么修改?
在VB6中,我还真不知道如何处理。
因为所有类的“构造函数”,VB6并没有“交给我们”来控制。
如果象C++那种,应该就很容易了。
另外还有一种方法,不知道对你是否适用:
参考我这个帖子:https://bbs.csdn.net/topics/392318790
用“自己创建对象”的方法(类对象不能New、只能通过自己的“创建对象的接口函数”来创建)。
这样,在调用“创建接口”时,如果没有创建,则创建一个; 如果已经创建,则返回已创建的“公共对象”的引用。
#10
刚才做了个试验,通过“对象创建时间”,可以明确的判断出:
你的EXE工程中,在Command1_Click() 和Command2_Click() 中使用的“cls全局”实例是独立的两个!
你的EXE工程中,在Command1_Click() 和Command2_Click() 中使用的“cls全局”实例是独立的两个!
' 第1个 ActiveX Dll 中增加1个成员变量和两个函数/过程
Private strTime As String
Public Function GetCreateTime() As String
GetCreateTime = strTime
End Function
Private Sub Class_Initialize()
strTime = Time$ ' 类对象初始化
End Sub
' 第2个 ActiveX Dll 中增加1个接口函数
Public Function GetObjTime() As String
GetObjTime = GetCreateTime()
End Function
' EXE工程中的修改:
Private Sub Command1_Click()
MsgBox "直接访问,我的年龄是:" & ReadAges()
' 增加下面这句,可以看到“时间”是 “启动程序”的时间
MsgBox "直接访问,对象创建时间:" & GetCreateTime()
End Sub
Private Sub Command2_Click()
Dim tmp业务对象 As Object
Set tmp业务对象 = New cls业务
MsgBox "通过外部Dll访问,我的年龄是:" & tmp业务对象.TellMyAges()
' 增加下面这句,可以看到“时间”是 “点击Command2”的时间
MsgBox "外部Dll访问,对象创建时间:" & tmp业务对象.GetObjTime()
End Sub
#11
类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了
globalmultiuse的类,不显式执行new,会执行Class_Initialize()?
VB里Class_Initialize 就是类的构造函数。
#12
楼上两位大神,按照上面的例子,如果要两个按钮都输出28,只修改 全局函数测试.vbp文件的话,该怎么修改?
这里涉及到一个问题,VB类的构造函数是不能带参数的,所以说 光一个new 或者 CreateObject 是没有办法把初始值传给这个类实例的,除非有个第三方数据源,使用某种约定的方式访问数据。
#13
看讨论得那么热闹,按照楼主的步骤一步一步建立了工程和工程组。
运行的结果是
两个按钮出来的都是28!!!!
运行环境:win10
运行的结果是
两个按钮出来的都是28!!!!
运行环境:win10
#14
看讨论得那么热闹,按照楼主的步骤一步一步建立了工程和工程组。
运行的结果是
两个按钮出来的都是28!!!!
运行环境:win10
我也win10 照做了,一个28,一个0
#15
Win10中,能“正常”???
我是在WinXP的虚拟机中试的,但我觉得这个“运行机制”应该跟Win版本无关吧。
(编译ActiveX DLL会“注册”一些垃圾信息,我没在真机上试。反正安装的虚拟机都是用来做测试的,无所谓了。)
有空我也得在Win10中试试。
另外,我觉得VB6的 Class_Initialize 应该不能算是“类构造函数”,
我觉得它的实质就是: VB6通知你,你的“对象”已经按默认规则构建好了,你还想做点什么修改吗?
我是在WinXP的虚拟机中试的,但我觉得这个“运行机制”应该跟Win版本无关吧。
(编译ActiveX DLL会“注册”一些垃圾信息,我没在真机上试。反正安装的虚拟机都是用来做测试的,无所谓了。)
有空我也得在Win10中试试。
另外,我觉得VB6的 Class_Initialize 应该不能算是“类构造函数”,
我觉得它的实质就是: VB6通知你,你的“对象”已经按默认规则构建好了,你还想做点什么修改吗?
#16
怀疑你引用的是之前编译的旧版本DLL。
仔细看看你各个工程的设置,按顺序进行以下操作看能否解决你的问题。
1、检查全局函数测试 的工程属性里“部件”tab页是否设置了 版本兼容。点选二进制兼容,然后兼容目标指向你编译的DLL
2、业务对象测工程试引用 指向 全局函数测试编译出的DLL
3、业务对象测试工程属性与步骤1一样设置对自身编译结果的二进制兼容
4、EXE工程引用指向两个编译的DLL结果。
然后重新编译两个DLL
仔细看看你各个工程的设置,按顺序进行以下操作看能否解决你的问题。
1、检查全局函数测试 的工程属性里“部件”tab页是否设置了 版本兼容。点选二进制兼容,然后兼容目标指向你编译的DLL
2、业务对象测工程试引用 指向 全局函数测试编译出的DLL
3、业务对象测试工程属性与步骤1一样设置对自身编译结果的二进制兼容
4、EXE工程引用指向两个编译的DLL结果。
然后重新编译两个DLL
#17
在64位Windows下:
64位exe和dll在目录c:\windows\sys tem32目录下;
32位exe和dll在目录c:\windows\sys wow64目录下;
所以要注意:
在win64位系统下注册32位ocx或dll需要将32位ocx或dll拷贝到c:\windows\syswow64\目录下。
且注册要用c:\windows\syswow64\regsvr32 xxxxxxx.ocx或dll
64 位 Windows 平台注意点之文件系统重定向 http://www.cnblogs.com/jiake/p/4981555.html
64 位 Windows 平台注意点之注册表重定向 http://www.cnblogs.com/jiake/p/4956218.html
64位exe和dll在目录c:\windows\sys tem32目录下;
32位exe和dll在目录c:\windows\sys wow64目录下;
所以要注意:
在win64位系统下注册32位ocx或dll需要将32位ocx或dll拷贝到c:\windows\syswow64\目录下。
且注册要用c:\windows\syswow64\regsvr32 xxxxxxx.ocx或dll
64 位 Windows 平台注意点之文件系统重定向 http://www.cnblogs.com/jiake/p/4981555.html
64 位 Windows 平台注意点之注册表重定向 http://www.cnblogs.com/jiake/p/4956218.html
#18
对全局工程稍作改造
Public Ages As Long
Public strTime As String
Public Sub InitClass(ByVal paraAges As Long)
Ages = paraAges
strTime = Now() '保存创建时间,用以区分实例
MsgBox strTime & Str(Ages)
End Sub
Public Function ReadAges() As Long
ReadAges = Ages
MsgBox strTime '每次调用的时候显示本实例创建时间。
End Function
然后在form_load那加一个断点。
启动后,进入断点,但并没有弹窗,说明并不在整个进程启动的时候就加载这个全局对象。继续往下一步,对全局公共变量进行了赋值,这时候发生了弹窗,说明对象被加载了。弹窗出来的内容可以看出,公共变量已经被赋值了,再进入initialize的。所以并不是4楼所说的原因。
记下弹窗显示的时间。
此后点击两个按钮都会发生弹窗。弹窗显示的都是同一个时间。也就是说两个按钮调用的都是同一个实例,并不是10楼所说的原因
#19
在64位Windows下:
64位exe和dll在目录c:\windows\sys tem32目录下;
32位exe和dll在目录c:\windows\sys wow64目录下;
所以要注意:
在win64位系统下注册32位ocx或dll需要将32位ocx或dll拷贝到c:\windows\syswow64\目录下。
且注册要用c:\windows\syswow64\regsvr32 xxxxxxx.ocx或dll
64 位 Windows 平台注意点之文件系统重定向 http://www.cnblogs.com/jiake/p/4981555.html
64 位 Windows 平台注意点之注册表重定向 http://www.cnblogs.com/jiake/p/4956218.html
所有的一切都不涉及外部组件的调用,关你这个32位64位啥事啊,就算要灌水,好歹也仔细看看楼主的诉求以及前面的讨论。啥都不看,直接随机粘贴你的文本,起码的尊重都没有
#20
对全局工程稍作改造
Public Ages As Long
Public strTime As String
Public Sub InitClass(ByVal paraAges As Long)
Ages = paraAges
strTime = Now() '保存创建时间,用以区分实例
MsgBox strTime & Str(Ages)
End Sub
Public Function ReadAges() As Long
ReadAges = Ages
MsgBox strTime '每次调用的时候显示本实例创建时间。
End Function
然后在form_load那加一个断点。
启动后,进入断点,但并没有弹窗,说明并不在整个进程启动的时候就加载这个全局对象。继续往下一步,对全局公共变量进行了赋值,这时候发生了弹窗,说明对象被加载了。弹窗出来的内容可以看出,公共变量已经被赋值了,再进入initialize的。所以并不是4楼所说的原因。
记下弹窗显示的时间。
此后点击两个按钮都会发生弹窗。弹窗显示的都是同一个时间。也就是说两个按钮调用的都是同一个实例,并不是10楼所说的原因
就以你这“改造”后的代码,连 Class_Initialize( )过程都没有,
真无法明白:你“对全局公共变量进行了赋值”(哪个变量?是Ages,还是strTime?)的时候,如何能引起“弹窗”的?
#21
难道“大雪糕”的Windows系统是定制的?
对象管理机制,跟我们用的系统都不一样…………
对象管理机制,跟我们用的系统都不一样…………
#22
对全局工程稍作改造
Public Ages As Long
Public strTime As String
Public Sub InitClass(ByVal paraAges As Long)
Ages = paraAges
strTime = Now() '保存创建时间,用以区分实例
MsgBox strTime & Str(Ages)
End Sub
Public Function ReadAges() As Long
ReadAges = Ages
MsgBox strTime '每次调用的时候显示本实例创建时间。
End Function
然后在form_load那加一个断点。
启动后,进入断点,但并没有弹窗,说明并不在整个进程启动的时候就加载这个全局对象。继续往下一步,对全局公共变量进行了赋值,这时候发生了弹窗,说明对象被加载了。弹窗出来的内容可以看出,公共变量已经被赋值了,再进入initialize的。所以并不是4楼所说的原因。
记下弹窗显示的时间。
此后点击两个按钮都会发生弹窗。弹窗显示的都是同一个时间。也就是说两个按钮调用的都是同一个实例,并不是10楼所说的原因
就以你这“改造”后的代码,连 Class_Initialize( )过程都没有,
真无法明白:你“对全局公共变量进行了赋值”(哪个变量?是Ages,还是strTime?)的时候,如何能引起“弹窗”的?
我所说的“对全局公共变量进行了赋值” 是说form里面的那行 ,好吧我看错了,不是对变量赋值,是直接调用initialize 。
嗯,丢人了。
不过我这的确是两个28。但至少能说明两个按钮调用的是同一个实例吧
Microsoft Windows [版本 10.0.16299.192]
#23
. . . . . . .
. . . . . . . . . .
不过我这的确是两个28。但至少能说明两个按钮调用的是同一个实例吧
Microsoft Windows [版本 10.0.16299.192]
我在WinXP虚拟机中试的,两个时间是不一样的(如我在10代码中的注释)。
并且“Command2_Click()”的是动态时间:什么时候点的按钮、就是什么时间。
Command1_Click()则不会变,始终是程序启动的那个时间。
从我的测试结果来看,它们就是两个不相关的对象。
14楼“笨狗先飞”也说了,他的是Win10系统,照样是一个28、一个0。
并且,我们的“试验环境”,根本不存在你在16楼说的那种“版本冲突”问题,因为都是“全新的”。
#24
在Win10系统中,运行WinXP上的老代码、老模块出莫名其妙的兼容性问题很正常。个人意见。
#25
也许楼主要做的只是在资源管理器中要运行的exe文件上点鼠标右键、兼容性、设置以Windows XP (SP 3或4)兼容模式运行,以管理员身份运行。
#26
工程组运行的时候是两个28,
按楼主说的,编译引用后就是28,0
按楼主说的,编译引用后就是28,0
#27
嗯,我运行的时候,两个DLL都是编译好的。
VB6中只有一个EXE工程。
不懂就不要瞎说…………
VB6中只有一个EXE工程。
在Win10系统中,运行WinXP上的老代码、老模块出莫名其妙的兼容性问题很正常。个人意见。
不懂就不要瞎说…………
#28
我觉得,在IDE里的时候,两个DLL,其实各创建了一个实例
但是在EXE运行的时候
EXE中创建了一个 cls全局实例,和一个cls业务
但在创建cls业务的时候在 业务对象测试.dll 中有一个cls全局实例
28其实存在于这个实例中,但是EXE访问不到,他访问到的那个cls全局实例 并不是dll里那个。
但是在EXE运行的时候
EXE中创建了一个 cls全局实例,和一个cls业务
但在创建cls业务的时候在 业务对象测试.dll 中有一个cls全局实例
28其实存在于这个实例中,但是EXE访问不到,他访问到的那个cls全局实例 并不是dll里那个。
#29
大概就这么个意思吧
#30
“28”是在EXE的全局实例中,不是在“业务”创建的“全局”实例中。
#31
估计要对 业务对象测试.vbp来改造才行
#32
#33
我觉得,如果要“共享”唯一的全局对象,但VB6又无法“阻止乱New全局类对象”,那么应该改变“管理方式”:
应该由 EXE启动时,New一个“全局”对象;
其它的“业务对象”不能再自己去New,而应该提供一个“获取对象”的接口函数(过程);
在EXE启动后,创建其它“业务对象”时,调用其接口,把“全局”对象传递给它(当然是“对象引用”)。
在“业务对象”中,都是通过这个“获得的对象引用”来操作“全局对象”。
应该由 EXE启动时,New一个“全局”对象;
其它的“业务对象”不能再自己去New,而应该提供一个“获取对象”的接口函数(过程);
在EXE启动后,创建其它“业务对象”时,调用其接口,把“全局”对象传递给它(当然是“对象引用”)。
在“业务对象”中,都是通过这个“获得的对象引用”来操作“全局对象”。
#34
把全局对象挪到SQL数据库中。
#35
把全局对象挪到SQL数据库中。
怎么不说“把数据写到文本文件中”了…………
#36
为了描述我的问题,我写成了测试代码,并运行过:
一、新建一个ActiveX DLL工程,名字:全局函数测试;
添加一个类模块,名字cls全局,它的Instancing设置为GloabalMultiUse, 代码:
。。。。
把它的Instancing设置为 PublicNotCreate
#37
为了描述我的问题,我写成了测试代码,并运行过:
一、新建一个ActiveX DLL工程,名字:全局函数测试;
添加一个类模块,名字cls全局,它的Instancing设置为GloabalMultiUse, 代码:
。。。。
把它的Instancing设置为 PublicNotCreate
一改编译不出来了