Imperfection de Delphi : Interop et IPropertyStorage ?
Je travailles depuis une semaine sur IPropertyStorage et après quelques recherches je suis tomber sur quelques bugs.
Déjà le type TStatPropSTG n'est pas défini correctement dans Borland.VCL.activeX. voici la bonne déclaration :
Code:
1 2 3 4 5 6 7 8
|
tagSTATPROPSTG = packed record
lpwstrName: IntPtr; { POleStr }
propid: TPropID;
vt: TVarType;
end;
STATPROPSTG = tagSTATPROPSTG;
TStatPropStg = tagSTATPROPSTG; |
Bon ensuite je me balade avec plein d'interrogations.
Lorsque j'utilise IPropertyStorage.ReadMultiple j'ai un problème avec mon element de type TPropVariant. S'il s'agit d'un élément VT_VECTOR je me retrouve avec un tableau.
Si je prends la propriété capropvar.pelems elle est défini comme un IntPtr, mais en fait in s'agit d'un pointeur sur un tableau de TPropVariant. Comment je fais pour récupérer mon tableau ?
pour l'instant je fais :
Code:
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
|
nb:=value.ulVal;
if value.vt<>VT_EMPTY then
subType:=value.vt - VT_VECTOR
else
subType:=VT_EMPTY;
offs:=0;
case subType of
VT_LPSTR,VT_LPWSTR : len:=sizeof(IntPtr);
VT_VARIANT : len:=SizeOf(TypeOf(TPropVariant));
end;
for I := 0 to nb - 1 do
begin
if subType<>VT_VARIANT then
Data:=IntPtr(integer(value.caub.pElems.ToInt32)+i*sizeof(IntPtr))
else
Data:=IntPtr(value.caub.pElems.ToInt32+i*sizeof(TPropVariant));
if subType<>VT_VARIANT then
begin
newProp.vt:=subType;
newProp.puuid:=marshal.ReadIntPtr(Data);
FValues.AddGood(subType).LoadValue(newProp);
end
else
begin
newProp:=TPropVariant(marshal.PtrToStructure(Data,typeOf(TPropVariant)));
FValues.AddGood(newProp.vt).LoadValue(newprop);
end;
end; |
Et donc je suis obligé de faire des conversions du type IntPtr(....ToInt32+...);
Enfin passons au cas où j'ai un TPropVariant de type VT_CF. Je n'arrive pas à récupérer l'image.
Voilà ce que je fais
Code:
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
|
lpData:=TClipData(marshal.PtrToStructure(value.pclipdata,typeof(TclipData)));
size:=clpData.cbSize;
format:=clpData.ulClipFmt;
Data:=clpData.pClipData;
if format=-1 then
begin
fileFormat:=marshal.ReadInt32(Data);
case fileFormat of
CF_METAFILEPICT :
begin
Data:=IntPtr(Data.ToInt32+sizeof(Int32));
packedMeta:=TPackedMeta(marshal.PtrToStructure(Data,typeOf(TPackedMeta)));
Data:=IntPtr(Integer(Data.ToInt32)+marshal.SizeOf(typeof(TPackedMeta)));
size:=clpData.cbSize-sizeof(clpData.ulClipFmt)-sizeof(DWord)-sizeof(TPackedMeta);
nSizeImage:=4*packedMeta.xExt*packedMeta.yExt;
tpHandle:=SetEnhMetaFileBits(size,Data);
if tpHandle<>0 then
begin
FValue:=TMetafile.create;
TMetaFile(FValue).Handle:=tpHandle;
end
else
RaiseLastOSError;
end;
CF_BITMAP :
begin
FValue:=TBitmap.Create;
end;
end;
end; |
Le problème c'est que j'ai une erreur. raiseLastOsError me retroune que les données ne sont pas valides. Pourtant j'ai suivi les instructions d'un site. Si quelqu'un a un autre exemple pour obtenir l'image associé à un fichier je suis preneur.