VCL组件是否不能在多个线程中使用,只能在VCL主线程中使用?
我在写一个ActiveX的控件,但是它在IE中运行时,由于IE中的多个窗口分别在不同线程中(进程是同一个),所以有些VCL组件不正常,比如TPopupMenu就只能在第一个控件中弹出,在其他窗口的控件中不能弹出,不知道大家有什么方法可以处理。谢谢

解决方案 »

  1.   

    VCL界面控件不是线程安全的,多线程要访问这些控件时用Synchronize切换到主线程来执行。
    TThread.Synchronize
      

  2.   

    怎么解决不太清楚,等高手来说。但是大多数VCL组建都不是线程安全的,通常VCL组建也使用于主线程,非主线程的通过synchronized()与VCL组建通信
      

  3.   

    TPopupMenu确实不是线程安全的,象你说的“只能在第一个控件中弹出,在其他窗口的控件中不能弹出”的问题我也遇到过,我用过好几种办法解决此问题,都不太理想,后来,终于用最原始的办法搞定了,下面大致说说:
    ------------------------------------------
    1。象通常一样设计,定义TPopupMenu,但不要写其OnClick事件2。在需要弹出菜单的地方,不要用自动弹出,或调用Popup(),在OnMouseUp(或适当的其他事件内)
    用API弹出菜单: ::TrackPopupMenu(PopupMenu1->Handle,TPM_LEFTALIGN,
                       Mouse->CursorPos.x,
                       Mouse->CursorPos.y,
                       0,Handle,NULL);
    //这里的 Handle 参数就是Form的 Handle,因为菜单的消息由Form处理(即WMMenuCommand函数)3。在 .h中加入:class TfmMain : public TForm
    {
    ... 
    protected:
            BEGIN_MESSAGE_MAP
                    VCL_MESSAGE_HANDLER(WM_COMMAND, Messages::TWMCommand, WMMenuCommand)
            END_MESSAGE_MAP(TForm)
            void __fastcall WMMenuCommand(Messages::TWMCommand &msg);
    };4。在 .cpp中加入消息处理函数:void __fastcall TfmMain::WMMenuCommand(Messages::TWMCommand &msg)
    {
      //MenuItem1,MenuItem2 是菜单项的名称
      //也可用switch...case...  if(msg.ItemID == MenuItem1->Command) {
        ...//响应菜单1
      }
      if(msg.ItemID == MenuItem2->Command) {
        ...//响应菜单2
      }
      ...
    }
      

  4.   

    补充一点,对于ActiveForm,映射宏应该这样(TForm => TActiveForm):protected:
            BEGIN_MESSAGE_MAP
                    VCL_MESSAGE_HANDLER(WM_COMMAND, Messages::TWMCommand, WMMenuCommand)
            END_MESSAGE_MAP(TActiveForm)
      

  5.   

    我用的是BCB,delphi原理一样的,消息映射的写法不同而已。
      

  6.   

    to myy()
        首先,谢谢了,你的方法应该可行,先收下,但是我并不满足,因为VCL不是线程安全的,所以菜单问题可以如此解决,其他是否还有问题,总是不放心。
        我不知道将线程模式ThreadMode设成tmSingle有没有用,好像还是不行,不知道这个模式有什么用,我原来用的是Apartment的。
      

  7.   

    ot zy61(张旸) :对于ActiveX这种技术,Borland 在BCB 和 Delphi 上采用了不同的办法,BCB用的基本是ATL封装VCL,除了少数VCL本身的非线程安全会带来一些问题(比较典型的就是TPopupMenu),虽然编程稍复杂,还是很稳定的;而delphi是用borland自己开发的DAX框架,问题更多(相信你经常遇到著名的DAX Error),所以我现在基本不用Delphi做ActiveX了。顺便说一下,我用BCB开发的ActiveForm是相当复杂的,用到VirtualTree, Raize, DevExpress FlowChart等几个第三方控件(尤其是VirtualTree,源代码多达3万多行),并且是嵌入网页中的,但从使用的情况来看,在Win 9x/2k/xp/2003 上,相当稳定。
      

  8.   

    to myy
        听君一席话,胜读十年书,不过问题是,我现在正在开发的软件换用bcb或其他可能不大,必须Delphi到底,如何是好,虽然遇到的问题不是很多,也不是没有办法解决,但是对于可能遇到的问题不了然的话,尤其是还是DAX中的作物,那实在是很可怕的事情。难道没有太好的办法吗?
        另外,问一下,线程模式tmSingle和tmApartment有什么区别。