Dropping Thunderbird Attachment into Delphi

Home Forums DropMaster Dropping Thunderbird Attachment into Delphi

Viewing 2 reply threads
  • Author
    Posts
    • #3063
      Michael Gross
      Participant

        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ß

      • #3064
        Michael Gross
        Participant

          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.

        • #3065
          DropMaster Support
          Participant

            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.

        Viewing 2 reply threads
        • You must be logged in to reply to this topic.