我可以将项目从Outlook拖到我的SWT应用程序中吗?

Woo*_*III 5 outlook swt drag-and-drop

背景

我们的基于Eclipse RCP 3.6的应用程序允许人们拖动文件进行存储/处理.从文件系统拖动文件时,这种方法很有效,但是当人们直接从Outlook拖动项目(邮件或附件)时则不行.

这似乎是因为Outlook希望通过养活我们的应用程序的文件FileGroupDescriptorWFileContents,但只SWT包括FileTransfer类型.(在FileTransfer,只有文件路径通过,并假设接收器可以找到并阅读.在FileGroupDescriptorW/ FileContents方法,而无需编写临时文件到磁盘可以提供文件直接应用到应用程序.)

我们试图生成一个ByteArrayTransfer可以接受FileGroupDescriptorW和的子类FileContents.基于Web上的一些示例,我们能够接收和解析FileGroupDescriptorW,(顾名思义)描述了可用于传输的文件.(见下面的代码草图.)但我们一直无法接受FileContents.

这似乎是因为Outlook FileContents仅将数据提供为TYMED_ISTREAMTYMED_ISTORAGE,但SWT仅了解如何交换数据TYMED_HGLOBAL.其中,似乎TYMED_ISTORAGE更可取,因为不清楚如何TYMED_ISTREAM提供对多个文件内容的访问.

(我们也有一些担心SWT希望选择和转换只有一种TransferData类型,考虑到我们需要处理两种类型,但我们认为我们可能会以某种方式破解Java:似乎所有TransferDatas都可以在其他点上获得这个过程.)

问题

我们在这里走在正确的轨道上吗?有没有人设法接受FileContentsSWT呢?我们是否有可能在TYMED_ISTORAGE不离开Java的情况下处理数据(即使是通过创建基于片段的补丁或SWT的派生版本),还是我们还需要构建一些新的本机支持代码?

相关代码片段

提取文件名的草图代码:

    // THIS IS NOT PRODUCTION-QUALITY CODE - FOR ILLUSTRATION ONLY
    final Transfer transfer = new ByteArrayTransfer() {
        private final String[] typeNames = new String[] { "FileGroupDescriptorW", "FileContents" };
        private final int[] typeIds = new int[] { registerType(typeNames[0]), registerType(typeNames[1]) };

        @Override
        protected String[] getTypeNames() {
            return typeNames;
        }

        @Override
        protected int[] getTypeIds() {
            return typeIds;
        }

        @Override
        protected Object nativeToJava(TransferData transferData) {
            if (!isSupportedType(transferData))
                return null;

            final byte[] buffer = (byte[]) super.nativeToJava(transferData);
            if (buffer == null)
                return null;

            try {
                final DataInputStream in = new DataInputStream(new ByteArrayInputStream(buffer));

                long count = 0;
                for (int i = 0; i < 4; i++) {
                    count += in.readUnsignedByte() << i;
                }

                for (int i = 0; i < count; i++) {
                    final byte[] filenameBytes = new byte[260 * 2];
                    in.skipBytes(72); // probable architecture assumption(s) - may be wrong outside standard 32-bit Win XP
                    in.read(filenameBytes);
                    final String fileNameIncludingTrailingNulls = new String(filenameBytes, "UTF-16LE");
                    int stringLength = fileNameIncludingTrailingNulls.indexOf('\0');
                    if (stringLength == -1)
                        stringLength = 260;
                    final String fileName = fileNameIncludingTrailingNulls.substring(0, stringLength);
                    System.out.println("File " + i + ": " + fileName);
                }

                in.close();

                return buffer;
            }
            catch (final Exception e) {
                return null;
            }
        }
    };
Run Code Online (Sandbox Code Playgroud)

在调试中,我们看到ByteArrayTransferisSupportedType()最终返回falseFileContents,因为下面的测试不通过(因为它的tymedIS TYMED_ISTREAM | TYMED_ISTORAGE):

    if (format.cfFormat == types[i] &&
        (format.dwAspect & COM.DVASPECT_CONTENT) == COM.DVASPECT_CONTENT && 
        (format.tymed & COM.TYMED_HGLOBAL) == COM.TYMED_HGLOBAL  )
        return true;
Run Code Online (Sandbox Code Playgroud)

这段摘录org.eclipse.swt.internal.ole.win32.COM让我们对一个简单的解决方案感到不那么希望:

public static final int TYMED_HGLOBAL = 1;
//public static final int TYMED_ISTORAGE = 8;
//public static final int TYMED_ISTREAM = 4;
Run Code Online (Sandbox Code Playgroud)

谢谢.

小智 2

您看过https://bugs.eclipse.org/bugs/show_bug.cgi?id=132514吗?

此 bugzilla 条目附带了一个可能令人感兴趣的补丁(针对相当旧的 SWT 版本)。