关于vb6中创建全局函数类得问题

时间:2022-07-13 23:15:43
为了描述我的问题,我写成了测试代码,并运行过:

一、新建一个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(), 应该是基于“不同的对象实例”的。

#2


引用 1 楼 Chen8013 的回复:
我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
 对于数值类型的变量,在VB6中自然就是0。

你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。


两者在运行时是在同一进程中的,业务对象已经new过了,也没有数据需要初始化的,初始化在自定义全局函数 InitClass中

#3


引用 2 楼 goodafu2 的回复:
Quote: 引用 1 楼 Chen8013 的回复:

我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
 对于数值类型的变量,在VB6中自然就是0。

你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。


两者在运行时是在同一进程中的,业务对象已经new过了,也没有数据需要初始化的,初始化在自定义全局函数 InitClass中

我认为,虽然是“在同一进程中”,但是:
在Form_Load( )调用 InitClass时,会创建一个“全局函数测试”对象;
在“业务对象测试”中,它肯定New了另一个“全局函数测试”对象。

#4


类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了

#5


引用 4 楼 bakw 的回复:
类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了


globalmultiuse的类,不显式执行new,会执行Class_Initialize()?

#6


引用 3 楼 Chen8013 的回复:
Quote: 引用 2 楼 goodafu2 的回复:

Quote: 引用 1 楼 Chen8013 的回复:

我觉得,是因为你的“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() 中看到的返回值,应该就是你给它赋的“初值”了。

#9


引用 7 楼 goodafu2 的回复:
楼上两位大神,按照上面的例子,如果要两个按钮都输出28,只修改 全局函数测试.vbp文件的话,该怎么修改?

在VB6中,我还真不知道如何处理。
因为所有类的“构造函数”,VB6并没有“交给我们”来控制。
如果象C++那种,应该就很容易了。

另外还有一种方法,不知道对你是否适用:
参考我这个帖子:https://bbs.csdn.net/topics/392318790
用“自己创建对象”的方法(类对象不能New、只能通过自己的“创建对象的接口函数”来创建)。
这样,在调用“创建接口”时,如果没有创建,则创建一个; 如果已经创建,则返回已创建的“公共对象”的引用。

#10


刚才做了个试验,通过“对象创建时间”,可以明确的判断出:
 你的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


引用 5 楼 goodafu2 的回复:
Quote: 引用 4 楼 bakw 的回复:

类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了


globalmultiuse的类,不显式执行new,会执行Class_Initialize()?

VB里Class_Initialize 就是类的构造函数。

#12


引用 7 楼 goodafu2 的回复:
楼上两位大神,按照上面的例子,如果要两个按钮都输出28,只修改 全局函数测试.vbp文件的话,该怎么修改?

这里涉及到一个问题,VB类的构造函数是不能带参数的,所以说 光一个new 或者 CreateObject 是没有办法把初始值传给这个类实例的,除非有个第三方数据源,使用某种约定的方式访问数据。

#13


看讨论得那么热闹,按照楼主的步骤一步一步建立了工程和工程组。
运行的结果是
两个按钮出来的都是28!!!!
运行环境:win10

#14


引用 13 楼 chewinggum 的回复:
看讨论得那么热闹,按照楼主的步骤一步一步建立了工程和工程组。
运行的结果是
两个按钮出来的都是28!!!!
运行环境:win10

我也win10 照做了,一个28,一个0

#15


Win10中,能“正常”???

我是在WinXP的虚拟机中试的,但我觉得这个“运行机制”应该跟Win版本无关吧。
(编译ActiveX DLL会“注册”一些垃圾信息,我没在真机上试。反正安装的虚拟机都是用来做测试的,无所谓了。)
有空我也得在Win10中试试。 关于vb6中创建全局函数类得问题


另外,我觉得VB6的 Class_Initialize 应该不能算是“类构造函数”,
 我觉得它的实质就是: VB6通知你,你的“对象”已经按默认规则构建好了,你还想做点什么修改吗?

#16


怀疑你引用的是之前编译的旧版本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

