/Src/Droppy/Utility/FileOperation.cs

https://github.com/dxm007/Droppy · C# · 253 lines · 130 code · 43 blank · 80 comment · 1 complexity · eeb754f1b6053a6b295404724c349218 MD5 · raw file

  1. //=================================================================================================
  2. //=================================================================================================
  3. //
  4. // Copyright (c) 2012 Dennis Mnuskin
  5. //
  6. // This file is part of Droppy application.
  7. //
  8. // This source code is distributed under the MIT license. For full text, see
  9. // http://www.opensource.org/licenses/mit-license.php Same text is found in LICENSE file which
  10. // is located in root directory of the project.
  11. //
  12. //=================================================================================================
  13. //=================================================================================================
  14. using System;
  15. using System.Collections;
  16. using System.Collections.Generic;
  17. using System.Collections.ObjectModel;
  18. using System.Linq;
  19. using System.Runtime.InteropServices;
  20. using System.Text;
  21. using System.Windows;
  22. using System.Windows.Interop;
  23. namespace Droppy
  24. {
  25. /// <summary>
  26. /// Part of IFileOperation, indicates which file operation to perform. See MSDN's
  27. /// documentation of SHFILEOPSTRUCT structure for detailed explanation of these flag values.
  28. /// </summary>
  29. enum FILEOP_CODES : uint
  30. {
  31. /// <summary>
  32. /// Move files specified in 'From' field of IFileOperation to 'To'
  33. /// </summary>
  34. FO_MOVE = 0x0001,
  35. /// <summary>
  36. /// Copies files specified in 'From' field of IFileOperation to 'To'
  37. /// </summary>
  38. FO_COPY = 0x0002,
  39. /// <summary>
  40. /// Deletes files specified in 'From' field of IFileOperation
  41. /// </summary>
  42. FO_DELETE = 0x0003,
  43. /// <summary>
  44. /// Renames the file specified in 'From' field of IFileOperation. This flag cannot be used
  45. /// to rename multiple files in a single IFileOperation call. Use FO_MOVE instead.
  46. /// </summary>
  47. FO_RENAME = 0x0004,
  48. }
  49. /// <summary>
  50. /// Flags that control the behavior of IFileOperation object. See MSDN's documentation of
  51. /// SHFILEOPSTRUCT structure for detailed explanation of these flag values.
  52. /// </summary>
  53. [Flags]
  54. enum FILEOP_FLAGS
  55. {
  56. FOF_MULTIDESTFILES = 0x00000001,
  57. FOF_CONFIRMMOUSE = 0x00000002,
  58. FOF_SILENT = 0x00000004,
  59. FOF_RENAMEONCOLLISION = 0x00000008,
  60. FOF_NOCONFIRMATION = 0x00000010,
  61. FOF_WANTMAPPINGHANDLE = 0x00000020,
  62. FOF_ALLOWUNDO = 0x00000040,
  63. FOF_FILESONLY = 0x00000080,
  64. FOF_SIMPLEPROGRESS = 0x00000100,
  65. FOF_NOCONFIRMMKDIR = 0x00000200,
  66. FOF_NOERRORUI = 0x00000400,
  67. FOF_NOCOPYSECURITYATTRIBS = 0x00000800,
  68. FOF_NORECURSION = 0x00001000, /* don't do recursion into directories */
  69. FOF_NO_CONNECTED_ELEMENTS = 0x00002000, /* don't do connected files */
  70. FOF_WANTNUKEWARNING = 0x00004000, /* during delete operation, warn if delete instead
  71. of recycling (even if FOF_NOCONFIRMATION) */
  72. FOF_NORECURSEREPARSE = 0x00008000,
  73. // Flags below are available when using 2nd gne of
  74. // file operation (IFileOperation COM-based)
  75. FOFX_NOSKIPJUNCTIONS = 0x00010000,
  76. FOFX_PREFERHARDLINK = 0x00020000,
  77. FOFX_SHOWELEVATIONPROMPT = 0x00040000,
  78. FOFX_EARLYFAILURE = 0x00100000,
  79. FOFX_PRESERVEFILEEXTENSIONS = 0x00200000,
  80. FOFX_KEEPNEWERFILE = 0x00400000,
  81. FOFX_NOCOPYHOOKS = 0x00800000,
  82. FOFX_NOMINIMIZEBOX = 0x01000000,
  83. FOFX_MOVEACLSACROSSVOLUMES = 0x02000000,
  84. FOFX_DONTDISPLAYSOURCEPATH = 0x04000000,
  85. FOFX_DONTDISPLAYDESTPATH = 0x08000000,
  86. }
  87. /// <summary>
  88. /// Implemented by an object which supports Windows shell file operation.
  89. /// </summary>
  90. interface IFileOperation
  91. {
  92. /// <summary>
  93. /// Ges/sets parent window for the file operation dialog if one is to be displayed
  94. /// </summary>
  95. Window ParentWindow { get; set; }
  96. /// <summary>
  97. /// Gets/sets a flag which indicates which operation to perform
  98. /// </summary>
  99. FILEOP_CODES Operation { get; set; }
  100. /// <summary>
  101. /// Gets/sets flags which control the behavior of the file operation
  102. /// </summary>
  103. FILEOP_FLAGS Flags { get; set; }
  104. /// <summary>
  105. /// Gets/sets a list of files to move, copy or delete. Wildcard characters are allowed
  106. /// in the file portion of each path.
  107. /// </summary>
  108. string[] From { get; set; }
  109. /// <summary>
  110. /// Gets/sets a list of destination directories. Multiple directories can be specified
  111. /// if FOF_MULTIDESTFILES flag is passed in.
  112. /// </summary>
  113. string[] To { get; set; }
  114. /// <summary>
  115. /// After file operation completes, this member is set to true if a file operation was
  116. /// aborted by the user.
  117. /// </summary>
  118. bool AnyOpAborted { get; }
  119. /// <summary>
  120. /// This property is not currently supported. DO NOT USE IT.
  121. /// </summary>
  122. Dictionary< string, string >[] NameMappings { get; }
  123. /// <summary>
  124. /// Gets/sets a title of a progress dialog box. This property is only used if
  125. /// FOF_SIMPLEPROGRESS flag is specified
  126. /// </summary>
  127. string ProgressTitle { get; set; }
  128. /// <summary>
  129. /// Called to invoke file operation after other properties of this interface have been
  130. /// filled in.
  131. /// </summary>
  132. void Execute();
  133. }
  134. /// <summary>
  135. /// Implements Windows Shell file operation using first generation of file operation method.
  136. /// For more information about capabilities and use of this class, see MSDN Library's
  137. /// documentation of SHFileOperation functions.
  138. /// </summary>
  139. class FileOperationG1 : IFileOperation
  140. {
  141. #region ----------------------- Public Members ------------------------
  142. /// <summary>
  143. /// Default constructor
  144. /// </summary>
  145. public FileOperationG1()
  146. {
  147. _isAnyOpAborted = false;
  148. }
  149. #region - - - - - - - IFileOperation Interface - - - - - - - - - - - -
  150. public Window ParentWindow { get; set; }
  151. public FILEOP_CODES Operation { get; set; }
  152. public FILEOP_FLAGS Flags { get; set; }
  153. public string[] From { get; set; }
  154. public string[] To { get; set; }
  155. public bool AnyOpAborted { get { return _isAnyOpAborted; } }
  156. public Dictionary< string, string >[] NameMappings { get { return null; } }
  157. public string ProgressTitle { get; set; }
  158. public void Execute()
  159. {
  160. WindowInteropHelper wih = new WindowInteropHelper( ParentWindow );
  161. SHFILEOPSTRUCT fileOp = new SHFILEOPSTRUCT();
  162. if( this.Flags.HasFlag( FILEOP_FLAGS.FOF_WANTMAPPINGHANDLE ) )
  163. {
  164. throw new NotImplementedException();
  165. }
  166. fileOp.hwnd = wih.Handle;
  167. fileOp.wFunc = Convert.ToInt32( this.Operation );
  168. fileOp.pFrom = ArrayToMultiString( this.From );
  169. fileOp.pTo = ArrayToMultiString( this.To );
  170. fileOp.fAnyOperationAborted = 0;
  171. fileOp.fFlags = Convert.ToInt16( this.Flags );
  172. fileOp.hNameMapping = IntPtr.Zero;
  173. fileOp.lpszProgressTitle = this.ProgressTitle;
  174. int res = SHFileOperation( ref fileOp );
  175. }
  176. #endregion
  177. #endregion
  178. #region ----------------------- Private Members -----------------------
  179. private string ArrayToMultiString( string[] strings )
  180. {
  181. StringBuilder sb = new StringBuilder();
  182. foreach( var s in strings )
  183. {
  184. sb.Append( s ).Append( '\0' );
  185. }
  186. return sb.ToString();
  187. }
  188. #region - - - - - - - Shell API Interop - - - - - - - - - - - - - - - -
  189. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  190. private struct SHFILEOPSTRUCT
  191. {
  192. public IntPtr hwnd;
  193. public Int32 wFunc;
  194. [MarshalAs(UnmanagedType.LPWStr)]
  195. public String pFrom;
  196. [MarshalAs(UnmanagedType.LPWStr)]
  197. public String pTo;
  198. public Int16 fFlags; // zero or more FILEOP_FLAGS values (lower 16-bit only)
  199. public Int32 fAnyOperationAborted;
  200. public IntPtr hNameMapping;
  201. [MarshalAs(UnmanagedType.LPWStr)]
  202. public String lpszProgressTitle;
  203. }
  204. [DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
  205. private static extern Int32 SHFileOperation( ref SHFILEOPSTRUCT lpFileOp );
  206. #endregion
  207. private bool _isAnyOpAborted;
  208. #endregion
  209. }
  210. }