描述:
各位好:
小弟新学ActiveX编程,在MFC Wizzard基础上添加自己的功能,并用Class Wizzard 添加了若干Method和Event。
我如果通过HTML中的VBScript调用ActiveX控件的Method,然后在Method中
FireXXEvent,一切都正常。通过VBScript能正确响应该事件。
然而,我用控件内部自己创建的工作线程FireXXEvent时,IE却不能正确
响应该事件,在调试状态,还能看见异常发生,好像是控件内的Invoke
方法没返回正确值。(在TSTCON32中调试时,能看见事件发生)
我查以往CSDN时,也发现了同类问题,见:
http://expert.csdn.net/Expert/topic/2495/2495556.xml?temp=.8208277
希望对此有了解的朋友能给点帮助。谢先!
解决方案1:
那是因为FireEvent实际上是调用客户端实现的一个接口(在这就是IE实现的IDispatch接口)的方法,而ActiveX控件一定是放在STA套间(虽然也可以,但应该没人实现为放在MTA)的,因此工作线程调用IE的IDispatch接口一定且必须是代理接口,这个接口必须通过汇集得到(以创建代理对象)。
即需要在主线程调用CoMarshalInterface来列集IE的那个IDispatch接口,再在工作线程调用CoUnmarshalInterface来散集IDispatch接口,进而在工作线程中通过散集的IDispatch接口发起事件。由于楼主是在线程间汇集接口,所以可以使用CoMarshalInterThreadInterfaceInStream和CoGetInterfaceAndReleaseStream代替上面的两个函数进行汇集,效率会有所提高。
而这样做(即建立代理对象)的实际工作工程,与楼主说的“另外”是异曲同工的,所以楼主要是闲上面麻烦,可以按照楼主说的“另外”来实现。
还有就是COleControl是MFC的包装类,其中使用了一些MFC的底层的机制(如线程状态等),所以当欲跨线程传递ActiveX对象的指针时,不可直接传递COleControl*之类,否则就有可能发生断言失败,而应该通过FromHandle和Detach来传递句柄(不过这样就不能使用派生类的相关成员函数)。因此楼主如果想使用上面的方法,需先获得客户的接口指针(即IDispatch),然后将其列集得到的IStream*作为线程参数传递给工作线程,而不要使用直接的this。