#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


引用 17 楼 zhao4zhong1 的回复:
在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


引用 18 楼 chewinggum 的回复:
对全局工程稍作改造

    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?)的时候,如何能引起“弹窗”的?
关于vb6中创建全局函数类得问题

#21


难道“大雪糕”的Windows系统是定制的?
对象管理机制,跟我们用的系统都不一样…………
关于vb6中创建全局函数类得问题

#22


引用 20 楼 Chen8013 的回复:
Quote: 引用 18 楼 chewinggum 的回复:


对全局工程稍作改造

    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?)的时候,如何能引起“弹窗”的?
关于vb6中创建全局函数类得问题


我所说的“对全局公共变量进行了赋值” 是说form里面的那行 ,好吧我看错了,不是对变量赋值,是直接调用initialize 。
嗯,丢人了。
不过我这的确是两个28。但至少能说明两个按钮调用的是同一个实例吧
Microsoft Windows [版本 10.0.16299.192]

#23


引用 22 楼 chewinggum 的回复:
Quote: 引用 20 楼 Chen8013 的回复:

. . . . . . . 


. . . . . . . . . .
不过我这的确是两个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

#27


嗯,我运行的时候,两个DLL都是编译好的。
VB6中只有一个EXE工程。


引用 24 楼 zhao4zhong1 的回复:
在Win10系统中,运行WinXP上的老代码、老模块出莫名其妙的兼容性问题很正常。个人意见。

不懂就不要瞎说…………
关于vb6中创建全局函数类得问题

#28


我觉得,在IDE里的时候,两个DLL,其实各创建了一个实例
但是在EXE运行的时候
EXE中创建了一个 cls全局实例,和一个cls业务
但在创建cls业务的时候在 业务对象测试.dll 中有一个cls全局实例
28其实存在于这个实例中,但是EXE访问不到,他访问到的那个cls全局实例 并不是dll里那个。

#29


关于vb6中创建全局函数类得问题
大概就这么个意思吧

#30


“28”是在EXE的全局实例中,不是在“业务”创建的“全局”实例中。
关于vb6中创建全局函数类得问题

#31


估计要对 业务对象测试.vbp来改造才行

#32


关于vb6中创建全局函数类得问题

#33


我觉得,如果要“共享”唯一的全局对象,但VB6又无法“阻止乱New全局类对象”,那么应该改变“管理方式”:
应该由 EXE启动时,New一个“全局”对象;
其它的“业务对象”不能再自己去New,而应该提供一个“获取对象”的接口函数(过程);
在EXE启动后,创建其它“业务对象”时,调用其接口,把“全局”对象传递给它(当然是“对象引用”)。

在“业务对象”中,都是通过这个“获得的对象引用”来操作“全局对象”。

#34


把全局对象挪到SQL数据库中。 关于vb6中创建全局函数类得问题

#35


引用 34 楼 zhao4zhong1 的回复:
把全局对象挪到SQL数据库中。 关于vb6中创建全局函数类得问题

关于vb6中创建全局函数类得问题
怎么不说“把数据写到文本文件中”了…………

#36


引用 楼主 goodafu2 的回复:
为了描述我的问题,我写成了测试代码,并运行过:

一、新建一个ActiveX DLL工程,名字:全局函数测试;
       添加一个类模块,名字cls全局,它的Instancing设置为GloabalMultiUse, 代码:
。。。。


把它的Instancing设置为 PublicNotCreate

#37


引用 36 楼 PctGL 的回复:
Quote: 引用 楼主 goodafu2 的回复:

为了描述我的问题,我写成了测试代码,并运行过:

一、新建一个ActiveX DLL工程,名字:全局函数测试;
       添加一个类模块,名字cls全局,它的Instancing设置为GloabalMultiUse, 代码:
。。。。


把它的Instancing设置为 PublicNotCreate

一改编译不出来了

#1


我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
 对于数值类型的变量,在VB6中自然就是0。

你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。

#2


引用 1 楼 Chen8013 的回复:
我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
 对于数值类型的变量,在VB6中自然就是0。

