【问题标题】:Drag a .lnk file to the Windows 10 taskbar将 .lnk 文件拖到 Windows 10 任务栏
【发布时间】:2019-05-18 18:33:21
【问题描述】:

如何使用 Java 和 SWT 将 .lnk 文件成功拖到 Windows 10 任务栏(“固定到任务栏”)?我尝试了以下代码(拖动标签的内容),但无论我使用什么操作常量,它都会在 Windows 10 任务栏上显示不允许拖动的光标。

import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class DragTest {

    public static void main(String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
        final Label label = new Label(shell, SWT.BORDER);
        label.setText("Start drag from here");

        final Transfer[] types = new Transfer[] {FileTransfer.getInstance()};
        final int operations = DND.DROP_LINK; // DND.DROP_COPY or DND.DROP_MOVE

        final DragSource source = new DragSource(label, operations);
        source.setTransfer(types);
        source.addListener(DND.DragSetData, 
                           event -> event.data = new String[] { 
                                "C:\\ThunderbirdPortable\\ThunderbirdPortable - Shortcut.lnk"
                           });

        shell.setSize(200, 200);
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();
    }
}

注意,从 Windows 资源管理器中拖动文件可以正常工作,因此文件是正确的。

【问题讨论】:

  • 这里有什么问题?你有什么例外吗?
  • 不,我只是得到一个不允许拖动的光标。我需要进行哪些更改才能使其正常工作?
  • 其他任务栏功能在 SWT 中通过实际调用平台函数实现来实现。例如。任务项的进度动画在 org.eclipse.swt.widgets.TaskItem.setProgress(int) 中。也许您可以在那里挖掘并找到一种无需拖放即可实现此功能的方法。

标签: java windows drag-and-drop swt


【解决方案1】:

11.07.19 更新:当前的夜间构建和 SWT 的下一个版本改进了 FileTransfer 以将文件拖放到 Windows 任务栏上。因此,对于 SWT 4.13+,Thomas 的示例代码无需进一步更改即可工作。

SWT 4.12 及更早版本的解决方法:

目前,SWT 的任何传输类型都不能用于拖放到任务栏上。问题是 FileTransfer 使用 CF_HDROP 作为传输数据类型,而任务栏需要 CFSTR_SHELLIDLIST

另请参阅此类似的chromium bug report 和此SWT bug report

为了显示 SWT 通常可以拖放到任务栏,我修改了您的示例。

import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class DragTransferTest {

    public static void main(String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
        final Label label = new Label(shell, SWT.BORDER);
        label.setText("Drop file here to start");

        final Transfer[] types = new Transfer[] { new ByteArrayTransfer() {

            byte[] lastDrop;

            @Override
            protected Object nativeToJava(TransferData transferData) {
                byte[] data = (byte[]) super.nativeToJava(transferData);
                lastDrop = data;
                return null;
            }

            @Override
            protected void javaToNative(Object object, TransferData transferData) {
                if (lastDrop == null) {
                    DND.error(DND.ERROR_INVALID_DATA);
                }
                super.javaToNative(lastDrop, transferData);
            };

            @Override
            protected String[] getTypeNames() {
                return new String[] { "Shell IDList Array" };
            }

            @Override
            protected int[] getTypeIds() {
                return new int[] { registerType("Shell IDList Array") };
            }
        } };
        final int operations = DND.DROP_LINK | DND.DROP_COPY | DND.DROP_MOVE;

        final DragSource source = new DragSource(label, operations);
        source.setTransfer(types);

        DropTarget target = new DropTarget(label, -1);
        target.setTransfer(types);

        shell.setSize(200, 200);
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();
    }
}

如果您将文件(.lnk 或其他类型)拖放到此示例上,然后从该文件拖动到任务栏,则固定应该可以工作。

所以最后你需要做的“唯一”事情是使用CFSTR_SHELLIDLIST 实现一个新的传输,它将数据作为IDAITEMLISTS 提供。

小更新: 我在 Windows 7 上对此进行了测试,但无论出于何种原因,传输类型 ID 在 Windows 10 上都是另一个。因此,在上面的示例中,您需要将 Windows 7 的 ID 49287 替换为 Windows 10 的 49336。顺便说一句,您可以轻松检查那些带有SWT Snippet 83的ID。

here 所述,获取类型 ID 的正确方法是使用 RegisterClipboardFormat 函数。

【讨论】:

  • 完美答案!
猜你喜欢
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多