Drag a .lnk file to the Windows 10 taskbar

Thomas S. :

How can I drag a .lnk file successfully to the Windows 10 taskbar ("Pin to Taskbar") using Java and SWT? I've tried following code (dragging the label's content), but no matter what operation constant I'm using, it shows the drag-not-allowed cursor over the Windows 10 taskbar.

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();
    }
}

Note, that dragging the file from Windows Explorer works fine, so the file is correct.

Paul Pazderski :

Update 11.07.19: Current nightly builds and the next release of SWT improve FileTransfer to drop files on Windows taskbar. So for SWT 4.13+ Thomas' example code just works without further changes.

Workaround for SWT 4.12 and older:

At the moment none of SWT's Transfer types can be used to drop on the taskbar. The problem is that FileTransfer uses CF_HDROP as transfer data type while the taskbar expects a CFSTR_SHELLIDLIST.

See also this similar chromium bug report and this SWT bug report.

To show that SWT in general could drop to the taskbar I modified your example.

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();
    }
}

If you drop a file (.lnk or other type) onto this example and then drag from it to the taskbar the pinning should works.

So in the end the "only" thing you need to do is implementing a new Transfer with CFSTR_SHELLIDLIST which provides the data as an IDA of ITEMLISTS.

Small update: I tested this on Windows 7 but for whatever reason the transfer type id is another on Windows 10. So in my example above you need to replace the ID 49287 for Windows 7 with 49336 for Windows 10. Btw you can easy inspect those IDs with SWT Snippet 83.

As described here the correct way to get the type ID is using the RegisterClipboardFormat function.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=149143&siteId=1