Home › Forums › DropMaster › Dropping Thunderbird Attachment into Delphi
Tagged: Attachment, Thunderbird
- This topic has 2 replies, 2 voices, and was last updated 2022-05-16 at 8:50 pm by DropMaster Support.
-
AuthorPosts
-
-
May 13, 2022 at 5:04 am #3063
Hello,
I got a problem with Dragging a Mailattachment from Thunderbird (Version 78.13.0, 32-bit) into my application. Outlook works fine and saving the attachment to Desktop and then drag+drop it into my software works, too.
Here is my Source Function. It’s well copied from your samples for Outlook and changed a bit. The error is in red. It seems that there ist no „filecontents“ in Thunderbird. I can’t try this with Thunderbird and read out the object, but perhaps you know mor about Thunderbird and you can give me a hint how to solve this problem or a sample code for Thunderbird I can integrate.
procedure TDlgBMRechnungseingang.DMTextTarget1Drop(Sender: TObject; Acceptor: TWinControl; const DropText: string; X, Y: Integer);
// Handle dropping of files and, in particular, the format in which MS Outlook
// passes e-mail attachments to OLE drag and drop (as file contents on an IStream,
// accompanied by a file group descriptor).
var
hasFGD, hasFileContentsOnIStream, hasFileContentsOnIStorage: boolean;
S, t: AnsiString;
nFiles: DWORD;
aFd: TFileDescriptorA;
j: integer;
anIstream: IStream;
anIStorage: IStorage;
tempFileName, newFileName: String;
FileList:tStringlist;
i:Integer;begin
FileList:=tStringlist.Create;
with (Sender as TDMTextTarget) do
begin
if (DroppedTextFormat = dtfFiles) then
begin
// It’s a plain list of files – do the “usual” thing
FileList.AddStrings(DroppedLines);
end
else
begin
// It’s not simple files, but MS Outlook’s combination of a FileGroupDescriptor
// and FileContents on an IStream. We have to go get the attachments and then
// put them on files ourselves. It appears that Outlook 97 also puts a copy
// of this file in the TEMP directory, but we ignore that here so we can
// demonstrate the principles.// Do we have fgd on HGLobal?
hasFGD := DataObjectHasFormat(‘FileGroupDescriptor’);// Global override for tymed – reset automatically by calls to
// DataObjectHasFormat and DataObjectGetFormat
DataObjectTymed := TYMED_ISTREAM;
// Do we have fc? Do the call first, so we’re guaranteed that it won’t
// be short-circuited, so that the global tymed and lindex get reset properly.
hasFileContentsOnIStream := DataObjectHasFormat(‘FileContents’);// How about on an IStorage? Outlook e-mails as attachments come in this way.
dataobjecttymed := TYMED_ISTORAGE;
hasFileContentsOnIStorage := DataObjectHasFormat(‘FileContents’);if hasFGD and (hasFileContentsOnIStream or hasFileContentsOnIStorage) then
begin
// Get the file group descriptors
s := DataObjectGetFormat(‘FileGroupDescriptor’);
// How many fgd’s in the returned data? That’s a DWORD at the head
// of the string-encoded data
nFiles := DecodeDWORDFromString(s);// Process them all
for j := 1 to nFiles do // Iterate
begin
// Get the j’th file descriptor. It starts after the initial DWORD,
// and has the length of a TFileDescriptor.
System.Move(s[SizeOf(DWORD)+1+(j-1)*SizeOf(TFileDescriptorA)], aFd,
SizeOf(TFileDescriptorA));// Its content is on an IStream, at lindex j-1
// Global overrides for lindex and tymed
DataObjectLindex := j-1;
DataObjectTymed := TYMED_ISTREAM;
t := DataObjectGetFormat(‘FileContents’);// Watch out for nothing at that index…
if (t <> ”) then
begin
// Don’t use “anIStream := IStream(DecodeDWORDFromString(s));” since that
// would add another reference, due to Delphi’s automatic reference handling.
// Alternatively, do it that way, but immediately call anIStream._Release;
TDMNativeUint(anIStream) := DecodeDWORDFromString(t);// Now, we have a singly-referenced Istream interface that we can read from.
// We put it on a file somewhere. For this example, we’re using a
// temporary file name that begins with ‘dmx’ and has the same extension
// as the original and also adding it to the list. Note that
// GetTempFileNameEx also creates the file, so we rename it immediately.
tempFileName := GetTempFileNameEx(‘dmx’);
newFileName := ChangeFileExt(tempFileName, ExtractFileExt(String(aFd.cFileName)));
RenameFile(tempFileName, newFileName);
FileList.Add(SaveIStreamToFile(anIstream, newFileName));// + ‘ (‘ + String(aFD.cFileName) + ‘)’);
end
else
begin
DataObjectLindex := j-1;
DataObjectTymed := TYMED_ISTORAGE;
t := DataObjectGetFormat(‘FileContents’);
if (t <> ”) then
begin
TDMNativeUint(anIStorage) := DecodeDWORDFromString(t);
tempFileName := GetTempFileNameEx(‘dmx’);
newFileName := ChangeFileExt(tempFileName, ExtractFileExt(String(aFd.cFileName)));
RenameFile(tempFileName, newFileName);
FileList.Add(SaveIStorageToFile(anIStorage, newFileName));// + ‘ (‘ + String(aFD.cFileName) + ‘)’);
end
else showmessageex(‘Dropmaster: Could not get interface for ‘ + aFD.cFileName);
end;
end; // for
end; // if hasFormats
end // if (DroppedTextFormat = dtfFiles)
end; // with//Jetzt die Dateiliste durchlaufen und die ZUGFeRD-Dateien importieren
for i:=0 to FileList.count-1 do begin
if comparetext(ExtractFileExt(Filelist[i]),’.PDF’)=0 then begin
ImportZugferdDatei(Filelist[i],Filelist.Count=1);
end;
end;FileList.Free;
end;Greetings
Michael Groß -
May 13, 2022 at 5:09 am #3064
More Info:
The tDMTextTarget is Version 2.5.2, I’m using Delphi 11.
The Acceptorcontrol is a tcxGrid vom Devexpress.
The AcceptTextFormats are dtfFiles and dtfCusom. -
May 16, 2022 at 8:50 pm #3065
We don’t have an example for Thunderbird. However, all of the demos were created using information derived from running the Demos\FormatViewer\FormatViewer.dpr demo. You can build FormatViewer, and then drag your content from Thunderbird onto it; it will then list what data formats and storage medium types are available in the dropped data object. You can use that information to set up a TDMTextTarget with the appropriate configuration. Since drag-and-drop information made available by most applications is undocumented, this is really the only way to proceed.
Hope this helps.
-
-
AuthorPosts
- You must be logged in to reply to this topic.