Microsoft & .NETVisual BasicUsing Explorer's File Copy Dialog Box

Using Explorer’s File Copy Dialog Box

Ever wanted to use the dialog box that appears when you do file operations
in Explorer? Well, it is not that hard to work, and can be used to provide some very neat
little features for your application. One little warning before we go too much further:
you can easily use this function to delete entire directories without any confirmation; I
recommend that you create some temporary directories that you can play about with, rather
than destroying any useful directories.

All the dialog boxes are based around one function, SHFileOperation. It is
very easy to use, and only has one parameter, a SHFILEOPSTRUCT user-defined type. Here are
the declarations that you will need:

Public Declare Function SHFileOperation Lib _
"shell32.dll" Alias "SHFileOperationA" _
(lpFileOp As Any) As LongPublic Declare Sub _
    SHFreeNameMappings Lib _
"shell32.dll" (ByVal hNameMappings As Long)

Public Declare Sub CopyMemory Lib "KERNEL32" _
Alias "RtlMoveMemory" (hpvDest As Any, hpvSource _
As Any, ByVal cbCopy As Long)Public Type SHFILEOPSTRUCT
hwnd As Long
wFunc As FO_Functions
pFrom As String
pTo As String
fFlags As FOF_Flags
fAnyOperationsAborted As Long
hNameMappings As Long
lpszProgressTitle As String 'only used if FOF_SIMPLEPROGRESS
End Type

Public Enum FO_Functions
FO_MOVE = &H1
FO_COPY = &H2
FO_DELETE = &H3
FO_RENAME = &H4
End Enum

Public Enum FOF_Flags
FOF_MULTIDESTFILES = &H1
FOF_CONFIRMMOUSE = &H2
FOF_SILENT = &H4
FOF_RENAMEONCOLLISION = &H8
FOF_NOCONFIRMATION = &H10
FOF_WANTMAPPINGHANDLE = &H20
FOF_ALLOWUNDO = &H40
FOF_FILESONLY = &H80
FOF_SIMPLEPROGRESS = &H100
FOF_NOCONFIRMMKDIR = &H200
FOF_NOERRORUI = &H400
FOF_NOCOPYSECURITYATTRIBS = &H800
FOF_NORECURSION = &H1000
FOF_NO_CONNECTED_ELEMENTS = &H2000
FOF_WANTNUKEWARNING = &H4000
End Enum

Public Type SHNAMEMAPPING
pszOldPath As String
pszNewPath As String
cchOldPath As Long
cchNewPath As Long
End Type

Calling is not quite as easy as it looks: the API function expects the UDT
to be byte aligned, but VB aligns the UDT in double byte boundaries. Therefore, we must
use a small workaround to get it to work properly:

Public Function SHFileOP(ByRef lpFileOp _
       As SHFileOpStruct) As Long
' This uses a method suggested at MSKB to 
' ensure that all parameters are passed correctly
' Call this wrapper rather than the API function 
' directly

Dim result As Long
Dim lenFileop As Long
Dim foBuf() As Byte

lenFileop = LenB(lpFileOp)
ReDim foBuf(1 To lenFileop) ' the size of the structure.

' Now we need to copy the structure into a byte array
Call CopyMemory(foBuf(1), lpFileOp, lenFileop)

' Next we move the last 12 bytes by 2 to byte align the data
Call CopyMemory(foBuf(19), foBuf(21), 12)
result = SHFileOperation(foBuf(1))

SHFileOP = result
End Function

Call this function instead of the API one, and it will correct the
problem, then make the call.

This is how the SHFILEOPSTRUCT works:

hwnd: a window handle of the owner of the dialog box. You should
set this to the hwnd of the form that is calling the box, although, you can set it to 0,
so that the desktop is the owner.

wFunc:
FO_COPY – Copies the files specified in the pFrom member to the location
specified in the pTo member.
FO_DELETE – Deletes the files specified in pFrom. (pTo is ignored.)
FO_MOVE – Moves the files specified in pFrom to the location specified in pTo.
FO_RENAME – Renames the files specified in pFrom.

pFrom: A string containing the names of the sources files and
directories. Separate multiple names by nulls (vbNullChar) and finish with two nulls. It
is important to remember this.

pTo: A string containing the name of the destination file or
directory. If only files are specified in pFrom, you can specify specific names in pTo,
again separated by nulls and ended with a double null.

