There is nothing wrong with your television set. Do not attempt to adjust the picture.
Status
Latest version: 5.2
Released: 17 aug 2010
Download
The Drag and Drop Component Suite is a freeware VCL component library that enables your Delphi and C++Builder applications to support COM based drag and drop and integrate with the Windows clipboard.
The drag and drop system that is built into the VCL, is limited in that it only supports drag and drop within the same application. If you need to drag data from your application to other applications (e.g. Word, Explorer or Outlook), or if you need to be able to accept data dropped from other application (e.g. the Explorer), you have to use COM based drag and drop. COM based drag and drop is an integral and very important part of the Windows user interface and the Drag and Drop Component Suite makes it very easy to leverage all the features of COM based drag and drop in your own Delphi and C++Builder applications.
Every drag and drop operation involves two objects: A drop source and a drop target. The drop source provides the data to be dragged, and the drop target accepts the dragged data.
Likewise there are basically two sets of components in the Drag and Drop Component Suite; Drop source components and drop target components. Most of the source and target components are specialized to handle just one type of data, but a few of the components supports a wider range of data types or are completely generic.
In addition to the drag and drop components, the Drag and Drop Component Suite also includes components that can be used to build Windows Shell Extensions. While these components aren’t all related to Drag and Drop, they benefit from the Drag and Drop Component Suite framework and allow you to write Windows Shell Extensions with very little code. But most important; I had a lot of fun writing them :-).
IDropSource
, IDropTarget
, IDataObject
and IAsyncOperation
interfaces.The Drag and Drop Component Suite contains the following components:
Drop Sources | Drop Targets | |
---|---|---|
|
|
Shell Extensions | Additional |
|
---|---|---|
|
|
This work is licensed under a
Creative Commons Attribution-Share Alike 3.0 Unported License.
The library has been tested with the following versions of Delphi:
D1 | D2 | D3 | D4 | D5 | D6 | D7 | D2005 | D2006 | D2007 | D2009 | D2010 |
If you can confirm compatibility with any of the untested versions of Delphi (or C++ Builder for that matter), please let me know and I will update the table.
I have done absolutely no testing with C++ Builder so I don’t know if the code works with it or not. That said, according to feedback I have received, the current release should work with C++ Builder.
Download: | The Drag and Drop Component Suite v5.2 |
---|---|
Version: | 5.2 |
Updated: | 17 August, 2010 |
Size: | 505.61 KB |
Notes: | Includes component source and demo applications. |
Downloads: | 38,845 |
Old versions can be found on the downloads page.
Packages
folder, find the design time package that matches your version of Delphi. Open it in Delphi, Compile and Install.Library
sub-folder that matches your version of Delphi. Add it to the Delphi library search path.Source
folder to the Delphi browsing path.Drag and Drop Component Suite
design time package.Library
folder from the Delphi library search path.Source
folder from the Delphi browsing path.Changes since version 4.2:
TRawClipboardFormat
.TRawClipboardFormat
that caused it to stop functioning after first use.TDropContextMenu
now properly supports nested context menus.DragDetectPlus
has been improved to make it possible to use it with popup menus and TTreeView
:
TCustomDropTarget.Enabled
has been improved.AutoScroll
feature
ResetScrollZone
method.ResetScrollZone
in both DragEnter
and DragOver
. DragOver
will not call ResetScrollZone
if a custom scroll zone has been specified through the NoScrollZone
property thus if the user specifies a custom scroll zone in OnDragEnter
then the scroll zone will not be automatically reset in DragOver
.TOutlookDataFormat
and TStorageDataFormat
has been improved based on user feedback.TFileContentsStreamClipboardFormat
and TFileContentsStorageClipboardFormat
now handles both Ansi and Unicode data. Among other things this fixes problems with Outlook drop targets.TRawClipboardFormat.CopyFromStgMedium
and CopyToStgMedium
methods are now functions that return a boolean. The return values indicates if the method was able to perform the requested operation.TDropFileSource.Files
and MappedNames
properties are no longer published. They are now public properties.MakeRTF
function in the DragDropText
unit failed to compile with some versions of Delphi.DragDetectPlus
no longer eats right-click mouse messages.OnGetData
event) instead of when the data is dropped (OnDrop
event). This change was made to handle application that require the files to be physically present when ever they query the drop source for the file names.TListView
’s internal mouse message handling makes it impossible to handle right-click correctly.TCustomDropTarget.Enabled
property.TMessages
class (used for Outlook drag/drop) now support sessions. This can be (and is) used to work around the various quirks in Outlook’s interface reference counting mechanism.TAnsiStringClipboardFormat.GetClipboardFormat
has been implemented.TCustomDropTarget.PasteFromClipboard
no longer clears the data after the OnDrop event has fired.TClipboardFormat.GetData
that caused drop targets to reject data after first drop.TTextDataFormat
that mainly affected TDropTextTarget
.TDropComboTarget.OptimizedMove
and TDropFileTarget.OptimizedMove
is now declared correctly.TStrings
but is Assign
/AssignTo
compatible with it.TWideStringList
for Unicode support, now use the new TUnicodeStringList
instead.DragDetectPlus
function now leave mouse click messages (WM_xBUTTONDOWN
, WM_xBUTTONUP
, etc) in the message queue.MakeRTF
utility function now support Unicode strings and generate proper RTF formatted text.TRichTextClipboardFormat class
).TCustomDropSource.OnGetDragImage
event added.TFileGroupDescriptor*ClipboardFormat
, TFileContents*ClipboardFormat
and TVirtualFileStreamDataFormat
classes has been moved to the DragDropFile unit.T*TextClipboardFormat
classes has been moved to the DragDropText unit.CreateIStreamFromIStorage
and CreateIStorageOnHGlobal
which primarily affected drag/drop from Outlook.TFileGroupDescriptorCustomClipboardFormat
.TFilenameClipboardFormat
has been renamed TAnsiFilenameClipboardFormat
.TFilenameWClipboardFormat
has been renamed TUnicodeFilenameClipboardFormat
.TFilenameClipboardFormat
is now an alias for the native (ansi or unicode) format.TFilenameMapClipboardFormat
has been renamed TAnsiFilenameMapClipboardFormat
.TFilenameMapWClipboardFormat
has been renamed TUnicodeFilenameMapClipboardFormat
.TFilenameMapClipboardFormat
is now an alias for the native (ansi or unicode) format.TFileGroupDescriptorClipboardFormat
has been renamed TAnsiFileGroupDescriptorClipboardFormat
.TFileGroupDescriptorWClipboardFormat
has been renamed TUnicodeFileGroupDescriptorClipboardFormat
.TFileGroupDescriptorClipboardFormat
is now an alias for the native (ansi or unicode) format.TTextClipboardFormat
has been renamed TAnsiTextClipboardFormat
TCustomTextClipboardFormat
has been renamed TCustomAnsiTextClipboardFormat
TCustomWideTextClipboardFormat
has been renamed TCustomUnicodeTextClipboardFormat
TTextClipboardFormat
is now an alias for the native (ansi or unicode) format.TDropTextTarget
, TDropTextSource
and TTextDataFormat
now keeps string data data in the source format and only converts between unicode and ansi on demand.Text
property of TDropTextTarget
, TDropTextSource
and TTextDataFormat
is now named AnsiText
.Text
property of TDropTextTarget
, TDropTextSource
and TTextDataFormat
now returns the native string format.RichText
, OEMText
, CSVText
and HTML
properties of the TDropTextTarget
, TDropTextSource
and TTextDataFormat
classes are no longer supported and have been removed.TDropContextMenu
component.TDropContextMenu.OnPrepareMenu
event.TDropContextMenu.FolderPIDL
and TDropContextMenu.Folder
properties.TDragDropHandler.GetFolderPIDL
function has been replaced with the FolderPIDL
property.TURLClipboardFormat
has been renamed TAnsiURLClipboardFormat
TURLWClipboardFormat
has been renamed TUnicodeURLClipboardFormat
TURLClipboardFormat
is now an alias for the native (ansi or unicode) format.Title
property of TDropURLTarget
, TDropURLSource
and TURLDataFormat
is now a Unicode string.const
directive to interface parameters.TFileGroupDescriptorCustomClipboardFormat
as common ancestor for TFileGroupDescriptorClipboardFormat
and TFileGroupDescriptorWClipboardFormat
.In short, you can’t.
You must understand that the drag/drop API works the same for all applications that uses it, and the Explorer is just like any other application. The drag/drop API provides a framework that facilitates the interaction between a drop source and the target, but since the drop target can do anything it wants with the data it receives, there is no way to communicate the destiny of the data back to the drop source in a uniform way.
One target may chose to display the dropped data (e.g. notepad), another one to upload it to a web server (e.g. a FTP client), a third to move and rename the file (e.g. the Recycle Bin) and a fourth may chose to copy or move the file (e.g. Explorer).
In my experience there is never any real need to know the destination of a drop to the Explorer. If you find that you do need this, you should rethink your solution. - and feel free to ask for help.
AllowAsyncTransfer
property and the Execute
methods’ Asynchronous
parameter?The Execute
methods Asynchronous
parameter specifies if the source should perform the transfer in a thread.
The AllowAsyncTransfer
property specifies if the drop target is allowed to perform an asynchronous transfer.
The two are completely independent. One does not have priority over the other.
Asynchronous transfer on the source side is an “invention” of mine. It can be done even if the drop target doesn’t support, and thus doesn’t take an active part in, asynchronous transfer.
Asynchronous transfer on the target side is a COM drag/drop feature (see IAsyncOperation
in MSDN). It requires that both the source and the target support asynchronous transfer. All the Drag and Drop Component Suite components support asynchronous transfer, but apart from Windows Explorer few applications has implemented the feature.
An optimized move is simply a move operation where the drop target moves the data from the source to the destination location.
In a conventional move operation, the source and the target must cooperate in order to complete the operation. First the target makes a copy of the data at the desired location. Then, when the target has completed copying the data, it hands control back to the source who then deletes the original data. This procedure can be very inefficient because it requires two simultaneous copies of the data.
With an optimized move, the target handles the entire move operation and signals the source that an optimized move took place upon completion.
The Drag and Drop Component Suite supports Optimized Move on both the source and target side.
When migrating from pre-5.0 releases, are there any guidelines? Code that needs to be changed, "gotchas" to look out for, etc.
Thanks.
It depends…
If you are using custom drop target or drop source classes, or using the data- and clipboard format classes directly, then things have changed quite a lot. Many classes have been renamed and reimplemented.
If you are just using the standard components then you should be good to go. I have made a great effort to maintain high level backward compatibility.
One thing to look out for is that
TDropFileTarget.Files
andTDropFileSource.Files
is now a custom string list which doesn't descend fromTStrings
. This will not be a problem in most cases and the compiler will catch it for you if it is. I.e. if it compiles, then it works.When attempting to compile/install the D-and-D Component Suite 5 in D5 I get two errors:
"Cannot find the resource file …DragDropD5.res. Recreated" (which is a minor problem…)
and a fatal error: "Could not create output file …\DropSource.dcu".
The package fails to install.
Is there a problem somewhere?
The missing
.res
file is normal. Since the.res
file will be recreated by Delphi when you open the package, I decided not to include it in the zip file this time. The same goes for the.proj
and.group_proj
files used by D2005 and later.The "Cannot create out file…" error is likely caused by a missing folder. The zip file contains a number of empty folders under the
DragDrop\Library
folder. When you unzipped the file these folders should have been recreated even though they are empty. I known that WinZip, 7-zip and WinRar supports this - did you use something else?The Delphi 5 package outputs the binary files (
.dcu
,.bpl
,.dcp
) in theDragDrop\Library\Delphi 5
folder. Try creating that folder and recompile the package.Yes, as you said. Now it installs OK. Many thanks!
great work! would you consider about creating an online svn/cvs repository?
The source currently lives in a StarTeam repository on a SAN hosted by a cluster situated in a nuclear proof bunker. The only downside is that I can only access it through VPN.
It would be nice if I could give the public access to the source, or move the source to a public repository, but I'm afraid there's nothing "in it for me" - only more work.
Excelent component! I'll be using it from now on..
P.S. A lot of demo apps are raising weird exceptions at startup. Please, have a look. I'm using Delphi 7 on Windows 2003 Server R2..
The DropTarget component is working easy and nice as it's supposed to.
Congratulations for your great work!
That is because the forms has been opened (by me) with a newer version of Delphi than the one you are using. It's a quite common problem when working with multiple versions of Delphi.
To resolve the problem just open the forms and save them and then recompile.
Just downloaded and tested some of your demos. In the file source demo I can drag files FROM my application into any Windows Explorer window, except on the desktop. Why? Isn't the windows desktop just another instance of explorer.exe?
What am I missing?
It's a bug.
One of the classes that converts between filenames and PIDLs has a problem that prevents the "Link" drop kind from working.
I have already fixed it internally and will post a new version ASAP.
Regarding the SourceDemo
Can the following two kinds of drag'n'drop co-exisit:
1. Drag the ListView items to other applications, eg Explorer (this is a behavior of the SourceDemo)
2. If the user drag'n'drop the ListView items within the ListView, I want the items to be re-sorted.
Please advise. Thank you.
That's actually quite easy:
TDropFileTarget
component to turn the listview into a drop target.TListView.OnMouseDown
handler). Clear the flag whenTDropFileSource.Execute
returns.TDropFileTarget.OnEnter
handler reject the drop unless the flag has been set.TDropFileTarget.OnDrop
handler move the currently selected listview items to the drop location. You can useTListView.GetItemAt
to find the drop location.See also: Rearrange Multiple TListView Items using Drag and Drop.
Thanks for your components it is a wonderful gift To the community but..
it fails to compile so does not install.
[DCC Error] DragDropText.pas(325): E2011 Low bound exceeds high bound
I hope you can fix it soon .
Merry Christmas - Peace
Philippe Watel
Which version of Delphi are you using?
Hello. I trying to make drag&drop images from browser to my program.
using DropComboTarget.
With Firefox it works fine. I get Bitmap and working with it, but with IE and Chrome i got only Text and Url when drop image. I tried to look at Source Analyzer Demo: when i drop image from
Chrome i got "filecontents" and this is content of dropped image, but in DropComboTarget i got only Text & Url … (sorry if my English was bad, hope u understand me )
As far as I can tell this is caused by a bug in IE8 (as far as I remember it used to work in previous versions of IE): IE does offer the FileContents clipboard format, but fails to actually fill it with any data. The Drop Source Analyzer indicates this by drawing the medium (GlobalMem) in red.
If you are seeing something different please state your version of IE and mail me the data format list (select Save list… from the toolbar) from the Source Analyzer.
Further tests show that IE8 can drag images, but only if the image isn't wrapped in an A tag (i.e. a link). I'm afraid there's nothing I can do about this strange behavior.
hi
delphi 2010 but i tried with 2009 and it was the same
bye
PW
I'm afraid I can't reproduce your problem with either D2009 or D2010 but try rewriting the case statement like this:
We have same error happened as
[DCC Error] DragDropText.pas(325): E2011 Low bound exceeds high bound
. But It's OK now after modify those code from you.Thanks for the feedback.
Although I still cannot reproduce the error I have now applied the change to my source so the problem doesn't reappear.
Hello!
Delphi 2009, component
TDropFileSource
.In popup menu:
It's a known problem.
I will see if I can find time to upload a new version this week.
This works beautifully in Delphi 6 but …
I had a lot of trouble getting this to install. I am now having to reinstall my system after a crash and so far have not been able to pesuade Delphi to compile D & D again (yes the folder does exist per above comment by David).
Thank you for this package. I appreciate the work put into its creation as I was part way through trying to work this out myself when I found your components.
What error are you getting from the compiler?
Thank you for the reply. The error message is
Could not create output file …\DropSource.dcu
On a hunch I tried adding the contents of the source folder to
Delphi6\Lib
and placingDragDropD6.dpk
in the same folder, double clicked onDragDropD6.dpk
and it installed.Hope this helps Paul
I just checked the Delphi 6 package files and it appears that they were not configured correctly.
With the files back in their original locations try editing the package source files in notepad:
DragDropD6.dof
change the[Directories]
section:DragDropD6.dpk
update the path to the source files:The
DragDropD2006.dpk
andDragDropD2007.dpk
files also needs to have their{$R}
directives adjusted.Thank you for the help.
Hello,
I have an application which will get all the email addresses in the server, and put them in the listview. Now I want this email addresses could be dragged from my listview to contacts in Outlook 2007.
could this be possible?
thanks and best regards
Yes it is possible.
There are two ways to do it:
Use the
TDropFileSource
component to drag a vCard file. See the VirtualFile demo for an example of how to drag an in-memory vCard.See the Outlook source demo for an example of how to drag Outlook items back into Outlook. The hard part with this solution is the construction of the Outlook contact COM object and I'm afraid I cannot provide any help beyond what the demo provides.
The vCard approach is by far the easiest and I recommend that you use it if possible. You can easily test it with the VirtualFile demo.
WRT messing with Outlook Contact objects I just remembered this old comment.
Hello. My program is using Version 4 of the toolkit, and, based on ExtractDemo, I've been working on having it allow the user to drag a .WAV file within the program onto a target location, including other apps that accept .WAV files dropped onto them.
My program renders the file at the time the file dropped to the target location, when
DropFileSource1Drop
is executed by my program. This works fine for some apps, however, in testing, there are reports that it doesn't work for some apps. One target app that I tested appears to require a fully-formed valid file to be present on disk at the time the mouse cursor is moved over it, otherwise the mouse cursor stays at "no drop allowed" cursor. Windows Media Player had a similar problem, in that it required a file with the target name to be present on disk, but I was able to get my program to drop into WMP by creating a small dummy file with the target file name, beforeDropFileSource1.Files.Add
andDropFileSource1.Execute
are called. Then, when theDropFileSource1Drop
method is executed to do the actual drop, my program just erases the dummy file and re-creates it and WMP received it.The problem: Unlike Windows Media Player, this other program requires the dummy .WAV file to be a VALID .WAV in order for the mouse cursor to indicate the program will accept the file, but if I try erase the file and then recreate it during
DropFileSource1Drop
, or if I have my program attempt to open the existing file and add to it, then it won't work because the other program (or windows) has taken control of the file and blocked my app from accessing it or erasing it.Wondering if there is any solution to this problem? How can I prevent the target app from taking control of the file before the
DropFileSource1Drop
is executed? Also I am curious how the target app even knows the name of the file when the mouse cursor is hovering over the app, but beforeDropFileSource1Drop
is executed?Thanks,
Jeff
The drop target can query the drop target about the data being dragged at any time during the drag operation. It does so using the
IDataObject
that is passed to it whenIDropTarget.DragEnter
is called.The solution to your problem is to create the source files if, and when, the target reads the file names from the drop source source's data object. Fortunately this is very easy: All you have to do is move the creation of the files from the
OnDrop
handler to theOnGetData
event handler.There are a few things you need to be aware of though:
OnGetData
event is fired each time the drop target callsIDataObject.GetData
.IDataObject.GetData
many times during a drag operation. Each call will fire theOnGetData
event.IDataObject.GetData
does not mean that it will eventually accept the drop.The following changes implement the above in the ExtractDemo application:
I hope this makes sense.
Makes sense. Thanks.
Hi! I've found your components tonight and am amazed. Thanks for the massive amount of work. However, I have to issues trying to simulate file-Drag&Drop from my application to a foreign target application that does not accept data from remote otherwise:
1. Is it possible at all to programatically drag and drop files to the target without moving the mouse cursor to the target "in real-time" with SetCursorPos?
2. The target seems to accept drops from Windows Explorer only. What is so special about Explorer that it can be identified by the target? How can I mimic Explorer's behaviour? Tomorrow, I will use your Source and Target analyzers to find out differences between my DataObjects and those of Explorer. Anyway, if you have an idea, any help is appreciated.
During a drag from Explorer it will most often be the active process. It is however possible to change the active process during a drag with Alt+Tab or by hovering over the task bar.
The target components does supply the InShellDragLoop format automatically but not the Shell Object Offsets format.
Hello, i just tried this one with D2005, using the include path to the source. I took that TargetDemo of the Demos, and modified it, since i can't include packages to my Delphi IDE because of the Delphi version.This one works fine with D5000 ! You should add something like the following, if you can't add packages like me:
I have released version 5.1.
All known bugs and problems fixed.
I have confirmed that these components ARE compatible with Delphi 2006.
By the way… nice job!!!! And much appreciated.
Thanks. I have updated the list.
Is there a way to know the source application?
I mean whether there is a way to know from which application, say WORD, EXCEL, Internet Explorer or FireFox, the data is dragged?
Thanks in advance.
No - not really.
You can examine the data formats offered by the source application and from that you can make an educated guess, but it's only a guess and you will have to have analyzed the different drop sources beforehand to learn of their "fingerprint".
Downloaded the DragDrop components, awesome. Ran the Outlook demo with Delphi 6, everything worked great. Ran the Outlook demo with Delphi 2010, the opening of attachements isn't working (ActionAttachmentOpenExecute). Saving the attachment appears to be failing, yet I'm not getting any errors. I have rights to the directory, not an expert with streams….any ideas?
I have reproduced and fixed the problem.
The function used to create the attachment file,
OpenStreamOnFile()
, was declared wrong. The filename parameter must be aPAnsiChar
even when Unicode is used.To correct the problem you can cast the filename to a
AnsiString
and then to aPAnsiChar
inActionAttachmentOpenExecute
:Great suite.
I am trying to make some simple copy/paste but I would like to copy a stream into the clipboard to be paste onto Explorer as a file. Is there any specific example in which this capability can be visualized ?
I am also thinking about how to create a shell handler to transfer this files directly by drag'n'drop (my application actually has the files centralized in a server and each time I need to open or copy them it is a remote operation, so they need to be downloaded first). Will appreciate any help… Thanks !
The VirtualFileStream example does what you need; It demonstrates how to drag data as a file stream or copy it onto the clipboard.
Wrt your second scenarion, check out the AsyncFTPClient example. It drags files from a remote FTP server. The files are transferred from the server on-demand as the drop source requests them.
I cannot help you with the Shell Namespace Extension as I have no experience with that. There are 3rd party solutions that can help with that if you do not wish to get your hands dirty.
Thanks for all the comments. I have tried some piece of code using as basis "onGetStream" event and work very fine to get files from the server and also to interpretate streams from Outlook (all the message or only file attachments, for example). Congratulation for you very powerfull suite.
Many thanks for the Drag & Drop Components (also TGIFImage). Your hard work is appreciated (glad it was fun!)
I compiled the Drag & Drop Components into my Delphi Turbo Explorer (2006) application and they have worked fine on Windows XP for some time now, however when I installed the application on a Windows 2000 system they don't seem to work. Is there something else I need to install? (I use this application to drag emails and attachments from Outlook 2003 to my application on the XP system, but I'm using Outlook Express from IE6 SP1 on the 2000 computer).
Thanks
I have not tested version 5 on W2K at all, but as far as I remember I haven't used any APIs that doesn't exist on W2K. If you can get any of the examples to fail on W2K let me know and I will try to reproduce the problem here. One of my kids computer is still running W2K - but not for much longer.
WRT Outlook Express you should be aware that you cannot use the same method to receive data from Outlook and Outlook Express. How do you get the data from Outlook Express?
Hi,
thanks for your components…
"Simple Source Demo" can't Drop files to Explorer or Desktop on Windows 7(32). A Dos-Box accept files.
Thanks
Try temporarily turning off UAC. If that solves the problem then the cause of the problem is that you are trying to drag between two applications that are running with different security levels.
As far as I know Vista has the exact same problem.
Using DragDrop component suite with a dynamic package runtime package may cause memory leak. I have create a sample project to show the leak, please download from here.
This sample project built with Drag and Drop component suite version 5.1 in Delphi 2007.
The memory leak should occurs in a method
TCustomSimpleClipboardFormat.DoSetData
of unitDragDropFormats.pas
:An instance of
TOLEStream
and an instance ofTFixedStreamAdapter
cause the leak.The memory leak only occurs if DragDrop components used in this dynamic runtime package behavior.
It doesn't happen if using DragDrop in static binding package.
I have tried your example and I'm afraid I cannot reproduce your problem.
I can't spot any problems with what the
DoSetData
method is doing either. TheTOleStream
object is owned (and thus destroyed) by theTFixedStreamAdapter
object. TheTFixedStreamAdapter
object is owned, through itsIStream
interface, by the caller and should be destroyed when the caller callsReleaseStgMedium
. Since the caller is Explorer it is Explorer that is responsible for freeing theIStream
object with a call toReleaseStgMedium
.It is possible that your memory leak detection is fooled by the fact that the objects are allocated in one process and freed in another. That happens a lot.
You can verify that the
TFixedStreamAdapter
object is indeed destroyed by introducing a destructor inTFixedStreamAdapter
and setting a break point in it.Btw, I should mention that I found two real memory leaks (nothing serious though) while I investigated this one so the effort wasn't wasted.
First, Anders, thank you for this nice library!
Chee Yang, did you get anywhere with this? I do not get a breakpoint at
TFixedStreamAdapter.Destroy
. The leak is reported in the big application. In a test application it is not reported, but the breakpoint does not fire. Feeling a bit confused.TIA,/DI recently purchased Rapware's EasyMapi components and was wondering if it's ok to modify your
DragDropInternet.pas
to work with Rapware's mapi units? Would a better approach be to make my ownTEasyMapiOutlookDataFormat
object in it's own unit instead?I'm looking for both it's ok to do this answer and this would be easier/better answer.
Daniel
I cannot tell which solution is the better or easiest since I don't know EasyMapi at all
I would generally advise against modifying the units as that can easily become a maintenance nightmare.
The
TOutlookDataFormat
andTMessages
classes are fairly simple so it would probably be quite easy to make a custom version of them in a new unit. I doubt that you will gain anything from it though.TMessages
is just a thin wrapper aroundOpenIMsgOnIStg()
andTOutlookDataFormat
doesn't really do anything in itself.Finally even if EasyMapi provides its own stub for
OpenIMsgOnIStg()
I can't see why it would be an advantage to use that instead of the one I have implemented.EasyMapi does have a wrapper for the Message Store but my application handles the mapi session differently than the
TMessages
implementation. Basically I already have a mapi session that I want theTMessages
to use. I'm going to try and create a new unit containingTMyMessages
.Yes, I see.
Would it be any help if I made it possible for you to override the MAPI session management? Something like this:
Possibly, but let me think about this for a while more. I'm still trying to wrap my head around both TDragDrop components source and the EasyMapi components source. Both are new to me as is the outlook object model, so it's taking me a bit to fit this puzzle together.
Hi Anders,
Thank you for the new version of Drag and Drop Component Suite. I'm a paid customer of Raize DropMaster because at an earlier time Drag and Drop Component Suite was lack of a function I needed (although I cannot remember what that was it) But now things have been changed, Raize DropMaster does not support UNICODE in pre-2009 versions of Delphi, but your excellent component suite does! and yours offers almost all features I needed! Thank you!
One question if you don't mind, the
TVirtualFileStreamDataFormat.FileNames
property isTStrings
instead ofTUnicodeStrings
, do you have a plan to add UNICODE support to this class?Thank you.
欢迎光临 Edwin,
It should be fairly easy to make
TVirtualFileStreamDataFormat
work with Unicode strings. As far as I can see all it takes is to makeTFileDescriptorToFilenameStrings
derive fromTUnicodeStrings
instead ofTStrings
and then make the necessary adjustments. It is definitely my plan to make this change (as is evident in the source comments). It will probably be in the next version - if I remember it…Hi, a remark regarding the
OnDrop
Event: the functionTCustomDropTarget.Drop
catches all exceptions. It should IMHO not catch exceptions that occur in the user defined callback.There are several good reasons why the
DragEnter
,DragOver
,DragLeave
andDrop
methods all "eat" exceptions.This is from the source code:
They would end up at the caller of the methods which is the Windows drag/drop system and ultimately the drop source application. Now why should the drop source receive an exception about an error that occurred in your application and which the drop source most likely doesn't have a clue about.
There is simply no way to get the exceptions to end up in the drop target application.
Ok, I see the reason. Then the OnDrop has to handle that itself.
Thanks for the reply.
I have just started using this component and I love it. I am working on an interface to allow a user to drag an email to it and then I will save the email in a specific folder.
I have used the OutlookDemo as a model
I can see the
IMessage
object and am able to extract the subject, attachments, and sender etcI am hoping that there is a simple method I can use like
AMessage.SaveAs ('c:\test.msg')
orAMessage.export ('c:\test.msg')
.I am using Delphi 2009.
Thank you
The
TMessage
class has aSaveToStream
method you can use. See theActionMessageSaveExecute()
method in the OutlookDemo example.Thank you for your Reply, I was trying to incorporate this into my Code, but am stumbling on the Tmessage vs Amessage vs Imessage.
in Simple terms I have modified your code as below:
When I call
ActionMessageSaveExecute(Sender);
I get an Exception violation in the following line of codeI am guessing it has to do with how I am assigning
FCurrentMessage
. Any documentation or just help you could offer would be awesomeJohn,
Um… The second parameter to
TMessage.Create()
must be anIStorage
interface pointer. Since you are passing nil you will naturally get an AV when a method on that interface is used.You need to get the
IStorage
interface from theTOutlookDataFormat
object. Check the OutlookDemo source again.Dear all,
If the need is to save the entire message as a "message.msg", I think the best way is to use
TVirtualFileStreamDataFormat
directly and catch the entire stream from the Drag Source or Clipboard (sorry If I misunderstood the question).Good point.
The VirtualFile and VirtualFileStream examples demonstrates how to do it.
Thank you both it is now working great
Great product. Thank you!
I have 2 questions.
How can I retrieve, in the OutlookDemo (OutlookTarget.pas) the Message ID and the Message Received Time?
I am unable to get these to values. I was using
PR_MESSAGE_DELIVERY_TIME
andPR_ENTRYID
.Thank you
This is the Drag and Drop Component Suite. There are much better places for Outlook and MAPI questions. That said…
The
PR_MESSAGE_DELIVERY_TIME
property works for me:Both the
PR_ENTRYID
andPR_LONGTERM_ENTRYID_FROM_TABLE
properties fails with the errorMAPI_E_NOT_FOUND
. I have no explanation for this and I have not been able to Google any clues. I suggest you ask for help in one of the places I linked to above. Let me know what you find out.Thank you for the answer. I could not find anything in the web explaining why PR_ENTRYID fails, but I managed to make it work by going back to Outlook and do a search on the subject line.
I modified your demo to capture all the email information. I can send it to you if you want to include it in your distribution package.
I have another question. How do I get Thunderbird emails? I looked at the examples and couldn't see anything related to Thunderbird.
Last question. Do you accept donations? If so, how do I donate money to the project?
Thank you again!
Yes please send me your modifications. I can't promise that I will use them but I'd like to see what you've done.
AFAIR Thunderbird v2 doesn't support drag of messages outside of it without custom plug-ins.
Thunderbird v3 however will support it. It passes mail messages in the FileContents (and FileGroupDescriptor) clipboard format. The FileContents data contains the mail message in mboxrd format (RFC 2822) - basically the raw mail message text. I think you should be able to use the TIdMessage class in Indy (idMessage unit) to parse the message. See the VirtualFile and VirtualFileStream demos for examples of how to handle the FileContent and FileGroupDescriptor formats.
I used to have an example of drag from the Netscape mail client but of course that stopped working a long time ago. If time permits I will make a Thunderbird example for the next release.
When investigating what drag/drop formats an application supports the first thing one should do is to run the Drop Source Analyzer and drop some data on it from the application in question.
The Drop Target Analyzer does the same thing, just with drop targets. Be aware though that the Target Analyzer exposes a bug in Thunderbird v3 that causes both the source and target to hang.
Donations are rare but welcome Preferably in the form of books. I have a wishlist on Amazon and Amazon UK.
Anders,
I sent you a little something via Amazon, as a token of my gratitude. It should be there tomorrow.
Thanks again!
It actually got here today. Thanks Francisco. That was very kind of you.
Hi Anders,
I found the the
TDropFileSource.MappedNames
does not work with Outlook 2007, although it works with the Windows Explorer, any comment about this? Thank you.Define "does not work".
To my knowledge Outlook does not support the FileNameMap clipboard format which is what the
MappedNames
property interfaces to.In order for
MappedNames
to have any effect the drop target must support the FileNameMap clipboard format. Explorer is the only application I know of that does so.Thank yo for the info, Anders!
TObject.Free v.s FreeAndNil
I think the code in TOutlookDataFormat.Destory is backwards. Instead of calling inherited Destroy first, IMHO destructors should always call it last after freeing their own resources.
destructor TOutlookDataFormat.Destroy;
begin
inherited Destroy; //<—- Should be called last
FMessages.Free;
end;
In the case of the TOutlookDataFormat calling inherited Destroy last, will cause an access violation. This is caused by the following chain of events.
TOutlookDataFormat.Destroy
TMessages.Destroy
TMessages.Clear
TMessages.FMessages.Free
(Inherited)
TStorageDataFormat.Destory
TStorageDataFormat.Clear – (polymorphism calls TOutlookDataFormats.Clear method here, which then tries to access FMessages member which has already been freed.)
I don’t think the Clear methods are ever called outside of the DragDropInternet.pas unit, but in any case by changing the TOutlookDataFormat.Destroy to use FreeAndNil you could then change the TOutlookDataFormat.Clear method to test for nil. Thereby correcting the aforementioned access violation assuming you correct the destructor to call inherited Destory last.
destructor TOutlookDataFormat.Destroy;
begin
FreeAndNil(FMessages);
inherited Destroy;
end;
procedure TOutlookDataFormat.Clear;
begin
inherited Clear;
if FMessages <> nil then
FMessages.Clear;
end;
Just my thoughts…
PS: Ever think about setting up a newsgroup instead of these comments?
I completely agree.
I normally always call inherited Destroy last except when I know the base class destructors can have side effects though polymorphism, as it has in this case.
Unfortunately this particular pattern (Destroy calling a polymorphic Clear method) is something I run into fairly often. I would prefer not to be forced to implement the Clear method defensibly, but it's probably the best solution. It just doesn't "feel" right, but then neither does the alternative.
Anyway, I have implemented your suggestion.
PS: Ever think about setting up a newsgroup instead of these comments?
Every day.
I have experimented with a bbPress forum but I want something that integrates properly with the existing WordPress site and is actively maintained. Even though "they" plan to run bbPress into a WordPress plug-in it doesn't appear to be going anywhere at the moment.
Now that BuddyPress can be used on stand-alone WordPress sites I may give that a try instead (ironically BuddyPress internally uses bbPress to implement its forum feature). Unfortunately I will have to update my existing WordPress installation first. Not a simple task since I have customized just about every theme and plug-in installed.
Customizing WordPress theme's and plug-ins eh? I'd like to quote your response to one of my previous posts:
"I would generally advise against modifying the units as that can easily become a maintenance nightmare."
Ouch! There's nothing worse than being lectured with your own words
But you are (or is it "I am" - I'm confused) right. I certainly won't mess that much with them next time. Luckily I won't have to as the newer versions has (almost) all the features I need. I will also switch to a fluid theme while I'm at it. A fixed width layout like this isn't good when you have lots of code snippets.
There's no better way to learn to respect guns than to shoot yourself in the foot a few times. The trick is to survive the process
Compiler Warning:
In the
TDropContextMenu.Initialize
I'm getting a warning saying return value might be undefined. Do you see a problem with movingResult := NOERROR
to the top of the method?Looks good.
How can my application (main form) be a droptarget for both files and outlook objects?
oh, wait, multiple DataFormatAdapters, not drop targets….
Exactly.
You can also use a
TDropFileTarget
and extend it with aTDataFormatAdapter
.Hello! In windows7 use Drag and Drop Component Suite Version 5.1 have been if the program using the Run as administrator can not be realized drag and drop! ! !
Does this help?
I'm trying to follow your reply to this comment where the files don't exist when the drag drop starts but get created on the
GetData
andOnDrop
events.Do I still populate the
TDropFileSource.Files
before I callTDropFileSource.Execute
or should I populate theTDropFileSource.Files
in one of the events likeGetData
?Either way should work. Give it a try and use the method that suits your purpose best.
Filling
TDropFileSource.Files
during theExtractFiles
method which gets called on theOnGetData
event seems to be working.Email Attachments
I can't seem to figure out how to get my application to accept email attachments if I drag the attachment from an open email window (outlook 2007). I'm not dragging the email, just the attachment in the email. Any ideas?
Generally:
To spare you some time, try the VirtualFile and VirtualFileStream examples.
I tried the SourceAnalyzer but soon after I posted the question I tried the VirtualFile demo and that worked. I came back here to edit my response to save you time but I was to late.
Hi, guys, I have a problem but I have no place to ask for help.
I have used the following code to get the HTML Format code of a webpage:
but unfortunately, some of the HTML Format code snippets are unreadable.
examples here:
Version:0.9
StartHTML:00000151
EndHTML:00000893
StartFragment:00000185
EndFragment:00000857
SourceURL:http://blog.ifeng.com/article/4665556.html
<html><body>
<!–StartFragment–> ?????€???????<!–EndFragment–>
</body>
</html>
It is dragged from a Chinese webpage. But the part between
StartFragment
andEndFragment
cannot be read.I am sure there must be one solution to this, but i can't find it. I would be grateful if any advice is given.
Thanks in advance.
I've examined the data in the SourceAnalyzer and I think it might be UTF-8 encoded. Have you tried UTF-8 decoding it?
Update: Yes it is indeed UTF-8. Here’s what the documentation for the CF_HTML format says:
If I have two data format adapters on a form that prompt the user during the OnDrop event for both formats, I can get it to error out in a rather unlikely scenario. In this example I'm using TOutlookDataFormat and a TFileDataFormat adapter.
1) Drop an email on the form, leave the modal dialog unanswered.
2) Now drop a file on the form and try to answer the modal dialogs.
This results in an AV. I've tried to disable the TDropEmptyTarget but it still lets me drop while I'm in the OnDrop event.
Under normal circumstances it should not be possible to get into the OnDrop event while a previous drop is still being processed. The Windows drag/drop system is not reentrant and neither is the drag/drop components.
My guess is that you have enabled asynchronous operation on the drop targets. In asynchronous mode, the OnDrop event is delegated to a separate thread which allows the main thread to return and process another drop. If the thread should block during the OnDrop event (e.g. if someone displays a modal dialog box in the OnDrop handler), then the scenario you are seeing could be possible.
If you run it in the debugger you should be able to see which thread(s) the OnDrop handler is being executed on.
Anyhow, it is not a good idea to display a modal dialog from inside a drag/drop event handler. If you need to display a prompt then you must post a message to yourself and display the prompt in the message handler.
I'll have to investigate why setting Enabled doesn't do anything. It's a fairly new feature so I might have missed something there.
Hi,
I want to detect if a file has a specific file format before allowing it to be dragged onto my application. Is this code safe, or is there a better way to do it? I'm a little concerned about the call to
.clear
, should that be there if my program refuses the file?Thanks
I'm not quite sure what you are trying to do but my guess is that you should not be calling
Clear
unless you are rejecting the drop. I.e.:However, the correct way to reject the drop is to set the
Effect
parameter toDROPEFFECT_NONE
:If you do that then the components will call
Clear
for you (fromTCustomDropTarget.DragLeave
) and inform the drop source that you rejected the drop.Hello,
I try to use OutlookDemo. But i've a problem when i drop a mail message on it.
only one message and i've a blank memo and nothing is display. more than one Access Violation and nothing is display
I'm using Delphi 2009 and Outlook 2000 under XP/SP2
In debug
// Get an IMessage interface
if (Supports(OutlookDataFormat.Messages[i], IMessage, AMessage)) then
begin
try
Item := ListViewBrowser.Items.Add;
… GetSender and GetSubject - > Return always ''
because if (Succeeded(HrGetOneProp(AMessage, PR_SUBJECT, Prop))) always False
GetTime(AMessage); — > return a good day but a bad time same with PR_MESSAGE_DELIVERY_TIME
Item.Data := TMessage.Create(AMessage, OutlookDataFormat.Storages[i]);
…
also in function ViewMessage
for j := 0 to Rows.aRow[i].cValues-1 do
begin
{$ifdef UNICODE}
{ TODO : TSPropValue.Value.lpszW is declared wrong }
Value := PWideChar(Rows.aRow[i].lpProps[0].Value.lpszW); – > EAccessViolation (item.data)
{$else}
Thanks for your help, i don't know what to do
I really like your Drag & Drop component 5.1 but I am not able to use it under the Creative Common license. I need a royalty free license that will allow me to use it in a closed source commercial application. Are you open to licensing it under alternate license in a conventional Delphi component model? If so how much would you license it for per developer? Thanks.
The license I'm using allows royalty free, closed source, commercial usage, but you can use the MPL license if you prefer.
Hi, I'm tried this package on Delphi 5. All works fine for me, thank You. But I'm find one big problem. Your components / demos does not work on Windows 7 64bit (tested on Outlook demo), the form does not accept drag. Please correct this.
Thank You, Petr
I'm looking at replacing my drag drop event that contains a loop which requires user interaction for each file dropped on the form. From everything I've read (and one of your previous posts) it's not good to do something modal in the
OnDrop
event because I'm holding up the shell's thread.I've tried
PostMessage
to self but the DataFormatAdapters are empty by the time my message handler fires. Do I need to save down the files myself to a temp location and process them in my message handler or is there a better way to accomplish this?Daniel
You're on the right track. Save a copy of the data somewhere, do a PostMessage and do your modal stuff in the message handler.
Hi Anders,
Thanks for a great set of components. Have you thought about providing them for Lazarus (Free Pascal) which could allow development for Macs?
The question has been asked before but I doubt that anything will happen.
I don't have the time or motivation and those that use Lazarus and FPC doesn't seem to care.
Thanks Anders - I understand your position.
I think you are wrong about Lazarus users not seeming to care though as I've now had a closer look at the Lazarus IDE and the good news is - there's a Form Boolean property called
AllowDropFiles
which allows easy drag and drop straight on to a form from another application window.The feature is really easy to set up - there's no need to set
DragMode
or write any code forDragOver
andDragDrop
events. The only thing you have to do is write the code for theOnDropFiles
event.This is quite an impressive feature which does not appear to exist in the versions of Delphi that I've seen (D1 to D2009).
Although it's fine for most people I'm not sure I'd call it impressive. A
WM_DROPFILES
wrapper (which I'm sure is what it is) can be done with something like 10-20 lines of code. A generic drag/drop implementation would be more like 10K-20K lines of code.Anyway, it's great that you found a solution.
I agree with you if you're thinking in the Windows box only. What impresses me is that Lazarus is cross platform - you can't use Windows API techniques to D&D in Mac OS!! Penile references to numbers of lines of code are irrelevant here.
Anyway, it's great that you've built such a good suite of components for Windows - I've used them before and they've been very reliable.
Thank You! Great Job!
————————–
Missed file in current release of DragDrop (20100129):
DragDrop\Demos\ShellContextMenuHandler\About.rc
Thanks. I'll make sure to get the file included for the next release.
I'm in China right now but I'll post a new version once I get back home. AFAIR there are a few other minor changes waiting to be released.
Love this component, but……
Recently upgraded to D2010 Architect. Installed version 5.1. Demo Project ComboTargetDemo, compiled and ran. From Outlook 2003 dragged attachment(text file) straight from email to drop area. Filename (
DropComboTarget1.Data.names[i]
) is empty. Data is intact.Reproduced from more than one machine.
I have reproduced the problem and located the cause of it.
The problem is that the
TFileContentsStreamClipboardFormat
class reads the filenames from the ANSIFileGroupDescriptor
clipboard format (CFSTR_FILEDESCRIPTORA
) when compiled with an ANSI Delphi and from theFileGroupDescriptorW
clipboard format (CFSTR_FILEDESCRIPTORW
) when compiled with an Unicode Delphi.Unfortunately Outlook only supports the
FileGroupDescriptor
format.I will have a solution in the next release… but first I need to find out why this comment box is completely borked. Strange that nobody has mentioned it.
I now have a solution that works with both Ansi and Unicode Delphi. New release coming RSN…
Also, the comment box was only broken for me. I had changed Firefox's UserAgent setting and that broke TinyMCE. Duh!
Hi Anders,
I'm looking forward to the new release when it's ready.
I found a problem with
TDropContextMenu
. Maybe it's among the changes you've already made and in that case you can skip this post cause you probably have a better soluton than I. When the context menu contains more than one level of submenus the wrong clickevent could be fired. After looking for bugs in my code, I tracked it down toGetMenuItem
not returning the MenuItem that was actually clicked.I interpreted it as all items not being counted when getting ItemIndex from
LoWord(lpici.lpVerb)
. Maybe you have a better clue to what's really going on?I've solved the problem by creating a new function
GetClickedMenuItem
in "DragDropContext.pas
" and calling it instead ofGetMenuItem
from withinInvokeCommand
. So far it's been working and I've tested it with up to four submenu levels. Here's what the function looks like:Thanks for the feedback.
I wasn't aware of that problem and I'll review your fix for inclusion in the next release.
Try this fix instead:
In
TDropContextMenu.QueryContextMenu
change theTraverse
procedure like this:Hi, I just found Drag&Drop. Very nice. Can I donate some money, maybe $100? Do you take VISA?
What would help is a doc that explains a few things. I need to figure out what that
TDropDummy
item is all about. The Async mode makes sense but I need to understand the issue areas. (I am not aTThread
expert, yet.)Thanks,
Bob Kondner
PS: I write some software used in electronic assembly. Just 1 guy with a shop and a small set of customers. But I do think I have some good ideas for the electronic design marketplace.
The TDropDummy component is just used to enable drag images on controls that are not drop targets. If you have specific questions wrt. asynchronous mode I'll be happy to help.
I'm afraid I don't have time to write documentation anymore. I'm a slow writer and from experience it takes me more time to document a feature than it takes to implement it. Instead I write examples.
That said, I do have some old help written for the V4 components. I guess that's better than nothing. I will see if I can HTMLify it and get it posted online.
Wrt donations I'd prefer a book or two. Much more personal and I avoid paying taxes (60%):
Thanks Anders. The change in TraverseMenu is working well. I've succesfully used it in Delphi 7, 2007 and 2010.
I'm glad to get rid of the procedure I added.
Hi, maybe this problem is already solved and I did not find the solution. But in the demos when a file is MOVED with TDropFileSource from a ListView to Windows Explorer the ListView is not refreshed to indicate that the source files have been deleted. I've searched for an event to handle this but did not find one, also the OnAfterDrop event does not work for this purpose. Any advice?
Hi,
I was looking through the DropComboTarget and I understood all the drop types except "mfData".
It is read in via a stream. Can you tell me what common apps might generate this format? I assume it is for passing large sextions of data?
Thanks,
Bob Kondner
mfData is for the FileContents clipboard format. Many different applications can supply this format. It is always accompanied with the FileGroupDescriptor format.
You can use the Source Analyzer demo application to determine which formats an application can supply and the Target Analyzer to determine which formats it consumes.
Hi,
The context menu component does not work in Windows 7 64 bit.
After the dll has been registered, the menu doesn't appear in the explorer. It works perfectly in 32bit version.
Is there any special treatment for windows 64bit version ?
Thanks,
Armin
Shell extensions must match the "bitness" of the OS. I.e. for 64-bit Windows you need a 64-bit compiler. Sorry.
Hi,
On ocassion when debugging an app, the app nolong responds that it can accept a drop. Restart of app or Delphi does not help. A machien Restart helps. I probably trashed the drag thread. Any ideas What would do that? The drop even stores the droped info in a variable and returns. A timer is used to start the priocessing of the drop.
Any ideas where I went astray?
Thanks,
Bob Kondner
I haven't got a clue.
It could be a bug in my code, in your code or in the drop source. I've seen memory overwrite bugs do that. Logout/Login usually helps. It shouldn't be necessary to reboot.
hi i found the dragdrop component, works great.
i use the TDropComboTarget the only thing i noticed i cannot drop on non std delphi components like a virtualtreeview ? Can i do anything about that ?
AFAIR VirtualTreeView has its own COM based drag/drop handling but I think it also has a method or property you can use to disable it with.
Hi,
I am looking for a solution which can dragdrop
virtual files and folders which from ftp into explorer,
the example asyncSource very similar to it?
but the example only write stream to files ,
It can not creat folders .
I saw TDataformatAdapterSource has
DataFormatName –> TPIDLDataFormat
Did you have example about it ?
Just add a folder to the filename when it's added to the drop source.
E.g. instead of dragging "foo.txt" you drag "bar\foo.txt".
When debugging in Delphi 2010 (CustomFormat1 demo) I notice that dragging to anywhere else but the correct spot locks up the program and the IDE. When program is killed in the Task Manager the IDE comes to life again. When the program exe is run outside of IDE it works like its supposed to. This makes debugging difficult.
This is caused by a bug in the debugger. The problem only occurs when you drag across the IDE while debugging (so don't do that).
What you are seeing is a dead lock. I believe it's caused by the debugger suspending the debugged application while the IDE handles the drag/drop operation. Since the debugged application is the source of the drop, the IDE waits forever for the drop source to deliver the data.
The problem has been reported in QC:
Report No: 62190 (RAID: 236101) Status: Open
IDE deadlock when debugging COM drop source
http://qc.codegear.com/wc/qcmain.aspx?d=62190
Report No: 23749 (RAID: unavailable) Status: Open
Debugger hang up when OleDragSource drags over IDE
http://qc.codegear.com/wc/qcmain.aspx?d=23749
Hi,
I was working with a TDropComboTarget object and I noticed that a drop of a URL from IE8 results in a Text property with a lot of zeros on the end. I saw your notes about some apps passing binary data and I saw the TrimZero property in TCustomAnsiStringClipboardFormat . Is this TrimZeroes the "Correct" way to resolve the extra Zeros. I was taking them out myself but that seems like a hack.
When it comes to OOPs design in Delphi I am still at Bozo level, could you explain how I access that TrimZeros prperty from the applications level. It seems deeply buried down in the base class.
Also, I would also like to extract the filename from a drop of an Outlook attachement. The data I can read using your example code the Name comes in blank. Can you point me in the right direction to implement this in the TDropComboTarget framework. Again, I realize this might not be the "Correct" location though the TDropComboTarget seems like such a nice application interface point. I can see the file name in the FileGroupDescriptor I just do not see it surfaced in the TDropComboTarget. I would think it should end up in Data.Names property.
Thanks,
Bob Kondner
PS: You have two wish list items on the way. The US wish list needs an address, I could not ship from the US list. I used the UK list.
I'm afraid the
TrimZeroes
property is for the classes internal use but I'll see if I can do something about getting rid of the zeroes in the URL. In the mean time you can easily trim them yourself by casting the string to aPChar
:I'm leaving on a weeks vacation in about 5 minutes so I don't have time to check the Outlook attachment problem now, but I'll look into it when I get back. Please ping me if I haven't responded within 10 days.
Thanks for the books.
I just now noticed that you were referring to the
Text
property and not theURL
property.The
URL
property get its data from theTAnsiURLClipboardFormat
class which, because it is derived fromTCustomAnsiTextClipboardFormat
, hasTrimZeroes
set to True by default.The
Text
property get its data, in the case of an URL dropped from IE, from theTFileContentsClipboardFormat
class. This class does not, and should not, haveTrimZeroes
set to True.TFileContentsClipboardFormat
should always make the raw data available.So the solution to your problem is simply to use the
URL
property for URLs.Melander,
I want to thank you for providing these components. They are a big help for a lot of us.
There seems to be a bug in the
TDropComboTarget
component when used in D2010.When dragging a FileContents stream (in my case, from an attachment on an Outlook email) to my application, the name of the attachment is returned as an empty string. This DOES work okay in Turbo Delphi 2006. The name is what gets lost, the file stream itself seems to be okay.
My system is:
To re-produce the bug:
Fill in the following code:
If it works correctly, “Label1” will be replaced with the file name of the attachment. If it doesn’t work correctly, the label caption will go blank.
For whatever it is worth, the
TDropEmptyTarget
andTDataFormatAdapter
combination does properly pick up the attachment file name in theFileNames
property in this situation.Thanks, David Hawk
After preparing this post, I noted it is similar to Bob Kondner’s post a couple days ago. I have provided a simple example to re-create the problem, and a suggestion that
TDropEmptyTarget
andTDataFormatAdapter
might be used instead - a possible workaround for Bob, see the VirtualFileStream demo. Meanwhile - I hope you are enjoying your vacation!Bob,
Melander might have a better answer when he gets back from vacation, but I had the same problem (no filename from the drop of an Outlook attachment), and was able to get something working using TDropEmptyTarget and TDataFormatAdapter. Look at the VirtualFileStream demo and look at the code in the DropEmptyTarget1Drop method in main.pas. The FileNames[] property works properly here.
Best,
David Hawk
David,
Thanks for the idea, I did start with that approach but I am not yet at the level to completely understand how I would interwork the Adper class with the Drop Combo class. The Combo is so close and I would like to do something useful like maybe add the Outlook name surfacing to the Combo. That would be useful for everyone.
But, I need some pointers before I can do any serious useful work. And I need a few more read throughs on these tools in general. I am just not at the required level, yet!
Thanks,
Bob Kondner
rkondner circlewitha indexdesigns period_com
Hi Anders,
I just upgraded to version 5.1 of your great drag and drop components Suite. There are two issues in
droptarget.pas
which you may or may not want to fix. It is hard to say when something is a feature and when something is a bugDragOver
is not called whenDragEnter
returnsDROPEFFECT_NONE
.You write in line 530 in
Droptarget.pas
>TCustomDropTarget.DragEnter()
First, I can not find this anymore on MSDN (maybe Microsoft removed it), but most importantly not calling
DragOver
causes a problem in some situations.My application contains an component with thumbnails. When I drag one thumbnail over another to sort them, I do not want to accept drops on the dragged thumbnail itself, but only on the other thumbnails. I use
OnGetDropEffect
to determine where dropping is allowed.With the current code when I start dragging a thumbnail it is rejected in
DragEnter
because the thumbnail is dragged over itself. Now when I move the cursor to the neighboring thumbnail the drop is still not accepted becauseDragOver
is never called due to the initial rejection. This is why I commented this code out:Droptarget.pas
>TCustomDropTarget.DragEnter()
, line: 536FNoScrollZone
only calculated inDragEnter
FNoScrollZone
is only calculated inDragEnter
. However, sometimes a component resizes while dragging causing scrollbars to appear while dragging. In this case scrolling does not work.An example of a resizing component is a treeview where nodes autoexpand while dragging over them.
FNoScrollZone
should be calculated inDragOver
too. Or it should be recalculated when a component that is dragged over resizes.Those are two rather exotic cases so I can understand it if you leave things as they are.
Hi Jan,
IMO the problem isn't really that
DragOver
doesn't get called if the drop is rejected inDragEnter
. The problem is that you are rejecting the drop prematurely and misusing theOnGetDropEffect
event.OnGetDropEffect
is primarily meant to be used to change the drop mode (copy/move/link/scroll) based on for example shift state.A simply solution to your problem would be to avoid using
OnGetDropEffect
and instead use theEffect
parameter of theOnEnter
andOnDragOver
events. InOnEnter
you can decide if the drag should be completely rejected based on target state or the content of the data being dragged. InOnDropOver
you can accept or reject the drag based on f.ex. mouse position.I have released version 5.2.
Been using your componet for a while - its great! However, we have found it doesn't work to well in windows 7. XP yes, windows 7 no - don't know about vista. Even in your outlooktarget demo it doesn't recognize that a drop can occur.
Any ideas?
Thanks in Advance
I don't use Vista or Windows 7 so I'm afraid I can't reproduce your problem, but from what I've heard UAC has pretty much crippled drag/drop.
Please read this post. Does that help?
Hello Anders,
First of all, thank you for having developed these highly useful components.
I have a technical question about the Async Data Tranfer - Drop Target demo. In its current state, this demo app accepts only files from Outlook.
What change would be required for this app to accept also files from Windows Explorer? The answer may be quite simple. In any case I hope to be able to use the demo project as a starting point for my project and I am willing to pay for assistance. At this moment, however, I am stuck.
Thank you for your help.
Kind regards,
Stefan
The AsyncTransferTarget demo only support the
FileGroupDescriptor
andFileContents
formats. The Explorer can accept these formats as a drop target but doesn't support them as a drop source.In order to make AsyncTransferTarget accept drops from the Explorer you must extend it with support for one of the formats offered by Explorer: CF_HDROP or Shell IDList (a PIDL list). See the Adapter demo for an example of how to do this.
Just discovered what the problem is. If you are trying to drag and drop under windows 7 (probably vista too) both dragger and dropper needs to be at the same security level. i.e. administrator,administrtor, or user,user. If they are not at the same level drag and drop doesn't work.
Yes, that was the point of the message I linked to, but It's good to get confirmation.
Thank you. I need one more piece of advice to be able to get started.
I use the AsyncTransferTarget as a basis for my application. The purpose is to transfer files to a network folder. Files have to be moved physically from Outlook to a folder.
In the AsyncTransferTarget demo application, I do not see where and how I have to modify the code or settings to achieve this. I am overlooking something obvious. If I do, I apologise for my lack of knowledge. I have not been able to deduct from the VirtualFile demo either how to do this.
A code snippet would be very useful.
Thank you.
I think I understand what you are trying to do (drag attachments from Outlook to your application and write them to disk) but I'm afraid I don't understand what specifically it is you are asking for.
Please clarify.
Dear Anders, I am really stuck, and I am really sorry having to bother you.You have understood what I am trying to achieve: drag attachments from Outlook to my application and write them to disk.However, I have not been able to figure out from the VirtualFile demo how to physically move an attachment via my application to a location on the hard disk. My application is based on the async data transfer target demo.Your help would be greatly appreciated. If you could just send me some sample code, or indicate how to move an outlook attachment to any location, for example c:\temp, that would get me going.I am willing to pay for any expenses and your time, of course.Thank you.Regards,Stefan
All you need to do is save the stream containing the dropped data to a file.
Try modifying the AsyncTransferTarget demo like this (untested):
You should add a path to the filename or the file will end up in the "current folder".
Hello again,
I think we are almost there. There is an error in the following line:
The Delphi compiler says:
It may be because there is one parameter missing.
The function is
I tried adding one
Nil^
, but that did not work. What would be the right parameter, please?Thanks again.
Stefan
Oh yes, I forgot about that one.
Great. It works now.
Thank you.
Again, my congratulations for this wonderful product and the great support.
Does anyone have an example for handling message and file attachment drops from Thunderbird v3?
The VirtualFile and VirtualFileStream examples should get you started.
Read this message for more information.
Hi, Melander
I can't find the right way to install these components into radstudio 2010.
My step is
Open DragDropD2010.dpr, and then select "Generate all C++ Builder files (including package libs)"
and added some paths to delphi and bcb paths.
then install .
When using in delphi ,every thing is ok.
But if I use it in bcb, there will be errors like this
"[ILINK32 Error] Fatal: Unable to open file 'DRAGDROP.OBJ'"
There is only dragdropd2010.lib in library fold ,no any obj files.
How to solve problem and using these components in both delphi and bcb 2010?
thanks
The detailed error messages are as follows
[BCC32 Error] Dragdropcomobj.hpp(28): E2303 Type name expected
[200 lines of irrelevant error messages snipped]
I don't have C++ Builder installed so I can't help you.
Sorry.
Hello Anders,
thanks for good demos of the great components you've developed.
I am working with the Outlookdemo an tried to reload a msg file from Filesystem which i previosly saved with
FCurrentMessage.SaveToStream
.Is could not figure out how to implement a analog
LoadFromStream
/File
to add the Message in the Demo.Can you give me a hint , so i can find my way
Thanks
The answer really depends on what it is you are trying to do on a higher level, but I'm afraid that is beyond the topic of this page.
That said, you should not modify the content of a TMessage object. If you need to modify the content of the message objects then you should create a copy of them and modify the copy instead.
Hi
I using your componet drag and drop. For me are the best. But i have problem with microsoft office 2010. I can't drag any information from this version. Can You help me ?
What specifically are you trying to drag?
You can use the SourceAnalyzer example application to determine what formats a given drop source supports.
If you drag from Office and drop on SourceAnalyzer it will tell you exactly what is being dropped. If that doesn't help, you are welcome to mail me the information (select Save list… from the toolbar and please zip the file).
Hi,
I have a
TTreeView
that represents a list of files. On the TreeView'sMouseDown
event, I'm calling aTDropFileSource
'sExecute
event, and everything works well if the node is dragged off theTTreeView
.However, I need to allow nodes to be dragged within the
TTreeView
because the users can rearrange files. When this happens, some strange behavior occurs: the wholeTTreeview
is in "don't accept" mode until the mouse button is let go, then as soon as I pass the next treenode, theTTreeView
goes into "accept" mode and the node can be dropped.Here's the code necessary to reproduce it. Drop a
TTreeView
and aTDropFileSource
on a form, and set theTTreeView
'sdragmode
todmAutomatic
. I'm using Delphi 7 if that matters.Thanks!
Hi,
I am using the OutlookTarget to drag and drop Emails into my Application. Everything works OK except that the filenames of the attachments are often shortened or replaced by e.g. 'attachment1'. Is there any way to ensure that the attachment name is displyed correctly ?
Thanks for your help
Marcus
Thanks for the greats components …
but the target drop .. (with example TargetDemo .. not work with Windows Seven 64 bit….)(not accept drop …)
Thanks for your help
Does it work if you start TargetDemo from the Explorer?
Can you drag from SourceDemo to TargetDemo (again, start both from Explorer)?
If it works when the application is started from Explorer, but not when you run in the IDE, then the problem is caused by UAC.
Dear Author,
I would like to drag and drop between a VirtualTreeview and a CADImportVCL component. Is it possible at all? All i want to do is grab nodes from the tree and 'put them' on a cad drawing. I would use only the mouse X,Y coordinates on a mouseUp event… so there would be no any 'classic' d&d data transfering.
What components could i use from your suite for the task above? If i need to use any for this task at all…
Thank you for your help!
If you don't need to drag data from the treeview to external applications (e.g. explorer) then I would recommend that you disable Virtual TreeView's COM drag/drop and revert to VCL based drag/drop. You can do this by setting the treeview's
DragType
property todtVCL
.If you do need COM based drag/drop then the easiest is to use a
TDropTextTarget
component. See the CustomFormat demos for examples of how to add support for custom data if you need that.I am using your components to get emails from outlook and to read the emails. It works great for Text and Rich Text emails but if I try to drag over an HTML email I can't seem to get the Body from the message. I'm using HrGetOneProp(AMessage, PR_BODY, Prop) should I be using something different?
That question is about MAPI or Outlook automation - not drag and drop.
Anyway, I found the answer via Google: If PR_BODY doesn't return anything, try PR_BODY_HTML and if that doesn't return anything, try PR_HTML. If all that fail you may have to grab the text from a compressed RTF format and do some voodoo on it. Google for details.
Hey Anders!
I am trying to use the
TDropText
components with myTSynEdit
(I guess you have heard of it?)I am trying to accomplish a Text-Drop from a component to the
TSynEdit
. The problem is, while dragging, I wish to set the Caret position of the SynEdit, and that is only possible through the SynEdit'sOnMouseCursor
event. But that event is not being fired while dragging. How do I work around that? Thank you!I do know
TSynEdit
but I haven't used it as a drop target.Try this (not tested):
TSynEdit
's own drop handler by clearing theeoDropFiles
option flag.TDropTextTarget
component and set theTarget
property to point to theTSynEdit
control.TDropTextTarget.OnDragOver
event handler callTSynEdit.DisplayToBufferPos
to calculate the new location of the caret andTSynEdit.CaretXY
to move the caret.TDropTextTarget.OnDrop
event handler do the same thing and then insert the dropped text withTSynEdit.SelText := TDropTextTarget.Text
.If you also need to be able to drop files onto
TSynEdit
and have them opened there, you should either use aTDropComboTarget
component instead or extend theTTextDropTarget
with support for file drops (see the adapter example).Hey Anders,
I already got it fixed a few days ago, basically the same code, but I did not need to disable the eoDropFiles flag
Thanks for the reply!
Hi.
I want to drag and drop file from WinExplorer into my app which is a MDI app. I want to drag&drop both in the main and child form.
If I move the mouse over the main form and drop the file, it works.
If I move the mouse over the child form and drop the file, it works.
The problem when I move the mouse first over the child form (and don’t drop yet), then I move the mouse over the main form and want to drop. In this case the cursor shape never changes to the + sign that shows that I can drop the files. And of course the drop operation is not performed.
To fix it, I have to move the mouse back over Win Explorer and then back over my app this time being careful not to go over child form again.
Any hints?
The code is something like this:
PS: great component!
I'm afraid I cannot reproduce your problem. I have tried both with MDI and SDI forms.
Are you doing anything in the
OnDragOver
,OnEnter
,OnLeave
orOnGetDropEffect
events?P.S. Try to use the same email address each time you post. That way I don't have to moderate you more than once. Also my spam filter normally blocks anyone that keep changing their address - and rightly so.
I have tried to move the controls from the MDI child form (where the were originally placed) into the parent form, but I get the same result.
Maybe there is a special way to handle MDI applications?
Are you aware of any problems with the drop source components when used under Windows 7?
When using the Version 5.2 SimpleTargetDemo on Windows XP, it compiles and runs (Delphi 7) fine. When the same program is compiled and run under Windows 7 (also Delpihi 7), it refuses to accept anything dropped. Oddly enough, the version compiled under Windows XP will accept dropped files even when run under Windows 7.
Dan
Other than the usual problem with UAC (you can't drag between different security levels) I don't known of any problems.
I doubt that the OS where the compiler runs has anything to do with it. My guess is that it works when you run outside the debugger but not when you run in the debugger.
Thanks. That appear to be correct.
Happy new year Anders
I just noticed that when right clicking a lnk-file my custom context-menu for "AllFileSystemObjects" appears twice. Once for the lnk-file itself and once for the file it links too.
In "DragDropContext.pas" at the beginning of the function
TDropContextMenu.QueryContextMenu
before the lineif (Assigned(FOnPrepareMenu)) then
I added the following code to work-around the problem:I guess this might break some applications or functionality but it works for my purpose.
Maybe a better solution is to make the
uFlags
a parameter to theFOnPrepareMenu
event, or to make the added code optional through a boolean property?There's of course also the possibility that it can be done with your original code and I just haven't figured out how to do it.
Happy coding
Per
Thanks for the feedback Per.
Is there any reason why you cannot use the name(s) of the target file(s) to determine if the menu should be populated or not?
E.g. in the
TDropContextMenu.OnPrepareMenu
event handler:I get an 'Unspecified Error' when this line of code executes
I believe this is initializing the connection to outllook. My question is, are these libraries compatible with windows terminal server 2008, Outlook 2010?
When I run the emailexample.exe I get a windows error as well
John
The Complete Error is
Failed to initialize mapi: Unspecified Error
All versions of WTS and Outlook should be supported.
That said, there has been problems with MAPI on Vista and Windows Server 2008. I suggest you try and run the FixMapi tool if you can locate it. Otherwise try and install the latest MAPI and see if that helps. Unfortunately I can't investigate further and I can't provide you with a direct download link as most of microsoft.com seems to be down at the moment.
The "Unspecified error" is the text of the generic E_FAIL error code. Basically it just means "shit happened" which really doesn't give us much information to work with
This fixed it thankyou you rock
http://www.microsoft.com/downl.....110307611E
Thanks for the quick reply Anders. I've tried your suggestion and managed to find some problems with it though.
Let's say I have selected three files with different extensions, for example a ".pas", a ".dfm" and a ".lnk". Then my contextmenu is only displayed if I rightclick the lnk-file. If I rightclick any of the other files in the selection no contextmenu is displayed. Per-haps not a very likely situation but it could be confusing.
If I rightclick a lnk-file it also seems like using your code will put the name of the linked file in the Files[0] property of the TDropContextMenu instead of the name of the lnk-file itself. In the rare cases I rightclick a lnk-file to use it with this particular extension I'd like it to operate on the lnk-file and not the file it links to. Correct me if I'm wrong and please ask if you didn't understand what I just wrote, I hardly do it myself.
A third and minor thing is that if I ever decide to write more shellextensions for "AllFileSystemObjects" I would have to add code to the OnPrepareMenu event for them too, instead of having the component handle the situation automatically.
Thank you for a fantastic component suite.
Per
It works good on WinXP, but seems not work on Win7, why?
Please read this comment.
Hi Anders
Lots of thanks for the excellent components you provide.
Following your SourceDemo example, I'm using the TDropFileSource to drop files in other applications.
It seems, however, that some apps (like Skype) do not accept them whilst others (like Word) accept them as filenames instead of opening them.
Best regards
Manos
Found out, that Skype demands dtMove to be included in DropFileSource.DragType in order to accept dropped files, whilst MSWord opens dropped files only when assosiated to it (like .doc, .rtf etc)
Nice components, thanks.
I have a question though. I have a listview control that displays files. The form that shows this listview can be open multiple times (MDI). If I do not use your components, put drag mode to automatic - I can successfully move files from one listview to another (across forms). This is accomplished because the DragDrop event populates a 'source' parameter that I can cast as TListView. Works great.
I need to add the ability to drag files in and out of these list views to other windows apps/explorer/etc. If I sent drag mode of the listview to manual, setup droptarget and drop source - I can get that working perfectly.
The problem is now I cannot drag between MDI windows in the app. If I do not set dragmode to manual - everything is crazy, since I start the drag using your product. Since dragmode is manual now, I never get the normal dragdrop event. Using your drop event, I cannot determine the 'source' that it came from - I need access to that listview (and the data it has) to perform the move.
How can I do both?
I'm afraid you cannot mix VCL and COM drag drop. I have previously tried to find a solution, but so far without luck.
In order to solve your problem you need to change your drag drop to be purely COM based; In addition to the
TDropFileSource
component you use now you'll need to also add aTDropFileTarget
andhave that manage drops onto your listview.To determine the source of the data dropped on you you can either save the necessary information in global data from an event in the drop source or you can transfer the data in a private data format in addition to the filename already being transferred. One of the examples demonstrate how to define and add custom data to the source and target components.
If you only support drops sourced by your own application you should enable the drop target(s) when your drop source starts a drag and disable them again when the drag ends. That way you don't need any special logic to detect and reject drops from other applications.
I hope this makes sense. Otherwise let me know.
Anders, Thanks for the reply. I will try the global variable route. However, in the DropSource OnDrop event, I actually CREATE the files because the user may have dropped them out of the program - then they are copied from the created location to where they dropped them. If they drop on my own program - I do not need to create these files - as I can just move some pointers around…..the problem is the dropsource ondrop event will fire before my DropTarget event - right? Therefore I do not know if the DropSource should do anything….when DropSource onDrop is called, I really need to know if the 'target' is my app or not - anyway to do that?Thanks again for the components and the reply!
Hi,
Is the Drag and Drop Component Suite 5.2 compatible with Delphi XE (2011)?
Kind regards,
Guus
Yes it is.
Hi Anders
Nice component and it is obvious that you have put a lot of work into it.
I've spent many hours trying to get it to work in my application (managing files on a PVR) and I'm almost there now. My current problem is that the OnLeave event does not always fire when the mouse leaves the DropFileTarget "quickly" - it only gets fired when the mouse is moved slowly from the target (I know that OnLeave is not being called because the event writes a message to a RichEdit control).
As extracting files from the PVR can take a "long" time, I only want to do that when dropping externally from the application (a bit like your ExtractDemo) - internal drags and drops can be performed directly on the PVR.
To determine whether or not I am dropping in the application, I am setting a flag, FInternalDrop, to true when initiating a drag and/or in the OnEnter event and to false in the OnLeave event. The OnGetData event only extracts the files from the PVR when FInternalDrop is false.
Is the lack of a consistent OnLeave event a feature of windows or something wrong in the drag suite (5.2)?
Can you suggest any other mechanism for how I can determine if I am dropping external to the application ? (I don't need to know the target application; setting the flag in the OnDrop event is too late as OnGetData has already fired).
Regards
Geoff
Application details: XP Pro, Delphi 7.1.
DropFileTarget1.MultiTarget is true ; one target is a treeview and the other is a listview (like explorer). Under the listview is a panel containing a RichEdit control. Dragging quickly from the ListView to the RichEdit control does not always fire the OnLeave event but it does fire if dragged slowly. Have also noticed not always fired when dragging from the listview to the treeview.
I suppose there may be a similar issue with the OnEnter event !
Hi Anders
I seem to have found an alternative method of detecting whether or not I am dropping outside my application (and this will probably work for WayneB as well).
This doesn't explain why the
OnLeave
event doesn't always fire when the mouse is moved quickly but does mean that I'm not dependent on the answer!Cheers
Geoff
Geoff (and Wayne, since your needs seem to almost identical),
I have not been able to reproduce any inconsistencies with the target
OnEnter
/OnLeave
events. The rule, which is enforced by Windows, is that a call toIDropTarget.DragEnter
method (OnEnter
) will always be followed by eitherIDropTarget.DragLeave
(OnLeave
) orIDropTarget.Drop
(OnDrop
).You can experiment with the “MultipleTargets” example application to verify this; If the
OnLeave
orOnDrop
event doesn't work consistently then the target zone will stay red.The only two things I can think of that could cause the events to not fire when you would expect them to is 1) an exception in the
DragLeave
orDrop
methods or 2) asynchronous transfer mode. Note that it isn't safe to mess with VCL or Windows objects (e.g. writing to aTRichEdit
) from the event handlers during an asynchronous transfer.A really easy way of determining if the drop target is within the application is to test the value of the drop target component's
Target
property. TheTarget
property is set in theDragEnter
method and reset in theDragLeave
andDrop
methods.If that doesn't work for you you can have the drop targets identify themselves to the drop source through the drop source's
IDataObject
in theOnEnter
event. Although it isn't used there is actually a special clipboard format just for that purpose: TheTTargetCLSIDClipboardFormat
class in the DragDropFormats unit. SeeCFSTR_TARGETCLSID
on MSDN for more information.Now with regard to the data you are transferring. If I've understood you correct you are both dragging files that doesn't physically exist at the time the drag begins. Furthermore it is relatively expensive to actually create the files. Finally drags within the application just flips some bits and does not require the physical files to be created.
It seems to me that you should be using a solution similar to the "VirtualFileStream", "AsyncSource" and "AsyncSource with Filestreams" example applications; Instead of dragging filenames, which brings along the problem of when to actually create the physical files, you should be dragging data streams and have the streams created on-demand when the target asks for them. The three examples mentioned should have most of the details covered.
To handle the internal drop case you could add a custom data format that contain the information required to flip the correct bits from the target. See the "CustomFormat" demos for examples of how to define and add custom data.
Actually on examining the source code it seems that the drop source components does use the
TTargetCLSIDClipboardFormat
class and exposes the value it contains through the publicTargetCLSID
property.That just leaves you to implement the target side of the equation:
Tada!
Anders,
RTF and HTML for
TDropComboTarget
?Thank you for your components. I find the RtfTarget demo interesting, the possibility to receive data, which the component does not provide as properties, rtf text in this case. For html text I have done a demo to receive html from
TDropURLTarget
. But is it possible to do the same forTDropComboTarget
? I would like to have rtf and html out ofTDropComboTarget
. Changing the component source would achive this, but is it possible to do this from the application side?I use D7.
Yes it is possible.
Please see the "Adapters" example application.
Very nice component pack.
I haven't been developing in Delphi 7 for several years but are now part of a project that step by step translates a very large app from Delphi to WPF. This is done by porting individual components and re-hosting them in Delphi via interop.
Using the drag drop package to elevate the events to COM level works great.
However, I have a minor things, that might spawn a small new feature.
When I drag an item from Delphi to the WPF component it expects the data to be of a specific format (actually, the dataformat tag to be set to a specific string) but the data itself is just generic text (xml).
So this means that I could be using the text component but then I have to add handling to the WPF component to allow an open 'text' data tag and for one reason or another the creators of that component would like to keep the id'ing tag as it is.
So the drag component needs to id the content correctly. Now, I guess that means I have to either create a sibling component to the text-one, or learn how to use the dataformatter — but for me it would be cool if the text component just had the option to have the set data tags to be overwritten or another component that accepts text etc but with a custom data tag.
Maybe I am making this too complicated for me… what is the recommended approach? It is a minor thing but I am not sure about the best solution path.
I'm not quite sure what you mean by the term "data tag" but I'm guessing it is just another term for "clipboard format name".
I think think the easiest approach would be to use the
TGenericDataFormat
class to add support for your special data format to one of the existing components. The Text components would probably be good candidates. Start by looking at the “CustomFormat1″ example as it does just that.You can use the “Drop Source Analyzer” application to determine the exact name of the clipboard format you need to implement, but let's say the name of your custom data format is "text". You'd add drop source support for this custom data format with the following code:
and use this to set the data before starting a drag:
The code for the drop target is similar:
Note that the
TGenericDataFormat.Data
property is an ansi string. If you need to transfer unicode string data (or arbitrary binary data) then you should use theSetDataHere
method:Hi, yes, I was referring to the dragdrop dataformat[s] that one uses when decoding the content to find out if the drop contains something of value to ones target.
Thank you so much for highlighting that approach — it is indeed the best and simplest way and very nicely done. It works great!
Hi Anders
Many thanks for your reply and apologies for the time I have taken to respond (difficulties loading Indy10 and I wanted to try your suggestions first).
First, my
OnEnter
andOnLeave
now seem to be working ok (I used your method of changing the background colour to prove it; I still don't see why the display of my message didn't work as I am only using synchronous operations). So please accept my apologies for making you go through your code.Prior to your response, I did get my program working as I wanted using DropFileSource and DropFileTarget. The only problem was that the cursor would stall over the windows explorer task bar icon as the files were created (one would need to keep the mouse down a long time for large transfers!).
After much trial and error, I have now managed to get the program to work using
TVirtualFileStreamDataFormat
(as in "AsyncSource with FileStreams" but synchronously) and this eliminates the stall. I thought I had then encountered an intractable problem in that while this works fine for files, I couldn't see anyway of copying empty folders. However, I've just found that by settingfaDirectory
in the file attributes, settingFD_ATTRIBUTES
indwflags
, and returningnil
as the stream inOnGetStream
, I can create empty folders in explorer. This allows me to mix files and folders in the same drag operation.Whether or not this works on versions of Windows after XP remains to be seen!
Many many thanks
Geoff
I need to allow drag&drop between my 2 application (from
TDBGrid
in application A toTEdit
in application B).How can I do it? Thank you for answer.
The demo applications should provide you with plenty of examples of how to do it.
If you have specific problems I'll be happy to help, but please use the tools available to you before you ask questions.
I have downloaded your demos. Could you help me which demo is the most suitable for me? Thank you.
It depends on what kind of data you need to transfer, but you should start with the SourceDemo and TargetDemo demos.
Then, if you need to drag something other than text, files, urls or bitmaps, take a look at the CustomFormat* demos.
If you need to drag large amounts of data (i.e. many bytes) or either the drop source or target is slow, you should look at the Async* demos.
Hello, I try to use your components to perform a drag and drop of the attached files from Outlook (V12/2007) in my delphi application but I can not.
Is what you could give me the solution?
Thank you.
Try the VirtualFile and VirtualFileStream examples.
Hello,
I use your great component with Delphi XE under Windows Server 2008 R2. Unfortunately, the drag/drop events do not occur. I tested some demo application but they do not react as expected either.
Any hints?
Thanks!
Be,
Jürgen Bauer
Please search the comments on this page for "UAC".
Hi,when I run the application without the Delphi IDE, it seems to work like expected.
Thanks!
Bye,
Jürgen
My guess is that the Delphi debugger runs the application with elevated privileges. Because of UAC you cannot drag from a non-elevated process (e.g. Explorer) to an elevated one (e.g. your application).
See:
Debugging a drag drop application with UAC enabled
Cannot drag and drop to debugged-application run from a privileged-run Visual Studio 2010
Anders, first congratulations that you started developing your components again! I was really sad when I saw that your site was down a few years ago, and that you stopped working on it. But a few months ago I accidentally went here and, boy, was I happy!
I have a small suggestion: I used the HTML property of the Combo component in the past, but it is now gone. I learned how to use the separate
HTMLClipboardFormat
class and it is working excellent, but there is a small issue with it. It uses the new UnicodeTStrings
class, however Firefox uses UTF8 texts. It is not a problem to do a conversion between them when I am using single character Windows code page (like Latin, Cyrillic and so on), but if Windows uses for example Chinese coding page, then the HTML gets messed up.Currently, I worked around it by adding an
UTF8String
property to theTHTMLClipboardFormat
and it works perfect. But generally, I don't want to mess with other people components, because it is a maintenance nightmare, so is there a chance that you add such properly in the next version officially?Since
THTMLClipboardFormat
uses UTF-8 strings anyway, I think it will be reasonable to use it in the component too.You are right - there is indeed a problem with the
THTMLClipboardFormat
class. The "HTML Format" clipboard format is always UTF8 encoded, both with IE and Firefox, but theTHTMLClipboardFormat
treats the data as ANSI and converts it to Unicode.I think the best way to solve this is with a breaking change:
Change the
THTMLClipboardFormat
class to derive fromTCustomUnicodeTextClipboardFormat
instead ofTCustomStringListClipboardFormat
.This will remove the "HTML" (TStrings) property. Instead the "Text" (UnicodeString) property will be used.Change the
THTMLDataFormat
class by removing the "HTML" (TStrings) property and replace it with a "Text" (UnicodeString) property.How does that sound?Hello,
I drop a message from Outlook2000 to OutlookDemo. When program wants to read this message i've a AV on this line in funtion
ViewMessage
I am under Windows XP and Delphi2009
Someone knows what is wong ?
Thanks for your help.
Is it compatible with Outlook 2010 64bit? I get an error when I run the Outlook demo "either there is no default mail client or …"Thanks
At present I'm unsure if that configuration is supported.
I'm not getting any errors when I try with Outlook 2010 on Win7×64, but I'm not getting any data either.
When I examine the dropped data using the SourceAnalyzer demo I can see that the "FileContents" data is empty. "FileContents" is the data format the outlook items are extracted from. The other data formats are mostly OK, so data is getting transferred - just not the data I need.
I'm not sure when I will have time to examine this problem in depth, so for now it might be better if you asked for help on StackOverflow or on the Outlook for Developers fora on MSDN. Dmitry Streblechenko will probably know the answer if you can catch his attention.
I just tried again with better luck. I don't know what's changed since yesterday.
I can now drag messages from Outlook 2010 on Win7 x64.
The SourceAnalyzer still doesn't work, but that is probably just because that it, unlike the classes used by OutlookDemo, doesn't do anything special to work around the known bugs in Outlook.
I have had no luck resolving this but have found the following http://msdn.microsoft.com/en-us/library/cc963763(office.14).aspx
Is perhaps the 'Mapi Stub' the solution - if so how would I implement it please (simple is good!)
Thanks
Please advise me with Delphi XE and Drag'n'Drop suite. I compile, run "SourceDemo" project (DragDrop\Demos\SourceDemo\) and try to move file from list to the root of D:\, but mouse shows me that I can't do it (mouse icon shows that I can't do it). If I start some application which accept files (MS Word for example), it accepts file withour problems.Please advise me what can it be? If I compile the same demo in Delphi 2010, this demo works correctly.
My OS is Win7 x86 SP1 Professional.
I have not been able to reproduce the problem with Delphi XE and Win7 x64 SP1.
I tried dragging to C:\ and apart from the ugly drag image and the file permission warning it succeeded.
I will investigate more next week.
Thank you for your answer! Possibly it was some temporary conflict in OS or some other software.
After I reboot my PC, application begin to drop files perfect and without problems.
Excellent!
Thanks for letting me know.
Hi,
Is possible change default system image (not cursor) when you drag file?
For example when you drag JPEG, system is using image preview insted .jpg icon.
I created custom image format and want to use dragged image thumbnail insted it icon (shell thumbnail handler not created, because I don't know how ;().
And second: after drag, in some cases I dispaly messagebox(), how to erase system image (see above)?
Hello Anders,
First, thanks for making such a great component! I don’t know what I’d do without it.
Second, I’ve ran into a problem which might be a memory leak in your component. I’m using a DropFileTarget with a DataFormatAdapter set to
TVirtualFileStreamDataFormat
format to be able to accept files from Outlook2007/2010. I’m saving it in a database with the following code:I’m using Eurekalog for memory leak detection and it threw up the following leak:
There is a comment in the code at the lines in question, but I don’t know if it’s related.
Could you please look into this if you have the time?
Thanks!
Hello Anders,
Firstly, thank you for publishing such an excellent package.
The project I am working on is to implement the shell DropTarget functionality as a replacement to the deprecated ddeexec functionality for opening files from explorer. The objective is for explorer to be able to open multiple files in a single instance of my application - for this, I have to use either ddeexec or DropTarget registry entries.
I have your TDropFilesTarget working nicely. In fact, to strip away any possible problems, I am just using your Simple Target Demo, which I have registered in the windows registry and have associated with a test file type with extension '.xyz'. With the Simple Target Demo running, dragging files onto the application works fine. However, with the Simple Target Demo not running, double clicking a .xyz file does launch the application, but the double-clicked file is not 'dropped' into the application. I see that the Simple Target Demo is launched by explorer with the '-embedding' parameter, so I believe I have configured the registry correctly. But explorer hangs for several seconds. I am guessing that explorer is waiting for the application to register in some way, so that it can then drop in the file. However the registration that makes the drop functionality work with a real drop done with the mouse, does not seem to be sufficient or equivalent for files dropped programmatically by explorer.
Am I doing something fundamentally wrong? Any suggestions are welcome.
Many thanks
Steve
P.S. The documentation I have used is here:
http://msdn.microsoft.com/en-us/library/ms683844(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ee872121(VS.85).aspx
Hello Anders
Firstly thank you for publishing this excellent package.
I have been tasked with the project of integrating drag and drop from Outlook and Thunderbird into an application. I have worked with your Outlook example and managed to use and change the code sufficiently for my drag and drop from Oulook but I am getting unstick with trying to drag and drop from Thunderbird. I am using the Tdataformatadapter with the Outlookdataformat but was hoping to trap the drop if it was coming from something else e.g. Thunderbird. Unfortunately I have had no luck. Can you provide an example or some direction on how I could trap drag and drop items from different email clients and then decide what to do from the result.
Many Thanks
Alan
In window 7, admin mode…Drag and drop does not support.
Please test SimpleTargetDemo on admin mode.
Hello Tommy Lee,
I am already running Windows 7 as an admin. Is this what you mean?
Steve
Dear Stephen Done
I am use Delphi 2010 and window 7, and test late version of your component.
Drag from file explore to application,
1. On Non admin authority, drag and drop work fine.
2. On Admin authority, does not work.
I think TDropFileTarget component have bug.
Dear Stephen Done
Pleaes execute by admin authority, I am also admin mode in win 7.
In same computer with delphi work fine.
But in another computer which does not installed delphi …. not work.
Ok, so you weren't replying to my post then. It is not me you want to be addressing, it is Anders - the Author of the suite. If you read this list of comments, there are other queries regarding admin privileges and drag/drop, so maybe look at previous postings on this page too.
Regards
Steve
Dear Anders,
First.. Thank you for your execllent suite.
I found bug conern admin privilage on window 7.
When you test another computer which does not installed delphi and execute by admin privilage.
Drag and drop from file explore to application does not support.
Ofcause non admin privilage execute work file.
Please check that bug
I hope this problem can fix as soon as possible.
Best regards
Tommy Lee.
Hi.
I hope I can get an answer to a problem I have with this (nice) VCL.
I have a main forma and a child form. In the create even pf the main form I have DropFileTarget.register (MainForm).
In the create event of the child for I register also few edit boxes.
My problem is that when I drag files over the main form it works UNTIL I move the mouse over one of those edit boxes (on the child form). At that moment I cannot drag and drop anymore into the main form - the cursor shape also indicates this.
To make it work, I have to move the mouse outside the main form and them move it back over the main form.
I removed all DropFileTarget's event handlers to make sure the problem is not there.
Hi Anders,
I also want to thank you for your great framework. I have an application that will have two drag sources targeting a Delphi tree view. I want to use a data adapter for Outlook as one source. For the second one I am trying to extend a TDropTextSource with my own Record. What design approach would you recommend?
Hi Anders,I am able to support the drag sources by the use of TDropTextSource, TDropTextTarget, and TDataFormatAdapter. The OnDrop event allows me to work with both types of drag sources.
Now I would like to delete from the mailbox the Outlook mail messages that are dropped. In general, messages should be moved to the Deleted folder. I assume that means exposing some additional functionality using MAPI. Do you have a recommendation of which one of your sources I should look at to add the message delete feature?
Hi, Anders,
I just switched from Delphi 2007 under Windows 2003/32bit to Delphi XE under Windows 2008/64bit.
Now my application does not support any drag/drop operation any more.
When I run my application under Windows 7/32bit, everything works as expected.
Any hints?
Bye,
Jürgen
Hi Anders,I was able to figure out which components to use (see my previous comment). I am using TDropTextSource, TDropTextTarget, and TDataFormatAdapter to provide the Outlook and extended text drop sources directed to my TreeView. I can handle both types of drops in the OnDrop and OnDragOver events of the target component.
I now would like to delete the mail message after successful drop. In Outlook terms, this probably means that it will be moved to your deleted folder. Which one of your sources do I need to enhance. I see there is an IMAPIFolder interface which provides a DeleteMessages method but I'm not sure if I should extend your TMessage class or implement a new one, something like a TMessageFolder, to provide support for this action. Ideas?
Solution DragDrop in windows 7 and Vista:
This is not only for this VERY GOOD Component from here, but for any application and any component !You may try for i.e. Total Commander:
UAC Enabled
Start TC as normal user
Start second instance "Run as Administrator"
In normal user you can drag and drop between Windows Explorer anything you want.From elewated (second instance TC) as administrator you can only drag. Nothing can be dropped.When UAC is disabled, there is no problems at all.Maybe is solution with registry changing, but this Component is work perfectly.
This component set looks just perfect.
Has anyone a simple test/demo project using C++ Builder 2007 so I can see how to use it.
Thank you
Hi, great thing …
… but any documentation?
Hu, I was looking for easy to use components, so I hope I just need two or three more expresso to see the tree of explanation in the forest of examples :-))
What's GetDataOnEnter for?
How can I set the the focus to the droped-on-component, even if I drag from an external application? (can I?)
Anyway.
thx for this component, I really like it.
I've found a solution for getting the focus (back) to my delphi app:
see http://www.swissdelphicenter.c.....php?id=261
I use the function SwitchToThisWindow from user32.dll. works fine with d5 and xp.
Hi,
I am just testing your great Drag/Drop component under Delphi XE.
When I run your demo app Drop Source Analyser and do a drag/drop from a Internet Explorer 9 window, no information can be retrieved.
With IE 8 or older the Drop Source Analyser can give me all the required information.
Any ideas?
Thanks,
Jürgen
Was your IE9 instance running in the "Trusted Sites" zone? If not, you have to set a special registry key to allow drag/drop of content out of Protected Mode.
Has anybody updated these components to work with Delphi XE2?
Yes, There were a few minor changes to incorporated. I found that info on a site by Graham Wideman. Contact me if you need help. bob at kondner dot com
I hope Anders is OK, it has been over two years since any feedback. This is a great tool, it needs only minor support but a whopper helping of knowhow.
Bob K.
Some folks had Email Probles so I put them on my site for download:
www.kondner.com/files/DragDrop_XE2_XE3.zip
A few people reported they worked ok on XE3 (I only have tried them on XE2).
Anders, I hope this is OK with you?
Thanks,
Bob Kondner
For XE4 there were some pointer type issues, I did a brute force cast in a few places.
Email me if you did the same. bob at kondner dot com
Bob K.