Фон
Наше приложение на основе Eclipse RCP 3.6 позволяет людям перетаскивать файлы для хранения / обработки.Это прекрасно работает, когда файлы перетаскиваются из файловой системы, но не когда люди перетаскивают элементы (сообщения или вложения) непосредственно из Outlook.
Это происходит потому, что Outlook хочет передать нашему приложению файлы через FileGroupDescriptorW
и FileContents
, но SWT включает только тип FileTransfer
.(В FileTransfer
передаются только пути к файлам, при условии, что получатель может найти и прочитать их. Подход FileGroupDescriptorW
/ FileContents
может передавать файлы непосредственно из приложения в приложение без записи временных файлов вдиск.)
Мы попытались создать подкласс ByteArrayTransfer
, который мог бы принимать FileGroupDescriptorW
и FileContents
.Основываясь на некоторых примерах в Интернете, мы смогли получить и проанализировать FileGroupDescriptorW
, который (как следует из названия) описывает файлы, доступные для передачи.(См. Рисунок кода ниже.) Но мы не смогли принять FileContents
.
. Это происходит потому, что Outlook предлагает данные FileContents
только как TYMED_ISTREAM
или TYMED_ISTORAGE
, но только SWTпонимает, как обмениваться данными как TYMED_HGLOBAL
.Из них представляется, что TYMED_ISTORAGE
будет предпочтительнее, поскольку неясно, как TYMED_ISTREAM
может обеспечить доступ к содержимому нескольких файлов.
(У нас также есть некоторые опасения по поводу желания SWT выбирать и конвертировать толькоодин тип TransferData
, учитывая, что нам нужно обработать два, но мы думаем, что мы могли бы как-то обойти это в Java: кажется, что все TransferData
доступны в других точках процесса.)
Вопросы
Мы на правильном пути?Кому-нибудь уже удалось принять FileContents
в SWT?Есть ли вероятность, что мы сможем обработать данные 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;
}
}
};
В отладчике мы видим, что ByteArrayTransfer
's isSupportedType()
в конечном итоге возвращает false
для FileContents
, потому что следующий тест не пройден (так как его tymed
равен 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
оставляет нас меньшенадеюсь на простое решение:
public static final int TYMED_HGLOBAL = 1;
//public static final int TYMED_ISTORAGE = 8;
//public static final int TYMED_ISTREAM = 4;
Спасибо.