2008-10-04 60 views
0

环境:VS2008(ATL),Borland Developer Studio 2006.公寓之间的ActiveX事件

大家好。我在ActiveX控件事件方面遇到了一些麻烦。

这里是我的应用程序的体系结构的简要描述:

有包含STA ActiveX控件(又名对照)和MTA COM对象(又名对象)的进程内COM服务器。

这里是控制和对象接口的IDL定义:

[ 
    object, 
    uuid(2338CCAF-BBAF-4E29-929B-A67285B1E772), 
    dual, 
    nonextensible, 
    pointer_default(unique) 
] 
interface IObject : IDispatch{ 
    [id(1)] HRESULT DoWork(void); 
}; 

[ 
    object, 
    uuid(1A0A1DA2-E33B-4DF4-99A9-9EAEF2281E7D), 
    dual, 
    nonextensible, 
    pointer_default(unique) 
] 
interface IControl : IDispatch{ 
}; 


[ 
    uuid(BC27FABD-2794-4F9C-B3BD-C0C0628741FA), 
    version(1.0), 
    helpstring("AVRep 1.0 Type Library") 
] 

library ActiveXLib 
{ 
    importlib("stdole2.tlb"); 
    [ 
     uuid(4B5575A7-E0FF-49B5-AE10-0D980CF49EB3) 
    ] 
    dispinterface _IControlEvents 
    { 
     properties: 
     methods: 
      [id(1)] HRESULT SomeEvent([in] IObject* obj); 
     }; 
    [ 
     uuid(7C44F19E-6B71-434B-96F6-E29A3C66C794), 
     control 
    ] 
    coclass Control 
    { 
     [default] interface IControl; 
     [default, source] dispinterface _IControlEvents; 
    }; 
    [ 
     uuid(17BDFAC0-DF21-4474-BCFF-846FE0075D68) 
    ] 
    coclass Object 
    { 
     [default] interface IObject; 
    }; 
}; 

客户端是一个Delphi应用程序与表单上ActiveX控件它创建MTA对象,并调用其的DoWork方法

var 
    mta : IObject; 
begin 
    mta := CreateOleObject('ActiveXLib.Object.1') as IObject; 
    mta.DoWork(); 
end; 

此方法直接调用ActiveX控件coclass的Fire_SomeEvent方法,并将“this”作为参数(指向IObject接口的指针)。 Delphi代码成功接收事件,但是当它尝试访问任何IObject方法或属性(为简单起见,未在idl中显示),则在oleaut32.dll中发生访问冲突。

一个重要的注意事项 - 我使用ATLCPImplMT类来实现不同线程的事件触发(详见http://support.microsoft.com/kb/280512)。该实现允许在事件触发时切换公寓(从对象的MTA公寓到STA Delphi公寓)。我建议这个问题与不正确的事件参数编组有关,因为当使用标准的ATLCPImpl类时,所有工作都很好。

跨公寓活动是否有任何限制?可能需要一些特殊的Delphi环境设置才能正确使用activex对象...

回答

1

您是否正在访问在事件处理程序所在的同一线程中创建的对象,或者是否在主线程中创建COM对象?如果您在事件处理程序中与创建该对象的线程不在同一个线程上下文中,则在尝试访问COM对象时可能会遇到访问冲突。

一个快速修复的解决方法可以是从事件处理程序向主线程发布消息,并让主线程访问主线程上下文中的COM对象,而不是直接访问COM事件处理程序。

线程和COM不是那么复杂,没有COM的线程。