Drag&Drop picture from canvas to folder?


how would I drop a picture created in code from a Canvas onto the Desktop (Mac, Win, Linux)?

I looked through all the examples (I think) but they drop&drag into the app or between apps, so that I can do.

But what do I need to do to drop it on the desktop or a folder?

I have the MBS plug-ins, so a solution using those is fine with me.



From the docs:

[quote]Dragging Promised Files
MacOS supports the concept of dragging a file before it actually exists in the file system. It could be a new document that hasn’t been saved yet or a file that exists on a remote server or on the web.

In these cases, the drag and drop gesture serves the purpose of specifying the location at which to save the new file. When the drag and drop operation is complete, it tells the source where it wants the files saved and the dragging source creates the files. This special type of file drag is called a promise because the drag operation contains a promise from the source to the destination that the source will create the specified files if the drag and drop is accepted.

To drag and drop promised files, call the RectControl or Window’s AcceptRawDataDrop method with “phfs”; as the data type. When an application that sends file promises is dropped on your application, you will find a FolderItem in the dragged item. Usually this will point to a file in the TemporaryItems folder and you should ordinarily delete it when you are finished with it.[/quote]

You add a folderitem to the dragitem and then you check the destination.

That is INTO your app, not out of your app.

Check the destination is the trick, isn’t it? How?

I can drag&drop into Mail etc, no problem. But the finder too should be able to accept a drop - but for some reason it doesn’t work.

Though that gives me an idea I might try …

