Click here to Skip to main content
15,892,927 members
Articles / Programming Languages / C#

C# does Shell, Part 4

Rate me:
Please Sign up or sign in to vote.
4.93/5 (84 votes)
26 Mar 2003Ms-PL14 min read 290.4K   4.7K   165  
This article is about the AutoComplete features enabled by windows and how to use them with C#. AutoComplete is the ability to expand strings written in an edit box. The article will develop a class for using this functionality in you applications.
using System;
using System.Runtime.InteropServices;

namespace ShellLib
{
	public class ShellFileOperation
	{
		public enum FileOperations
		{
			FO_MOVE           = 0x0001,		// Move the files specified in pFrom to the location specified in pTo. 
			FO_COPY           = 0x0002,		// Copy the files specified in the pFrom member to the location specified 
			// in the pTo member. 
			FO_DELETE         = 0x0003,		// Delete the files specified in pFrom. 
			FO_RENAME         = 0x0004		// Rename the file specified in pFrom. You cannot use this flag to rename 
			// multiple files with a single function call. Use FO_MOVE instead. 
		}

		[Flags]
		public enum ShellFileOperationFlags
		{
			FOF_MULTIDESTFILES         = 0x0001,	// The pTo member specifies multiple destination files (one for 
			// each source file) rather than one directory where all source 
			// files are to be deposited. 
			FOF_CONFIRMMOUSE           = 0x0002,	// Not currently used. 
			FOF_SILENT                 = 0x0004,	// Do not display a progress dialog box. 
			FOF_RENAMEONCOLLISION      = 0x0008,	// Give the file being operated on a new name in a move, copy, or 
			// rename operation if a file with the target name already exists. 
			FOF_NOCONFIRMATION         = 0x0010,	// Respond with "Yes to All" for any dialog box that is displayed. 
			FOF_WANTMAPPINGHANDLE      = 0x0020,	// If FOF_RENAMEONCOLLISION is specified and any files were renamed,
			// assign a name mapping object containing their old and new names 
			// to the hNameMappings member.
			FOF_ALLOWUNDO              = 0x0040,	// Preserve Undo information, if possible. If pFrom does not 
			// contain fully qualified path and file names, this flag is ignored. 
			FOF_FILESONLY              = 0x0080,	// Perform the operation on files only if a wildcard file 
			// name (*.*) is specified. 
			FOF_SIMPLEPROGRESS         = 0x0100,	// Display a progress dialog box but do not show the file names. 
			FOF_NOCONFIRMMKDIR         = 0x0200,	// Do not confirm the creation of a new directory if the operation
			// requires one to be created. 
			FOF_NOERRORUI              = 0x0400,	// Do not display a user interface if an error occurs. 
			FOF_NOCOPYSECURITYATTRIBS  = 0x0800,	// Do not copy the security attributes of the file.
			FOF_NORECURSION            = 0x1000,	// Only operate in the local directory. Don't operate recursively
			// into subdirectories.
			FOF_NO_CONNECTED_ELEMENTS  = 0x2000,	// Do not move connected files as a group. Only move the 
			// specified files. 
			FOF_WANTNUKEWARNING        = 0x4000,	// Send a warning if a file is being destroyed during a delete 
			// operation rather than recycled. This flag partially 
			// overrides FOF_NOCONFIRMATION.
			FOF_NORECURSEREPARSE       = 0x8000		// Treat reparse points as objects, not containers.

		}
		
