我写了一个控件(VC6+MFC),里面除了COleControl类外,还有多个基于CCmdTarget引出的对象。由于CCmdTarget对象要访问COleControl里面的成员变量,而在CCmdTarget对象生成时无法知道COleControl的指针,所以采用了全局变量的方式,这样达到了目的。这样就出现了问题:当只有一个实例时工作正常,多个实例时工作就不正常了。因为多个实例共用全局变量。我该怎么办?我是菜鸟,不知道问题说明白了没有。

解决方案 »

  1.   

    去掉全局变量,在CCmdTarget里添加一个COleControl的指针变量。
      

  2.   

    就像我所说的,如果将COleControl的指针变量传递给CCmdTarget对象呢?
      

  3.   

    CCmdTarget对象的生成不是由COleControl对象控制,所以就没有办法知道COleControl的指针。(也可能是我不知道有这个方法,能不能说详细点)。
      

  4.   

    在CCmdTarget里添加一个COleControl的指针变量,这样就可以互相访问了,在编程时尽量减少实例,用方法取得实例,在类中是这样的,比如类A和类B:
    Class B
    {
       ……
    };
    Class A 
    {
      B m_b;
    };
    在A中会先初始化m_b,也就是用先用类B形成实例m_b
      

  5.   

    楼上说的不行啊,因为CCmdTarget实例的生成是由容器控制的,不是我的程序里面有多个实例。
      

  6.   

    我认为ocx是动态连库,在一个应用程序进程空间中只能有一份,不能将全局量分开。
    你的问题我认为可以在COleControl中加一个方法让用户调用在内部生成CCmdTarget对象,再返回用户,这样你就可以控制它了
      

  7.   

    CCmdTarget对象是由容器生成的,不知道你们有没有使用过MapX(MapInfo公司的GIS控件)。我把我这边的情况说详细一点:
    (1)我做的控件就是类似MapX的。由一个CMapX(基类为COleControl)和其他诸如CLayer、CPattern等对象(基类为CCmdTarget)组成。
    (2)控件注册后,用户在应用程序中可以直接生成CLayer等对象。此时CLayer对象的生成CMapX好像没有办法控制。
    (3)由于CLayer对象必须使用CMapX的成员变量,所以我设置了一个CMapX的全局变量,在CMapX的构造函数里赋值(因为用户在使用我这个控件的时候,必然会调用CMapX的构造函数)然后CLayer对象生成后就可以通过这个全局变量访问CMapX了。
    (4)这个控件是可视控件,当用户应用程序界面上只用一次此控件时,工作良好;当再放一个此控件后,由于这两个控件是CMapX的两个实例,这两个实例访问的是同一个控件的全局变量,因此当一个控件实例改变设置后,另外一个控件实例会跟着改变不知道描述清楚了没有。在调试过程中我发现,这两个控件实例的指针是不一样的(CMapX的构造函数里的this指针不同)。我现在是使用全局变量保存CMapX的指针,使得在CLayer等对象生成后通过这个全局变量访问CMapX,因而会出现上述问题。如果在CLayer对象里有办法知道自己实例的指针,这个问题就解决了。不知道你们是否知道?谢谢!
      

  8.   

    两种途径:
    一,既然用户来创建CLayer、CPattern,你就可以给CLayer、CPattern提供显式的方法让用户设置它的COleControl实例,如果不设置,与COleControl实例相关的调用就报错。二,改变用户创建CLayer、CPattern的方式,在COloControl上提供创建方法,创建时就将实例给对象。
      

  9.   

    楼主的错误是因为违背了组件的Apartment套间类型的规则,我在下面的帖子中做过详细的讲解:
    http://expert.csdn.net/Expert/topic/2469/2469144.xml?temp=.3626825楼主的控件如果是使用了Apartment套间类型(即注册表项中为Apartment),这样生成的组件必须实现对全局及静态变量的线程保护,因而出现楼主的错误。
    如果楼主希望轻松点(即不改写源代码),可以只是简单地将注册表项中的值改为Single即可,此时在编写组件时就可以不要求对全局及静态变量进行保护了。