你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。


两者在运行时是在同一进程中的,业务对象已经new过了,也没有数据需要初始化的,初始化在自定义全局函数 InitClass中

#3


引用 2 楼 goodafu2 的回复:
Quote: 引用 1 楼 Chen8013 的回复:

我觉得,是因为你的“tmp业务对象”的数据未初始化,它的对象数据值就是“默认值”,
 对于数值类型的变量,在VB6中自然就是0。

你在 EXE工程中的 ReadAges() ,跟“业务对象测试”中的 ReadAges(), 应该是基于“不同的对象实例”的。


两者在运行时是在同一进程中的,业务对象已经new过了,也没有数据需要初始化的,初始化在自定义全局函数 InitClass中

我认为,虽然是“在同一进程中”,但是:
在Form_Load( )调用 InitClass时,会创建一个“全局函数测试”对象;
在“业务对象测试”中,它肯定New了另一个“全局函数测试”对象。

#4


类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了

#5


引用 4 楼 bakw 的回复:
类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了


globalmultiuse的类,不显式执行new,会执行Class_Initialize()?

#6


引用 3 楼 Chen8013 的回复:
Quote: 引用 2 楼 goodafu2 的回复:

Quote: 引用 1 楼 Chen8013 的回复:

我觉得,是因为你的“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() 中看到的返回值,应该就是你给它赋的“初值”了。

#9


引用 7 楼 goodafu2 的回复:
楼上两位大神,按照上面的例子,如果要两个按钮都输出28,只修改 全局函数测试.vbp文件的话,该怎么修改?

在VB6中,我还真不知道如何处理。
因为所有类的“构造函数”,VB6并没有“交给我们”来控制。
如果象C++那种,应该就很容易了。

另外还有一种方法,不知道对你是否适用:
参考我这个帖子:https://bbs.csdn.net/topics/392318790
用“自己创建对象”的方法(类对象不能New、只能通过自己的“创建对象的接口函数”来创建)。
这样,在调用“创建接口”时,如果没有创建,则创建一个; 如果已经创建,则返回已创建的“公共对象”的引用。

#10


刚才做了个试验,通过“对象创建时间”,可以明确的判断出:
 你的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


引用 5 楼 goodafu2 的回复:
Quote: 引用 4 楼 bakw 的回复:

类的初始化事件是 Private Sub Class_Initialize()
你的 InitClass 又不是初始化,VB类的初始化是不能带参数的。
Command2_Click()里创建了一个新局部变量,没经过InitClass赋值,当然是0了


globalmultiuse的类,不显式执行new,会执行Class_Initialize()?

VB里Class_Initialize 就是类的构造函数。

#12


引用 7 楼 goodafu2 的回复:
楼上两位大神,按照上面的例子,如果要两个按钮都输出28,只修改 全局函数测试.vbp文件的话,该怎么修改?

这里涉及到一个问题,VB类的构造函数是不能带参数的,所以说 光一个new 或者 CreateObject 是没有办法把初始值传给这个类实例的,除非有个第三方数据源,使用某种约定的方式访问数据。

#13


看讨论得那么热闹,按照楼主的步骤一步一步建立了工程和工程组。
运行的结果是
两个按钮出来的都是28!!!!
运行环境:win10

#14


引用 13 楼 chewinggum 的回复:
看讨论得那么热闹,按照楼主的步骤一步一步建立了工程和工程组。
运行的结果是
两个按钮出来的都是28!!!!
运行环境:win10

我也win10 照做了,一个28,一个0

#15


Win10中,能“正常”???

我是在WinXP的虚拟机中试的,但我觉得这个“运行机制”应该跟Win版本无关吧。
(编译ActiveX DLL会“注册”一些垃圾信息,我没在真机上试。反正安装的虚拟机都是用来做测试的,无所谓了。)
有空我也得在Win10中试试。 关于vb6中创建全局函数类得问题


