2008-10-04 45 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的線程。