问题描述
背景
我们基于Eclipse RCP 3.6的应用程序使人们可以拖入文件进行存储/处理.当从文件系统中拖动文件时,这种方法可以很好地工作,但当人们直接从Outlook中拖动项目(消息或附件)时,效果不佳.
Our Eclipse RCP 3.6-based application lets people drag files in for storage/processing. This works fine when the files are dragged from a filesystem, but not when people drag items (messages or attachments) directly from Outlook.
这似乎是因为Outlook希望通过FileGroupDescriptorW
和FileContents
为我们的应用程序提供文件,但是SWT仅包含FileTransfer
类型. (在FileTransfer
中,仅传递文件路径,并假设接收方可以找到并读取它们.FileGroupDescriptorW
/FileContents
方法可以直接在应用程序之间提供文件,而无需将临时文件写出到文件中.磁盘.)
This appears to be because Outlook wants to feed our application the files via a FileGroupDescriptorW
and FileContents
, but SWT only includes a FileTransfer
type. (In a FileTransfer
, only the file paths are passed, with the assumption that the receiver can locate and read them. The FileGroupDescriptorW
/FileContents
approach can supply files directly application-to-application without writing temporary files out to disk.)
我们试图产生一个可以接受FileGroupDescriptorW
和FileContents
的ByteArrayTransfer
子类.根据Web上的一些示例,我们能够接收和解析FileGroupDescriptorW
,该文件(顾名思义)描述了可用于传输的文件. (请参见下面的代码草图.)但是我们无法接受FileContents
.
We have tried to produce a ByteArrayTransfer
subclass that could accept FileGroupDescriptorW
and FileContents
. Based on some examples on the Web, we were able to receive and parse the FileGroupDescriptorW
, which (as the name implies) describes the files available for transfer. (See code sketch below.) But we have been unable to accept the FileContents
.
这似乎是因为Outlook仅以TYMED_ISTREAM
或TYMED_ISTORAGE
的形式提供FileContents
数据,但是SWT仅理解如何以TYMED_HGLOBAL
的形式交换数据.其中,TYMED_ISTORAGE
似乎更可取,因为尚不清楚TYMED_ISTREAM
如何提供对多个文件内容的访问.
This seems to be because Outlook offers the FileContents
data only as TYMED_ISTREAM
or TYMED_ISTORAGE
, but SWT only understands how to exchange data as TYMED_HGLOBAL
. Of those, it appears that TYMED_ISTORAGE
would be preferable, since it's not clear how TYMED_ISTREAM
could provide access to multiple files' contents.
(鉴于我们需要处理两种类型,我们还担心SWT只选择和转换一种TransferData
类型的愿望,但我们认为我们可能会以某种方式在Java中解决: TransferData
在该过程的其他位置可用.)
(We also have some concerns about SWT's desire to pick and convert only a single TransferData
type, given that we need to process two, but we think we could probably hack around that in Java somehow: it seems that all the TransferData
s are available at other points of the process.)
问题
我们在这里正确吗?有没有人设法在SWT中接受FileContents
?是否有可能在不离开Java的情况下处理TYMED_ISTORAGE
数据(即使通过为SWT创建基于片段的补丁程序或SWT的派生版本)还是还是必须构建一些新的本机支持代码?
Are we on the right track here? Has anyone managed to accept FileContents
in SWT yet? Is there any chance that we could process the TYMED_ISTORAGE
data without leaving Java (even if by creating a fragment-based patch to, or a derived version of, SWT), or would we have to build some new native support code too?
相关代码段
提取文件名的素描代码:
Sketch code that extracts file names:
// 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;
}
}
};
在调试器中,我们看到ByteArrayTransfer
的isSupportedType()
最终为FileContents
返回false
,因为未通过以下测试(因为其tymed
为TYMED_ISTREAM | TYMED_ISTORAGE
):
In the debugger, we see that ByteArrayTransfer
's isSupportedType()
ultimately returns false
for the FileContents
because the following test is not passed (since its tymed
is 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;
摘录自org.eclipse.swt.internal.ole.win32.COM
的内容使我们对寻求简单解决方案的希望减少了:
This excerpt from org.eclipse.swt.internal.ole.win32.COM
leaves us feeling less hope for an easy solution:
public static final int TYMED_HGLOBAL = 1;
//public static final int TYMED_ISTORAGE = 8;
//public static final int TYMED_ISTREAM = 4;
谢谢.
推荐答案
您是否看过 https://bugs.eclipse.org/bugs/show_bug.cgi?id=132514 吗?
此bugzilla条目所附的是一个补丁(相对于SWT的较旧版本),可能是您感兴趣的补丁.
Attached to this bugzilla entry is an patch (against an rather old version of SWT) that might be of interest.
这篇关于我可以将项目从Outlook拖到我的SWT应用程序中吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!