另外,我觉得VB6的 Class_Initialize 应该不能算是“类构造函数”,
 我觉得它的实质就是: VB6通知你,你的“对象”已经按默认规则构建好了,你还想做点什么修改吗?

#16


怀疑你引用的是之前编译的旧版本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

#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


引用 17 楼 zhao4zhong1 的回复:
在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


引用 18 楼 chewinggum 的回复:
对全局工程稍作改造

    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?)的时候,如何能引起“弹窗”的?
关于vb6中创建全局函数类得问题

#21


难道“大雪糕”的Windows系统是定制的?
对象管理机制,跟我们用的系统都不一样…………
关于vb6中创建全局函数类得问题

#22


引用 20 楼 Chen8013 的回复:
Quote: 引用 18 楼 chewinggum 的回复:


对全局工程稍作改造

    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?)的时候,如何能引起“弹窗”的?
关于vb6中创建全局函数类得问题


我所说的“对全局公共变量进行了赋值” 是说form里面的那行 ,好吧我看错了,不是对变量赋值,是直接调用initialize 。
嗯,丢人了。
不过我这的确是两个28。但至少能说明两个按钮调用的是同一个实例吧
Microsoft Windows [版本 10.0.16299.192]

#23


引用 22 楼 chewinggum 的回复:
Quote: 引用 20 楼 Chen8013 的回复:

. . . . . . . 


. . . . . . . . . .
不过我这的确是两个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

#27


嗯,我运行的时候,两个DLL都是编译好的。
VB6中只有一个EXE工程。


引用 24 楼 zhao4zhong1 的回复:
在Win10系统中,运行WinXP上的老代码、老模块出莫名其妙的兼容性问题很正常。个人意见。

不懂就不要瞎说…………
关于vb6中创建全局函数类得问题

#28


我觉得,在IDE里的时候,两个DLL,其实各创建了一个实例
但是在EXE运行的时候
EXE中创建了一个 cls全局实例,和一个cls业务
但在创建cls业务的时候在 业务对象测试.dll 中有一个cls全局实例
28其实存在于这个实例中,但是EXE访问不到,他访问到的那个cls全局实例 并不是dll里那个。

#29


关于vb6中创建全局函数类得问题
大概就这么个意思吧

#30


“28”是在EXE的全局实例中,不是在“业务”创建的“全局”实例中。
关于vb6中创建全局函数类得问题

#31


估计要对 业务对象测试.vbp来改造才行

#32


关于vb6中创建全局函数类得问题

#33


我觉得,如果要“共享”唯一的全局对象,但VB6又无法“阻止乱New全局类对象”,那么应该改变“管理方式”:
应该由 EXE启动时,New一个“全局”对象;
其它的“业务对象”不能再自己去New,而应该提供一个“获取对象”的接口函数(过程);
在EXE启动后,创建其它“业务对象”时,调用其接口,把“全局”对象传递给它(当然是“对象引用”)。

在“业务对象”中,都是通过这个“获得的对象引用”来操作“全局对象”。

#34


把全局对象挪到SQL数据库中。 关于vb6中创建全局函数类得问题

#35


引用 34 楼 zhao4zhong1 的回复:
把全局对象挪到SQL数据库中。 关于vb6中创建全局函数类得问题

关于vb6中创建全局函数类得问题
怎么不说“把数据写到文本文件中”了…………

#36


引用 楼主 goodafu2 的回复:
为了描述我的问题,我写成了测试代码,并运行过:

一、新建一个ActiveX DLL工程,名字:全局函数测试;
       添加一个类模块,名字cls全局,它的Instancing设置为GloabalMultiUse, 代码:
。。。。


把它的Instancing设置为 PublicNotCreate

#37


引用 36 楼 PctGL 的回复:
Quote: 引用 楼主 goodafu2 的回复:

为了描述我的问题,我写成了测试代码,并运行过:

一、新建一个ActiveX DLL工程,名字:全局函数测试;
       添加一个类模块,名字cls全局,它的Instancing设置为GloabalMultiUse, 代码:
。。。。


把它的Instancing设置为 PublicNotCreate

一改编译不出来了