		[Flags]
		public enum ShellChangeNotificationEvents : uint
		{
			SHCNE_RENAMEITEM          = 0x00000001,	// The name of a nonfolder item has changed. SHCNF_IDLIST or 
													// SHCNF_PATH must be specified in uFlags. dwItem1 contains the 
													// previous PIDL or name of the item. dwItem2 contains the new PIDL
													// or name of the item. 
			SHCNE_CREATE              = 0x00000002,	// A nonfolder item has been created. SHCNF_IDLIST or SHCNF_PATH 
													// must be specified in uFlags. dwItem1 contains the item that was 
													// created. dwItem2 is not used and should be NULL. 
			SHCNE_DELETE              = 0x00000004,	// A nonfolder item has been deleted. SHCNF_IDLIST or SHCNF_PATH
													// must be specified in uFlags. dwItem1 contains the item that was 
													// deleted. dwItem2 is not used and should be NULL. 
			SHCNE_MKDIR               = 0x00000008,	// A folder has been created. SHCNF_IDLIST or SHCNF_PATH must be 
													// specified in uFlags. dwItem1 contains the folder that was 
													// created. dwItem2 is not used and should be NULL. 
			SHCNE_RMDIR               = 0x00000010,	// A folder has been removed. SHCNF_IDLIST or SHCNF_PATH must be 
													// specified in uFlags. dwItem1 contains the folder that was 
													// removed. dwItem2 is not used and should be NULL. 
			SHCNE_MEDIAINSERTED       = 0x00000020,	// Storage media has been inserted into a drive. SHCNF_IDLIST or
													// SHCNF_PATH must be specified in uFlags. dwItem1 contains the root
													// of the drive that contains the new media. dwItem2 is not used 
													// and should be NULL. 
			SHCNE_MEDIAREMOVED        = 0x00000040,	// Storage media has been removed from a drive. SHCNF_IDLIST or 
													// SHCNF_PATH must be specified in uFlags. dwItem1 contains the root
													// of the drive from which the media was removed. dwItem2 is not 
													// used and should be NULL. 
			SHCNE_DRIVEREMOVED        = 0x00000080,	// A drive has been removed. SHCNF_IDLIST or SHCNF_PATH must be 
													// specified in uFlags. dwItem1 contains the root of the drive that
													// was removed. dwItem2 is not used and should be NULL. 
			SHCNE_DRIVEADD            = 0x00000100,	// A drive has been added. SHCNF_IDLIST or SHCNF_PATH must be 
													// specified in uFlags. dwItem1 contains the root of the drive that
													// was added. dwItem2 is not used and should be NULL. 
			SHCNE_NETSHARE            = 0x00000200,	// A folder on the local computer is being shared via the network.
													// SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1
													// contains the folder that is being shared. dwItem2 is not used and
													// should be NULL. 
			SHCNE_NETUNSHARE          = 0x00000400,	// A folder on the local computer is no longer being shared via the
													// network. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. 
													// dwItem1 contains the folder that is no longer being shared. 
													// dwItem2 is not used and should be NULL. 
			SHCNE_ATTRIBUTES          = 0x00000800,	// The attributes of an item or folder have changed. SHCNF_IDLIST
													// or SHCNF_PATH must be specified in uFlags. dwItem1 contains the
													// item or folder that has changed. dwItem2 is not used and should
													// be NULL. 
			SHCNE_UPDATEDIR           = 0x00001000,	// The contents of an existing folder have changed, but the folder
													// still exists and has not been renamed. SHCNF_IDLIST or SHCNF_PATH
													// must be specified in uFlags. dwItem1 contains the folder that 
													// has changed. dwItem2 is not used and should be NULL. If a folder
													// has been created, deleted, or renamed, use SHCNE_MKDIR, 
													// SHCNE_RMDIR, or SHCNE_RENAMEFOLDER, respectively, instead. 
			SHCNE_UPDATEITEM          = 0x00002000,	// An existing nonfolder item has changed, but the item still exists
													// and has not been renamed. SHCNF_IDLIST or SHCNF_PATH must be 
													// specified in uFlags. dwItem1 contains the item that has changed.
													// dwItem2 is not used and should be NULL. If a nonfolder item has 
													// been created, deleted, or renamed, use SHCNE_CREATE, 
													// SHCNE_DELETE, or SHCNE_RENAMEITEM, respectively, instead. 
			SHCNE_SERVERDISCONNECT    = 0x00004000,	// The computer has disconnected from a server. SHCNF_IDLIST or 
													// SHCNF_PATH must be specified in uFlags. dwItem1 contains the 
													// server from which the computer was disconnected. dwItem2 is not
													// used and should be NULL.
			SHCNE_UPDATEIMAGE         = 0x00008000,	// An image in the system image list has changed. SHCNF_DWORD must be 
													// specified in uFlags. dwItem1 contains the index in the system image 
													// list that has changed. dwItem2 is not used and should be NULL. 
			SHCNE_DRIVEADDGUI         = 0x00010000,	// A drive has been added and the Shell should create a new window
													// for the drive. SHCNF_IDLIST or SHCNF_PATH must be specified in 
													// uFlags. dwItem1 contains the root of the drive that was added. 
													// dwItem2 is not used and should be NULL. 
			SHCNE_RENAMEFOLDER        = 0x00020000,	// The name of a folder has changed. SHCNF_IDLIST or SHCNF_PATH must
													// be specified in uFlags. dwItem1 contains the previous pointer to
													// an item identifier list (PIDL) or name of the folder. dwItem2 
													// contains the new PIDL or name of the folder. 
			SHCNE_FREESPACE           = 0x00040000,	// The amount of free space on a drive has changed. SHCNF_IDLIST or
													// SHCNF_PATH must be specified in uFlags. dwItem1 contains the root
													// of the drive on which the free space changed. dwItem2 is not used
													// and should be NULL. 
			SHCNE_EXTENDED_EVENT      = 0x04000000,	// Not currently used. 
			SHCNE_ASSOCCHANGED        = 0x08000000,	// A file type association has changed. SHCNF_IDLIST must be 
													// specified in the uFlags parameter. dwItem1 and dwItem2 are not
													// used and must be NULL. 
			SHCNE_DISKEVENTS          = 0x0002381F,	// Specifies a combination of all of the disk event identifiers. 
			SHCNE_GLOBALEVENTS        = 0x0C0581E0,	// Specifies a combination of all of the global event identifiers. 
			SHCNE_ALLEVENTS           = 0x7FFFFFFF,	// All events have occurred. 
			SHCNE_INTERRUPT           = 0x80000000	// The specified event occurred as a result of a system interrupt.
													// As this value modifies other event values, it cannot be used alone.
		}