This is working but have to be enhanced:
(in Canvas1.MouseDrag:

[code] // Drag outside this application (to a web browser ?)
Dim ExportDI As DragItem
Dim TmpFI As FolderItem // Added on [2017-01-02]
Dim SQLDate As New Date // Added on [2017-01-02]
Dim SuffixName As String

// Anti crash test
If Me.Backdrop = Nil Then Return

If Self.Focus <> Nil And (Self.Focus.Name = Me.Name) Then
// Clears the Focus
Self.Focus = Nil
// Setthe Focus to … Me !
End If

// To set the file name unique
SuffixName = ReplaceAll(SQLDate.SQLDateTime,":","-") // Added on [2017-01-02]

// Save the image into Temporary
TmpFI = SpecialFolder.Temporary.Child(" - Windows 10 - Icon - " + SuffixName + “.png”) // Added on [2017-01-02], Changed on 2017-07-20

// Save the image in the Temporary Folder (Directory)
Me.Backdrop.Save(TmpFI,Picture.SaveAsPNG) // Added on [2017-01-02]

// Do the Drag
ExportDI = New DragItem(Self, Me.Left, Me.Top, Me.Width, Me.Height)
ExportDI.Picture = Me.Backdrop
ExportDI.DragPicture = Me.Backdrop
ExportDI.FolderItem = TmpFI // Added on [2017-01-02]
ExportDI.Drag // Allow the drag

// [2017-03-04] Clears the DragItem
ExportDI = Nil[/code]

It let a copy in the Temporary folder. At the writing (and revision) time, I was not able to remove that.

Also, I get some weird behaviros (the image is not always created where I release the mouse.

Any taker (for the needed changes) ?

The same method applies for dragging out. And no checking the destination isn’t a trick. Who would try to trick you?

My code is a bit more complex so I can’t post something simple. You do the drag and after dragging you check the destination. If the destination is nil then the drag was aborted.

From the LR:

 If di.Destination <> Nil Then

The problem is… it is always Nil (but .FolderItem is not, breakpoint set before the line ExportDI = Nil).

I am sure Markus would not ask for a clue if the LR example code (in DragItem.Destination) was working.


Thanks Emilie, that helped.

I would presume it is “always” Nil because at that point the destination has already been cleared. And you can’t set a breakpoint during the drag as that stops the drag and therefore you don’t get a destination at all.

Too much honour - I’m having bad hair days too, even though I don’t have hair … :wink:

Figure of speech. In English “that’s the trick” means “It is probably easy if you know how, but it isn’t obvious if you don’t”.

My code that works nicely for saving the background of a canvas (and is better documented than the LR):

[code]Sub MouseDrag(X As Integer, Y As Integer) Handles MouseDrag

// code from the Language Reference modified

// this will drag the background image of a Canvas to any destination
// the lines marked with ** are required for dragging to the finder

Dim tempImageFile As FolderItem //**
Dim d As New Date

//** set up a temporary FolderItem for the image and give it a unique name by using TotalSeconds
tempImageFile = SpecialFolder.Temporary.Child(“image” + Format(d.TotalSeconds, “#”) + “.png”)

//** test if tempImageFile is not Nil
If tempImageFile <> Nil Then

//** save the picture to be dragged in the temporary folderItem 
Me.Backdrop.Save(tempImageFile, Picture.SaveAsPNG)

// create a DragItem for the image 
Dim draggedItem As New DragItem(Self, 0, 0, 100, 100)

// set the little drag image to the backdrop or we'lll drag an empty rectangle 
draggedItem.DragPicture = Me.Backdrop

// if you want to drag the image into another app (like mail) you need to set the image property
draggedItem.Picture = Me.Backdrop

//** set the REAL item to be dragged to the temporary folderItem 
draggedItem.FolderItem = tempImageFile

// "Allows the drag to take place" … probably some behind the scenes communication
// with the system to find out where the item was dropped

//** did we get the destination information?
If draggedItem.Destination <> Nil Then
  //** is it a FolderItem?
  If draggedItem.Destination IsA FolderItem Then
    //** save the image there 
  End If
End If

MsgBox(“Unable to get FolderItem for temporary file.”)
End If
End Sub[/code]

Funny: I just drop to the Finder an image (1536 pixels wide) into the Finder and Firefox set the Drag’ Picture resized down (to something like 200 or 300 pixels wide

In the application where I extract the code far above, I display the image at its real size (the size range from 460 to 1024 pixels wide). That idea never even comes to my mind.

Now I am dubious about what to do: resize down the image for display during the drag to Finder or keep its real size ?

Maybe do it like this:

draggedItem.DragPicture = ScaleImageToCanvas(Me.Background, Me.Width, Me.Height) draggedItem.Picture = Me.Backdrop

You can scale the image with this function

[code]Public Function ScaleImageToCanvas(pic as Picture, maxWidth as Integer, maxHeight as Integer) as Picture

// Scales a Picture while keeping the correct aspect ratio
If pic <> Nil Then

// Calculate the scale ratio
Dim ratio As Double = Min(maxHeight / pic.height, maxWidth / pic.width)

// Create a new picture to return
Dim newPic As New Picture(pic.width * ratio, pic.height * ratio)

// Draw picture in the new size
newPic.graphics.DrawPicture(pic, 0, 0, newPic.width, newPic.height, 0, 0, pic.width, pic.height)

Return newPic

End If
End Function[/code]

so, you will provide a resized image during the drag.

The idea will be to take a width (or height) and resize the image to drag to that size only if the original image is larger than that, else, pass the real image.

That is an idea.

BTW: did you watch the actual time ? (2:28 !)

If you use the actual picture as dragPicture then that might make it difficult to accurately drop the image (it is also not the behaviour users would expect).

The time HERE is 12:40 … lunchtime!

P.S. Just updated my displayed details … (I moved to New Zealand)

Doh ! I do not realized you are down under now ! :wink:

Hey, it’s winter there !

[quote=445416:@Emile Schwarz]Doh ! I do not realized you are down under now ! :wink:
Hey, it’s winter there ![/quote]

Whatever qualifies in Auckland for Winter … :stuck_out_tongue:

Considering that I walk around in Shorts in Germany until it is under -20 degree Celcius it is hell for me here …


I tested your code, Markus (it was not needed…) and I found something I corrected:

the image is drawn from window 0,0. I prefer to get it just below the mouse. To do that, just modify the following line as below:

Dim draggedItem As New DragItem(Self, Me.Left, Me.Top, 100, 100)

Note Me.Left, Me.Top instead of 0, 0.