J
Jake
We have been working on a project to extract multiple image files from the
Outlook clipboard when attachments are copied to it. The project works fine
in
all flavors of Outlook but fails in Outlook 2003 .
I understand this may be due to changes made in Outlook 2003.
The following works with previous Outlook versions but not in 2003:
In The ProcessFileContents procedure, even though the FormatETC structure
has been filled correctly, it still returns an error ... with a HResult <>
0.
What changes are necessary to make it work in Outlook 2003?
Thanks
sample code below......
-----------------------------
....................
var
Form1: TForm1;
CF_FILEGROUPDESCRIPTORA: UINT = 0;
CF_FILEGROUPDESCRIPTORW: UINT = 0;
CF_FILECONTENTS: UINT = 0;
implementation
{$R *.dfm}
procedure TForm1.HandleFiles(dataObj: IDataObject; fetc: TFormatEtc; stgm:
TSTGMedium; DstFile: string);
begin
//get file from a created file stream
end;
procedure TForm1.ProcessFileContents(Obj: IDataObject; Index: UINT;
FileName: string);
var
Fetc: FORMATETC;
Medium: STGMEDIUM;
HR: HRESULT;
FormatName: array[0..128] of Char;
begin
Fetc.cfFormat := CF_FILECONTENTS;
Fetc.ptd := nil;
Fetc.dwAspect := DVASPECT_CONTENT;
Fetc.lindex := Index;
Fetc.tymed := TYMED_HGLOBAL or TYMED_ISTREAM or TYMED_ISTORAGE;
GetClipboardFormatName(FEtc.cfFormat, FormatName, SizeOf(FormatName));
Memo1.Lines.Add('---------------Retrieving file:--------------------');
Memo1.Lines.Add('Format: [' + IntToStr(Fetc.cfFormat)+'], '+
string(FormatName));
Memo1.Lines.Add('PTD: ' + IntToStr(Longint(Fetc.ptd)));
Memo1.Lines.Add('Aspect: ' + IntToStr(Fetc.dwAspect));
Memo1.Lines.Add('Lindex: ' + IntToStr(Fetc.lindex));
Memo1.Lines.Add('Tymed: ' + IntToStr(Fetc.tymed));
Memo1.Lines.Add('---------------------------------------------------');
HR := Obj.GetData(Fetc, Medium);
Memo1.Lines.Add('HR = [' + IntToStr(HR)+'], '+DSUtil.GetErrorString(HR));
if SUCCEEDED(HR) then
begin
case Medium.tymed of
TYMED_HGLOBAL: // use Medium.hGlobal as needed ...
Memo1.Lines.Add('TYMED_HGLOBAL');
TYMED_ISTREAM:
begin
Memo1.Lines.Add('TYMED_ISTREAM');
HandleFiles(Obj, FEtc, Medium, Edit1.Text + FileName);
end;
TYMED_ISTORAGE :
begin
Memo1.Lines.Add('TYMED_ISTORAGE');
end;
end;
ReleaseStgMedium(Medium);
end else
Memo1.Lines.Add('Failed');
end;
procedure TForm1.Button2Click(Sender: TObject);
var
DataObj : IDataObject;
Fetc: FORMATETC;
Medium: STGMEDIUM;
Enum: IEnumFORMATETC;
Group: Pointer;
S: string;
FormatName: array[0..128] of char;
I: UINT;
FileNameA: AnsiString;
FileNameW: WideString;
HR: HResult;
begin
memo1.Clear;
if (OleGetClipboard(DataObj) <> S_OK) then Exit;
if DataObj = nil then exit;
if FAILED(DataObj.EnumFormatEtc(DATADIR_GET, Enum)) then Exit;
while Enum.Next(1, Fetc, nil) = S_OK do
begin
S := StringFromClipboardFormat(fetc.cfFormat);
GetClipboardFormatName(FEtc.cfFormat, FormatName, SizeOf(FormatName));
Memo1.Lines.Add('[Clipboard Format: ' + S + ' ]');
Memo1.Lines.Add('[Format: ' + FormatName + ', ' +
IntToStr(Fetc.cfFormat) + ' ]');
Memo1.Lines.Add('[Aspect: ' + IntToStr(Fetc.dwAspect) + ' ]');
Memo1.Lines.Add('[Lindex: ' + IntToStr(Fetc.lindex) + ' ]');
Memo1.Lines.Add('[Tymed: ' + IntToStr(Fetc.tymed) + ' ]');
if (S = 'FileGroupDescriptor') or
(Fetc.cfFormat in [CF_FILEGROUPDESCRIPTORA, CF_FILEGROUPDESCRIPTORW])
then
begin
Showmessage('workin');
HR := DataObj.GetData(Fetc, Medium);
Memo1.Lines.Add('[ HResult =
'+inttostr(HR)+DSUtil.GetErrorString(HR)+'] ');
if Failed(HR) then Exit;
case Medium.tymed of
TYMED_HGLOBAL :
begin
Memo1.Lines.Add('[ Using Tymed_HGLOBAL ]');
Group := GlobalLock(Medium.hGlobal);
try
if FEtc.cfFormat = CF_FILEGROUPDESCRIPTORW then
begin
for I := 0 to PFileGroupDescriptorW(Group)^.cItems-1 do
begin
FileNameW := PFileGroupDescriptorW(Group)^.fgd.cFileName;
Memo1.Lines.Add('filenameW : ' + Filenamew);
ProcessFileContents(DataObj, I, FilenameW);
end;
end else
begin
for I := 0 to PFileGroupDescriptorA(Group)^.cItems-1 do
begin
FileNameA := PFileGroupDescriptorA(Group)^.fgd.cFileName;
memo1.Lines.Add('filenameA : ' + FileNameA);
ProcessFileContents(DataObj, I, FileNameA);
end;
end;
finally
GlobalUnlock(Medium.hGlobal);
end;
end; //tymed_hglobal
TYMED_ISTREAM :
Memo1.Lines.Add('[ Using Tymed_ISTREAM ]');
TYMED_ISTORAGE :
Memo1.Lines.Add('[ Using Tymed_ISTORAGE ]')
end;
ReleaseStgMedium(Medium);
end;
end;
end;
initialization
CF_FILEGROUPDESCRIPTORA := RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA);
CF_FILEGROUPDESCRIPTORW := RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
CF_FILECONTENTS := RegisterClipboardFormat(CFSTR_FILECONTENTS);
end.
-------------------------------------------------------------
RESULT
-------------------------------------------------------------
[Clipboard Format: DataObject ]
[Format: DataObject, 49161 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: FileGroupDescriptor ]
[Format: FileGroupDescriptor, 49331 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[ HResult = 0The operation completed successfully. ]
[ Using Tymed_HGLOBAL ]
filenameA : IMGP2151.jpg
---------------Retrieving file:--------------------
Format: [49330], FileContents
PTD: 0
Aspect: 1
Lindex: 0
Tymed: 13
---------------------------------------------------
HR = [-2147221404], Invalid FORMATETC structure
Failed
filenameA : IMGP2164.jpg
---------------Retrieving file:--------------------
Format: [49330], FileContents
PTD: 0
Aspect: 1
Lindex: 1
Tymed: 13
---------------------------------------------------
HR = [-2147221404], Invalid FORMATETC structure
Failed
filenameA : IMGP2144.jpg
---------------Retrieving file:--------------------
Format: [49330], FileContents
PTD: 0
Aspect: 1
Lindex: 2
Tymed: 13
---------------------------------------------------
HR = [-2147221404], Invalid FORMATETC structure
Failed
[Clipboard Format: RenPrivateFileAttachments ]
[Format: RenPrivateFileAttachments, 49730 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: FileContents ]
[Format: FileContents, 49330 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: CF_TEXT ]
[Format: FileContents, 1 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: CF_UNICODETEXT ]
[Format: FileContents, 13 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: Ole Private Data ]
[Format: Ole Private Data, 49171 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: CF_LOCALE ]
[Format: Ole Private Data, 16 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: CF_OEMTEXT ]
[Format: Ole Private Data, 7 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
Outlook clipboard when attachments are copied to it. The project works fine
in
all flavors of Outlook but fails in Outlook 2003 .
I understand this may be due to changes made in Outlook 2003.
The following works with previous Outlook versions but not in 2003:
In The ProcessFileContents procedure, even though the FormatETC structure
has been filled correctly, it still returns an error ... with a HResult <>
0.
What changes are necessary to make it work in Outlook 2003?
Thanks
sample code below......
-----------------------------
....................
var
Form1: TForm1;
CF_FILEGROUPDESCRIPTORA: UINT = 0;
CF_FILEGROUPDESCRIPTORW: UINT = 0;
CF_FILECONTENTS: UINT = 0;
implementation
{$R *.dfm}
procedure TForm1.HandleFiles(dataObj: IDataObject; fetc: TFormatEtc; stgm:
TSTGMedium; DstFile: string);
begin
//get file from a created file stream
end;
procedure TForm1.ProcessFileContents(Obj: IDataObject; Index: UINT;
FileName: string);
var
Fetc: FORMATETC;
Medium: STGMEDIUM;
HR: HRESULT;
FormatName: array[0..128] of Char;
begin
Fetc.cfFormat := CF_FILECONTENTS;
Fetc.ptd := nil;
Fetc.dwAspect := DVASPECT_CONTENT;
Fetc.lindex := Index;
Fetc.tymed := TYMED_HGLOBAL or TYMED_ISTREAM or TYMED_ISTORAGE;
GetClipboardFormatName(FEtc.cfFormat, FormatName, SizeOf(FormatName));
Memo1.Lines.Add('---------------Retrieving file:--------------------');
Memo1.Lines.Add('Format: [' + IntToStr(Fetc.cfFormat)+'], '+
string(FormatName));
Memo1.Lines.Add('PTD: ' + IntToStr(Longint(Fetc.ptd)));
Memo1.Lines.Add('Aspect: ' + IntToStr(Fetc.dwAspect));
Memo1.Lines.Add('Lindex: ' + IntToStr(Fetc.lindex));
Memo1.Lines.Add('Tymed: ' + IntToStr(Fetc.tymed));
Memo1.Lines.Add('---------------------------------------------------');
HR := Obj.GetData(Fetc, Medium);
Memo1.Lines.Add('HR = [' + IntToStr(HR)+'], '+DSUtil.GetErrorString(HR));
if SUCCEEDED(HR) then
begin
case Medium.tymed of
TYMED_HGLOBAL: // use Medium.hGlobal as needed ...
Memo1.Lines.Add('TYMED_HGLOBAL');
TYMED_ISTREAM:
begin
Memo1.Lines.Add('TYMED_ISTREAM');
HandleFiles(Obj, FEtc, Medium, Edit1.Text + FileName);
end;
TYMED_ISTORAGE :
begin
Memo1.Lines.Add('TYMED_ISTORAGE');
end;
end;
ReleaseStgMedium(Medium);
end else
Memo1.Lines.Add('Failed');
end;
procedure TForm1.Button2Click(Sender: TObject);
var
DataObj : IDataObject;
Fetc: FORMATETC;
Medium: STGMEDIUM;
Enum: IEnumFORMATETC;
Group: Pointer;
S: string;
FormatName: array[0..128] of char;
I: UINT;
FileNameA: AnsiString;
FileNameW: WideString;
HR: HResult;
begin
memo1.Clear;
if (OleGetClipboard(DataObj) <> S_OK) then Exit;
if DataObj = nil then exit;
if FAILED(DataObj.EnumFormatEtc(DATADIR_GET, Enum)) then Exit;
while Enum.Next(1, Fetc, nil) = S_OK do
begin
S := StringFromClipboardFormat(fetc.cfFormat);
GetClipboardFormatName(FEtc.cfFormat, FormatName, SizeOf(FormatName));
Memo1.Lines.Add('[Clipboard Format: ' + S + ' ]');
Memo1.Lines.Add('[Format: ' + FormatName + ', ' +
IntToStr(Fetc.cfFormat) + ' ]');
Memo1.Lines.Add('[Aspect: ' + IntToStr(Fetc.dwAspect) + ' ]');
Memo1.Lines.Add('[Lindex: ' + IntToStr(Fetc.lindex) + ' ]');
Memo1.Lines.Add('[Tymed: ' + IntToStr(Fetc.tymed) + ' ]');
if (S = 'FileGroupDescriptor') or
(Fetc.cfFormat in [CF_FILEGROUPDESCRIPTORA, CF_FILEGROUPDESCRIPTORW])
then
begin
Showmessage('workin');
HR := DataObj.GetData(Fetc, Medium);
Memo1.Lines.Add('[ HResult =
'+inttostr(HR)+DSUtil.GetErrorString(HR)+'] ');
if Failed(HR) then Exit;
case Medium.tymed of
TYMED_HGLOBAL :
begin
Memo1.Lines.Add('[ Using Tymed_HGLOBAL ]');
Group := GlobalLock(Medium.hGlobal);
try
if FEtc.cfFormat = CF_FILEGROUPDESCRIPTORW then
begin
for I := 0 to PFileGroupDescriptorW(Group)^.cItems-1 do
begin
FileNameW := PFileGroupDescriptorW(Group)^.fgd.cFileName;
Memo1.Lines.Add('filenameW : ' + Filenamew);
ProcessFileContents(DataObj, I, FilenameW);
end;
end else
begin
for I := 0 to PFileGroupDescriptorA(Group)^.cItems-1 do
begin
FileNameA := PFileGroupDescriptorA(Group)^.fgd.cFileName;
memo1.Lines.Add('filenameA : ' + FileNameA);
ProcessFileContents(DataObj, I, FileNameA);
end;
end;
finally
GlobalUnlock(Medium.hGlobal);
end;
end; //tymed_hglobal
TYMED_ISTREAM :
Memo1.Lines.Add('[ Using Tymed_ISTREAM ]');
TYMED_ISTORAGE :
Memo1.Lines.Add('[ Using Tymed_ISTORAGE ]')
end;
ReleaseStgMedium(Medium);
end;
end;
end;
initialization
CF_FILEGROUPDESCRIPTORA := RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA);
CF_FILEGROUPDESCRIPTORW := RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
CF_FILECONTENTS := RegisterClipboardFormat(CFSTR_FILECONTENTS);
end.
-------------------------------------------------------------
RESULT
-------------------------------------------------------------
[Clipboard Format: DataObject ]
[Format: DataObject, 49161 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: FileGroupDescriptor ]
[Format: FileGroupDescriptor, 49331 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[ HResult = 0The operation completed successfully. ]
[ Using Tymed_HGLOBAL ]
filenameA : IMGP2151.jpg
---------------Retrieving file:--------------------
Format: [49330], FileContents
PTD: 0
Aspect: 1
Lindex: 0
Tymed: 13
---------------------------------------------------
HR = [-2147221404], Invalid FORMATETC structure
Failed
filenameA : IMGP2164.jpg
---------------Retrieving file:--------------------
Format: [49330], FileContents
PTD: 0
Aspect: 1
Lindex: 1
Tymed: 13
---------------------------------------------------
HR = [-2147221404], Invalid FORMATETC structure
Failed
filenameA : IMGP2144.jpg
---------------Retrieving file:--------------------
Format: [49330], FileContents
PTD: 0
Aspect: 1
Lindex: 2
Tymed: 13
---------------------------------------------------
HR = [-2147221404], Invalid FORMATETC structure
Failed
[Clipboard Format: RenPrivateFileAttachments ]
[Format: RenPrivateFileAttachments, 49730 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: FileContents ]
[Format: FileContents, 49330 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: CF_TEXT ]
[Format: FileContents, 1 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: CF_UNICODETEXT ]
[Format: FileContents, 13 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: Ole Private Data ]
[Format: Ole Private Data, 49171 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: CF_LOCALE ]
[Format: Ole Private Data, 16 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]
[Clipboard Format: CF_OEMTEXT ]
[Format: Ole Private Data, 7 ]
[Aspect: 1 ]
[Lindex: -1 ]
[Tymed: 5 ]