2008-10-04 12 views
0

Environnement: VS2008 (ATL), Borland Developer Studio 2006.Événements ActiveX entre appartements

Bonjour à tous. Je rencontre des problèmes avec les événements de contrôle ActiveX.

Voici une brève description de mon architecture app:

Il y a un serveur COM inproc qui contient le contrôle ActiveX STA (aka contrôle) et de l'objet COM MTA (alias objet).

Voici la définition IDL des interfaces de contrôle et objet:

[ 
    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; 
    }; 
}; 

client est une application Delphi avec un contrôle ActiveX sur la forme qui crée un objet MTA et appelle sa méthode DoWork

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

Cette méthode appelle directement la méthode Fire_SomeEvent du contrôle ActiveX coclass et transmet 'this' comme paramètre (pointeur vers l'interface IObject). Le code Delphi reçoit avec succès l'événement mais quand il essaie d'accéder à n'importe quelle méthode ou propriété IObject (non montré dans idl pour la simplicité) alors la violation d'accès s'est produite dans oleaut32.dll.

Une remarque importante - J'utilise la classe ATLCPImplMT pour implémenter le déclenchement d'événement à partir de différents threads (voir http://support.microsoft.com/kb/280512 pour plus de détails). Cette implémentation permet de basculer des appartements lorsque l'événement se déclenche (de l'appartement MTA de l'objet à l'appartement STA Delphi). Je suggère que ce problème est lié au marshaling de paramètre d'événement incorrect parce que lorsque la classe ATLCPImpl standard est utilisée, tout fonctionne correctement.

Existe-t-il des restrictions pour les événements inter-appartements? Peut-être qu'une configuration spéciale de l'environnement Delphi est nécessaire pour travailler correctement avec les objets ActiveX ...

Répondre

1

Accédez-vous aux objets créés dans le même thread que le gestionnaire d'événements ou bien l'objet COM a-t-il été créé dans le thread principal? Si vous n'êtes pas dans le même contexte de thread dans le gestionnaire d'événement que le thread qui a créé l'objet, vous pouvez obtenir des violations d'accès lorsque vous essayez d'accéder à l'objet COM. Une solution de contournement rapide peut consister à envoyer un message au thread principal à partir du gestionnaire d'événements, et le thread principal accéder à l'objet COM dans le contexte de thread principal, au lieu de directement dans le gestionnaire d'événements COM.

Threads et COM n'est pas moins compliqué que les threads sans COM.