fFlags: Flags that control the file operation. This member can be a
combination of the following flags, combined using the Or operator:

FOF_ALLOWUNDO – Preserve Undo information, if possible.
FOF_CONFIRMMOUSE – Not currently implemented.
FOF_FILESONLY – Perform the operation on files only if a wildcard file name (*.*)
is specified.
FOF_MULTIDESTFILES – 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_NOCONFIRMATION – Respond with Yes to All for any dialog box that is
displayed.
FOF_NOCONFIRMMKDIR – Does not confirm the creation of a new directory if the
operation requires one to be created.
FOF_NOCOPYSECURITYATTRIBS – Do not copy NT file Security Attributes.
FOF_NOERRORUI – No user interface will be displayed if an error occurs.
FOF_NORECURSION – Do not recurse directories (i.e. only operate on the
directories specified in pFrom, and not any subdirectories).
FOF_RENAMEONCOLLISION – 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_SILENT – Does not display a progress dialog box.
FOF_SIMPLEPROGRESS – Displays a progress dialog box but does not show the file
names.
FOF_WANTMAPPINGHANDLE – If FOF_RENAMEONCOLLISION is specified, the hNameMappings
member will be filled in if any files were renamed.

These two only apply in Internet Explorer 5 Environments:

FOF_NO_CONNECTED_ELEMENTS – Do not operate on connected elements

FOF_WANTNUKEWARNING – During delete operations, warn if
permanently deleting instead of placing in recycle bin (partially overrides FOF_NOCONFIRMATION)

fAnyOperationsAborted: Value that contains 0 if the operation was
not cancelled, otherwise, it contains a non-zero number.

hNameMappings: Handle to a file name mapping object that contains
an array of SHNAMEMAPPING structures. Each structure contains the old and new path names
for each file that was moved, copied, or renamed. This member is used only if the fFlags
member includes the FOF_WANTMAPPINGHANDLE flag. The handle must be freed by using the
SHFreeNameMappings function. The exact use of this is beyond the depth of this article.

lpszProgressTitle – A string to use as the title of a progress dialog box.
This member is used only if fFlags includes the FOF_SIMPLEPROGRESS flag.

For example to back up your documents and VB programs to a backup folder,
you could use this code:

Dim lret As Long
Dim fileop As SHFILEOPSTRUCT

With fileop
.hwnd = 0
.wFunc = FO_COPY
.pFrom = "C:Program FilesDevStudioVBMy Programs" & _
vbNullChar & "C:My Documents" & vbNullChar & vbNullChar
.pTo = "c:Backup of Documents" & vbNullChar & vbNullChar
.lpszProgressTitle = "Please wait, backing up..."
.fFlags = FOF_SIMPLEPROGRESS Or FOF_RENAMEONCOLLISION
End With

lret = SHFileOp(fileop)

If result <> 0 Then ' Operation failed
MsgBox Err.LastDllError 'Show the error returned from the API.
Else
If fileop.fAnyOperationsAborted <> 0 Then
MsgBox "Operation Failed"
End If
End If

To send this directory to the recycle bin when it is too old, you could
use this code:

Dim lret As Long
Dim fileop As SHFILEOPSTRUCT

With fileop
.hwnd = 0
.wFunc = FO_DELETE
.pFrom = "c:Backup of Documents" & vbNullChar & vbNullChar
.lpszProgressTitle = "Please wait, backing up..."
.fFlags = FOF_SIMPLEPROGRESS Or FOF_ALLOWUNDO
End With

lret = SHFileOp(fileop)

If result <> 0 Then ' Operation failed
MsgBox Err.LastDllError 'Show the error returned from the API.
Else
If fileop.fAnyOperationsAborted <> 0 Then
MsgBox "Operation Failed"
End If
End If

That just about wraps up the SHFileOperation function. Have an experiment
and a play about with it, and before long you will have the wonderful progress dialog box
seamlessly integrated into your application.

If you have any comments/suggestions/questions, please email me.

Get the Free Newsletter!
Subscribe to Developer Insider for top news, trends & analysis
This email address is invalid.
Get the Free Newsletter!
Subscribe to Developer Insider for top news, trends & analysis
This email address is invalid.

Latest Posts

Related Stories