![]() |
Languages »
C# »
Windows Forms
Intermediate
License: The Code Project Open License (CPOL)
Drag and Drop files from Windows Explorer to Windows FormBy Alex FrHow to open files dropped from Explorer to a Windows Form |
C#, Windows, .NET 1.0, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
If we have a Windows Forms application which has File -> Open functionality, adding a few lines of code allows the user to open files dragged from the Windows Explorer. This article describes how to add this feature to your application.
Suppose we have simple image viewer program (demo project DropFiles).
When tje user selects File -> Open, it shows the 'Open File' dialog:
private void mnuFileOpen_Click(object sender, System.EventArgs e) { // Show Open File dialog OpenFileDialog openDlg = new OpenFileDialog(); openDlg.Filter = "Jpeg files (*.jpg)|*.jpg|Bitmap files (*.bmp)|" + *.bmp|All Files (*.*)|*.*"; openDlg.FileName = "" ; openDlg.CheckFileExists = true; openDlg.CheckPathExists = true; if ( openDlg.ShowDialog() != DialogResult.OK ) return; OpenFile(openDlg.FileName); }The function
OpenFile loads the image file to a class member Bitmap
m_Bitmap, and the Paint event handler shows this bitmap on the
screen:
private Bitmap m_Bitmap; private void OpenFile(string sFile) { Bitmap bmp; try { // load bitmap from file bmp = (Bitmap)Bitmap.FromFile(sFile, false); if ( bmp != null ) { // Keep bitmap in class member m_Bitmap = (Bitmap) bmp.Clone(); // Set Autoscroll properties this.AutoScroll = true; this.AutoScrollMinSize = new Size ( m_Bitmap.Width, m_Bitmap.Height); // draw image Invalidate(); } } catch (Exception ex) { MessageBox.Show( this, ex.Message, "Error loading from file"); } } private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { if ( m_Bitmap != null ) { e.Graphics.DrawImage( m_Bitmap, new Rectangle(this.AutoScrollPosition.X, this.AutoScrollPosition.Y, m_Bitmap.Width, m_Bitmap.Height)); } }To open files dropped from the Windows Explorer we need to set the form
AllowDrop
property to true. After this add the DragEnter and DragDrop
event handlers.
DragEnter handler is simple - program accepts only files:
private void Form1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy; else e.Effect = DragDropEffects.None; }
The DragEventArgs.GetData function returns an IDataObject
interface that contains the data associated with this DragDrop
event. When a file or files are dropped from Explorer to the form, IDataObject
contains an array of file names. If one file is dropped, the array contains one
element. All the time the DragDrop event handler is working, the Windows
Explorer instance is not responding. Therefore, we need to call the OpenFile
function asynchronously. This is done using the BeginInvoke function and
a delegate pointing to OpenFile. It is a good idea also to move the
form to the foreground after dropping file to it.
private delegate void DelegateOpenFile(String s); // type private DelegateOpenFile m_DelegateOpenFile; // instance private void Form1_Load(object sender, System.EventArgs e) { // create delegate used for asynchronous call m_DelegateOpenFile = new DelegateOpenFile(this.OpenFile); } private void Form1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) { try { Array a = (Array)e.Data.GetData(DataFormats.FileDrop); if ( a != null ) { // Extract string from first array element // (ignore all files except first if number of files are dropped). string s = a.GetValue(0).ToString(); // Call OpenFile asynchronously. // Explorer instance from which file is dropped is not responding // all the time when DragDrop handler is active, so we need to return // immidiately (especially if OpenFile shows MessageBox). this.BeginInvoke(m_DelegateOpenFile, new Object[] {s}); this.Activate(); // in the case Explorer overlaps this form } } catch (Exception ex) { Trace.WriteLine("Error in DragDrop function: " + ex.Message); // don't show MessageBox here - Explorer is waiting ! } }This is all we need to implement Drag-and-Drop capability in Windows Forms application. However, good programming style requires writing the wrapper class which encapsulates this feature.
DropFiles1 opens files dropped from
Explorer using helper class DragDropManager. The project is very
simple - it allows you to open one or more files and shows the file names in listbox. It
has mnuFileOpen_Click function which shows Open File dialog and
calls OpenFiles(Array a) passing array of file names selected by
user.
Form that uses DragDropManager should implement IDropFileTarget
interface defined in the same file as DragDropManager:
public interface IDropFileTarget { void OpenFiles(System.Array a); }So, main form is derived from
IDropFileTarget:
public class Form1 : System.Windows.Forms.Form, IDropFileTargetand has OpenFiles function which opens files selected from File - Open dialog or dropped from Windows Explorer:
public void OpenFiles(Array a) { // If our application can open only one file, we can process // here only first element of array or give some error message // in the case array contains more than one file. // // In this sample I allow to open number of files showing // their names in list box. string sError = ""; string sFile; lstFiles.Items.Clear(); // process all files in array for ( int i = 0; i < a.Length; i++ ) { sFile = a.GetValue(i).ToString(); // file name // Check file name // (Let's say we don't accept non-existing files or directories) FileInfo info = new FileInfo(sFile); if ( ! info.Exists ) { sError += "\nIncorrect file name: " + sFile; } else { lstFiles.Items.Add(sFile); } } if ( sError.Length > 0 ) MessageBox.Show(this, sError, "Open File Error"); }The Form has the member
private DragDropManager m_DragDropManager;
which is initialized in Load event handler:
private void Form1_Load(object sender, System.EventArgs e) { m_DragDropManager = new DragDropManager(); m_DragDropManager.Parent = this; }So, the steps that should be done for using
DragDropManager class
in Windows Form are:IDropFileTarget interface;IDropFileTarget interface adding function OpenFiles(Array
a);DragDropManager type to the form;Parent property to form reference.
private Form m_parent; // reference to owner form private delegate void DelegateOpenFiles(Array a); // type private DelegateOpenFiles m_DelegateOpenFiles; // instanceInitialization is done when client sets
Parent property:
public Form Parent { set { m_parent = value; // keep reference to owner form // Check if owner form implements IDropFileTarget interface if ( ! ( m_parent is IDropFileTarget ) ) { throw new Exception( "DragDropManager: Parent form doesn't implement IDropFileTarget interface"); } // create delegate used for asynchronous call m_DelegateOpenFiles = new DelegateOpenFiles(((IDropFileTarget)m_parent).OpenFiles); // ensure that owner form allows dropping m_parent.AllowDrop = true; // subscribe to owner form's drag-drop events m_parent.DragEnter += new System.Windows.Forms.DragEventHandler(this.OnDragEnter); m_parent.DragDrop += new System.Windows.Forms.DragEventHandler(this.OnDragDrop); } }
OnDragEnter and OnDragDrop are subscribed to owner
form DragEnter and DragDrop events:
private void OnDragEnter(object sender, System.Windows.Forms.DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy; else e.Effect = DragDropEffects.None; } private void OnDragDrop(object sender, System.Windows.Forms.DragEventArgs e) { try { Array a = (Array)e.Data.GetData(DataFormats.FileDrop); if ( a != null ) { // Call owner's OpenFiles asynchronously. m_parent.BeginInvoke(m_DelegateOpenFiles, new Object[] {a}); m_parent.Activate(); // in the case Explorer overlaps owner form } } catch (Exception ex) { Trace.WriteLine("Error in DragDropManager.OnDragDrop function: " + ex.Message); } }
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 31 Jan 2003 Editor: Chris Maunder |
Copyright 2003 by Alex Fr Everything else Copyright © CodeProject, 1999-2009 Web22 | Advertise on the Code Project |