		public enum ShellChangeNotificationFlags
		{
			SHCNF_IDLIST		= 0x0000,	// dwItem1 and dwItem2 are the addresses of ITEMIDLIST structures that
											// represent the item(s) affected by the change. Each ITEMIDLIST must be 
											// relative to the desktop folder. 
			SHCNF_PATHA			= 0x0001,	// dwItem1 and dwItem2 are the addresses of null-terminated strings of 
											// maximum length MAX_PATH that contain the full path names of the items 
											// affected by the change. 
			SHCNF_PRINTERA		= 0x0002,	// dwItem1 and dwItem2 are the addresses of null-terminated strings that 
											// represent the friendly names of the printer(s) affected by the change. 
			SHCNF_DWORD			= 0x0003,	// The dwItem1 and dwItem2 parameters are DWORD values. 
			SHCNF_PATHW			= 0x0005,	// like SHCNF_PATHA but unicode string
			SHCNF_PRINTERW		= 0x0006,	// like SHCNF_PRINTERA but unicode string
			SHCNF_TYPE			= 0x00FF,	
			SHCNF_FLUSH			= 0x1000,	// The function should not return until the notification has been delivered 
											// to all affected components. As this flag modifies other data-type flags,
											// it cannot by used by itself.
			SHCNF_FLUSHNOWAIT	= 0x2000	// The function should begin delivering notifications to all affected 
											// components but should return as soon as the notification process has
											// begun. As this flag modifies other data-type flags, it cannot by used 
											// by itself.
		}

		// properties
		public FileOperations Operation;
		public IntPtr OwnerWindow;
		public ShellFileOperationFlags OperationFlags;
		public String ProgressTitle;
		public String[] SourceFiles;
		public String[] DestFiles;

		public ShellFileOperation()
		{
			// set default properties
			Operation = FileOperations.FO_COPY;
			OwnerWindow = IntPtr.Zero;
			OperationFlags = ShellFileOperationFlags.FOF_ALLOWUNDO 
				| ShellFileOperationFlags.FOF_MULTIDESTFILES
				| ShellFileOperationFlags.FOF_NO_CONNECTED_ELEMENTS
				| ShellFileOperationFlags.FOF_WANTNUKEWARNING;
			ProgressTitle = "";
		}

		public bool DoOperation()
		{
			ShellApi.SHFILEOPSTRUCT FileOpStruct = new ShellApi.SHFILEOPSTRUCT();
			
			FileOpStruct.hwnd = OwnerWindow;
			FileOpStruct.wFunc = (uint)Operation;

			String multiSource = StringArrayToMultiString(SourceFiles);
			String multiDest = StringArrayToMultiString(DestFiles);
			FileOpStruct.pFrom = Marshal.StringToHGlobalUni(multiSource);
			FileOpStruct.pTo = Marshal.StringToHGlobalUni(multiDest);
			
			FileOpStruct.fFlags = (ushort)OperationFlags;
			FileOpStruct.lpszProgressTitle = ProgressTitle;
			FileOpStruct.fAnyOperationsAborted = 0;
			FileOpStruct.hNameMappings = IntPtr.Zero;

			int RetVal;
			RetVal = ShellApi.SHFileOperation(ref FileOpStruct);
			
			ShellApi.SHChangeNotify(
				(uint)ShellChangeNotificationEvents.SHCNE_ALLEVENTS,
				(uint)ShellChangeNotificationFlags.SHCNF_DWORD,
				IntPtr.Zero,
				IntPtr.Zero);

			if (RetVal!=0)
				return false;

			if (FileOpStruct.fAnyOperationsAborted != 0)
				return false;

			return true;
		}
		
		private String StringArrayToMultiString(String[] stringArray)
		{
			String multiString = "";

			if (stringArray == null)
				return "";

			for (int i=0 ; i<stringArray.Length ; i++)
				multiString += stringArray[i] + '\0';
			
			multiString += '\0';
			
			return multiString;
		}
	}

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
Software Developer (Senior) Verint
Israel Israel
Arik Poznanski is a senior software developer at Verint. He completed two B.Sc. degrees in Mathematics & Computer Science, summa cum laude, from the Technion in Israel.

Arik has extensive knowledge and experience in many Microsoft technologies, including .NET with C#, WPF, Silverlight, WinForms, Interop, COM/ATL programming, C++ Win32 programming and reverse engineering (assembly, IL).

Comments and Discussions