Bonjour,

alors j'ai un cas un peu compliqué à vous soumettre, c'est en relation avec l'utilisation de l'interface IEnumVariant qui permet de réaliser l'instruction foreach de VB avec Delphi. Voir la FAQ pour plus d'infos.

Donc j'arrive bien à faire un parcours de mon objet COM supportant l'interface pas de problème mais comme la syntaxe est assez lourde j'ai voulu faire une procédure qui serait capable de faire le foreach de l'objet COM et qui me transmettrais chaque item parcouru via une procédure de rappel passé en paramètre de ma procédure.

Voici mon code :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
TOleVariantProcedure = procedure (var poElement: OleVariant);
 
procedure Enumerate( const poObject: IDispatch; const CallBack: TOleVariantProcedure ); overload;
var
 voEnumDict, voElement: OleVariant;
 voEnumerator: IEnumVariant;
 DispParamNoArgs: TDispParams;
 viFetched: LongWord;
begin
 try
  // si les paramètres sont invalides alors ne rien faire
  if not Assigned( CallBack ) or ( poObject = NIL ) then
   Exit;
 
  // initialiser les paramètres
  DispParamNoArgs.rgvarg := NIL;
  DispParamNoArgs.rgdispidNamedArgs := NIL;
  DispParamNoArgs.cArgs := 0;
  DispParamNoArgs.cNamedArgs := 0;
 
  // récupérer l'interface IEnumVariant
  OleCheck( poObject.Invoke( DISPID_NEWENUM, GUID_NULL, 0, DISPATCH_PROPERTYGET, DispParamNoArgs, @voEnumDict, NIL, NIL ) );
 
  // L'interface est-elle assignée
  if VarIsEmpty( voEnumDict ) or VarIsNull( voEnumDict ) then
   raise Exception.Create( 'L''Enumerator récupéré n''est pas assigné.' );
 
  // l'interface est-elle du bon type
  if VarType( voEnumDict ) <> varUnknown then
   raise Exception.Create( 'L''Enumerator récupéré n''est pas valide.' );
 
  // caster l'Enumerator, très important !!
  voEnumerator := IUnknown( voEnumDict ) as IEnumVariant;
 
  // parcourir l'Enumerator
  while voEnumerator.Next( 1, voElement, viFetched ) = S_OK do
   CallBack( voElement );
 
 except
  on E: Exception do
  begin
   Add_DBLogEvent( viLogApplicationCode, K_LogSevereError, 'incObj_Tools : Enumerate ', E.Message );
   raise;
  end;
 end;
end;
A noter que j'ai une version overload de cette procédure pour utiliser le type :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
TOleVariantProcedureObject = procedure (var poElement: OleVariant) of object;
Ainsi je peux utiliser comme CallBack soit une procédure soit une méthode.

Le problème est le suivant : j'obtiens une Opération de variant incorrecte...

Voici un exemple d'appel :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
procedure TMaClasse.FaireQQchose();
var
 voFields: IDispatch;
 procedure ForEach( var poElement: OleVariant );
 begin
  // fais des choses
 
 end;
begin
  // voFields contient un objet COM supportant lEnumVariant
  Enumerate( voFields, @ForEach );
end;
Le problème semble subvenir lorsque j'utilises l'objet COM (ou celui qui le contient) à l'intérieur de ma procédure ForEach. Je tient à préciser que le code contenu dans Enumerate pour parcourir l'interface lEnumVariant est valide car si je fais tout dans le même bloc ça passe sans problèmes.
Si vous avez des idées, je suis preneur.