I was inspired by Ahmad Shyazli's DragEdit on CodeGuru.
Ahmad took the usual MFC approach and created a class derived from CEdit. I thought I could do it with my usual one-function approach and had a quick hack last night.
The result is a single function call to allow you to get file or folder names from files or folders dropped onto your edit control.
I used Ahmad's code as the basis for mine. However, I extended it by adding some features I thought might be useful. Using the code attached you can now have multiple files/folders, files, folders or both and optionally have shortcuts resolved.
It couldn't be much simpler, honestly I tried.
Add the files EnableDragEdit.h and EnableDragEdit.cpp into your library or right into application.
Next, to allow your edit control to recieve files add the following code to your
EnableDragEdit( GetDlgItem( IDC_EDIT ), uFlags );
uFlags can be a combination of the following:
- Enable the edit to accept files.
- Enable the edit to accept folders.
- Enable multiple files/folders.
- Expand shortcuts to their real-deal files/folder.
- When dropping file/folder add them to the edit rather than replacing the current content.
About the code - how does it work
Edit controls don't normally accept files dropped onto them. To enable any window to accept files being dropped on them you need to call
DragAcceptFiles. It's a simple yes/no function so calling it isn't complex in any way.
Once you have said you are willing to accept dropped files you wait...for a
WM_DROPFILES windows message.
Because I wanted just a single function API to enable edit controls to accept dropped files I needed to subclass the edit window, which I do in the function
EnableDragEdit. The subclass code is pretty simply stuff. Note that I also create a data structure and associate it with the window. It's a simple structure that has just one member - I left it as a structure so the whole show would be easier to extend later on...I knew you'd ask.
Again, the subclassed window procedure is basic stuff. We process the messages we are interested in and pass on everything else. No rocket science, but a decent and simple example of subclassing without MFC!
The interesting function is
OnDrop because it is the core of our feature. Without it we'd have nothing but an empty and useless subclass. There's plenty of comments in the code explaining what's what so I won't bore you with the details. But in summary; We get a
WM_DROPFILES message and along with it we get a handle. We use pass handle to
DragQueryFile to find out how many files are available in the drag operation, we have similar code to actually acquire the file names.
DragQueryFile is one of the worst multi-function interfaces I've seen this side of
realloc (which I also use!).
We basically iterate over the files using
DragQueryFile and add to them our string. We test each file against our options and make the required adjustments - plenty of comments should make it easy for you to modify this to meet your needs.
ExpandShortcut has a couple of issues. The first is for unicode, note the conditional code. The second is for zero length files, which I just stumbled across. I think it's a bug but your opinion may differ. If I passed a zero length file to
IShellLink and then used
GetPath it would say it was successful but would give a blank filename. I worked around this by using a quick test to see if the file length is zero.
IShellLink correctly fails when the file length is anything other than zero. Is there a better way to resolve a link?
Note: This has been tested on Windows 2000 only. It has been compiled for both ansi and unicode with level 4 warnings using MSVC 6.0.