一般要处理复制档案使用 File.Copy 方法就可以达到需求,可是若在复制档案过程中要显示进度及取消复制,就需要使用 API 函数 CopyFileEx 来处理。下列范例程序使用 CoypFileEx 来进行复制档案,复制过程序会显示进度,按下「取消复制」钮可中断复制动作。
Imports System.Runtime.InteropServices
Public Class Form1
Private pbCancel As Int32
<DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function CopyFileEx( _
ByVal lpExistingFileName As String, _
ByVal lpNewFileName As String, _
ByVal lpProgressRoutine As CopyProgressRoutine, _
ByVal lpData As IntPtr, _
ByRef pbCancel As Int32, _
ByVal dwCopyFlags As ECopyFileFlags) As Boolean
End Function
''' <summary>
''' 執行 CopyFileEx 方法的回呼函式定義。
''' </summary>
Delegate Function CopyProgressRoutine( _
ByVal TotalFileSize As Long, _
ByVal TotalBytesTransferred As Long, _
ByVal StreamSize As Long, _
ByVal StreamBytesTransferred As Long, _
ByVal dwStreamNumber As UInteger, _
ByVal dwCallbackReason As ECopyProgressCallbackReason, _
ByVal hSourceFile As IntPtr, _
ByVal hDestinationFile As IntPtr, _
ByVal lpData As IntPtr) As ECopyProgressResult
''' <summary>
''' 執行 CopyFileEx 的回呼函式的回傳列舉。
''' </summary>
Enum ECopyProgressResult As UInteger
PROGRESS_CONTINUE = 0
PROGRESS_CANCEL = 1
PROGRESS_STOP = 2
PROGRESS_QUIET = 3
End Enum
Enum ECopyProgressCallbackReason As UInteger
CALLBACK_CHUNK_FINISHED = 0
CALLBACK_STREAM_SWITCH = 1
End Enum
<Flags()> _
Enum ECopyFileFlags As UInteger
COPY_FILE_FAIL_IF_EXISTS = 1
COPY_FILE_RESTARTABLE = 2
COPY_FILE_OPEN_SOURCE_FOR_WRITE = 4
COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 8
End Enum
Private Function XCopy(ByVal oldFile As String, ByVal newFile As String) As Boolean
Return CopyFileEx(oldFile, newFile, New CopyProgressRoutine(AddressOf Me.CopyProgressHandler), IntPtr.Zero, pbCancel, ECopyFileFlags.COPY_FILE_RESTARTABLE)
End Function
Private Function CopyProgressHandler(ByVal total As Long, ByVal transferred As Long, ByVal streamSize As Long, ByVal StreamByteTrans As Long, ByVal dwStreamNumber As UInteger, ByVal reason As ECopyProgressCallbackReason, _
ByVal hSourceFile As IntPtr, ByVal hDestinationFile As IntPtr, ByVal lpData As IntPtr) As ECopyProgressResult
Label1.Text = String.Format("進度: {0}%", CInt(transferred / total * 100))
Application.DoEvents()
Return ECopyProgressResult.PROGRESS_CONTINUE
End Function
Private Sub btnCopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCopy.Click
If XCopy("C:\Source.avi", "D:\New.avi") Then
MsgBox("複製成功")
Else
MsgBox("複製失敗")
End If
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
pbCancel = 1
Application.DoEvents()
End Sub
End Class
Public Class Form1
Private pbCancel As Int32
<DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function CopyFileEx( _
ByVal lpExistingFileName As String, _
ByVal lpNewFileName As String, _
ByVal lpProgressRoutine As CopyProgressRoutine, _
ByVal lpData As IntPtr, _
ByRef pbCancel As Int32, _
ByVal dwCopyFlags As ECopyFileFlags) As Boolean
End Function
''' <summary>
''' 執行 CopyFileEx 方法的回呼函式定義。
''' </summary>
Delegate Function CopyProgressRoutine( _
ByVal TotalFileSize As Long, _
ByVal TotalBytesTransferred As Long, _
ByVal StreamSize As Long, _
ByVal StreamBytesTransferred As Long, _
ByVal dwStreamNumber As UInteger, _
ByVal dwCallbackReason As ECopyProgressCallbackReason, _
ByVal hSourceFile As IntPtr, _
ByVal hDestinationFile As IntPtr, _
ByVal lpData As IntPtr) As ECopyProgressResult
''' <summary>
''' 執行 CopyFileEx 的回呼函式的回傳列舉。
''' </summary>
Enum ECopyProgressResult As UInteger
PROGRESS_CONTINUE = 0
PROGRESS_CANCEL = 1
PROGRESS_STOP = 2
PROGRESS_QUIET = 3
End Enum
Enum ECopyProgressCallbackReason As UInteger
CALLBACK_CHUNK_FINISHED = 0
CALLBACK_STREAM_SWITCH = 1
End Enum
<Flags()> _
Enum ECopyFileFlags As UInteger
COPY_FILE_FAIL_IF_EXISTS = 1
COPY_FILE_RESTARTABLE = 2
COPY_FILE_OPEN_SOURCE_FOR_WRITE = 4
COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 8
End Enum
Private Function XCopy(ByVal oldFile As String, ByVal newFile As String) As Boolean
Return CopyFileEx(oldFile, newFile, New CopyProgressRoutine(AddressOf Me.CopyProgressHandler), IntPtr.Zero, pbCancel, ECopyFileFlags.COPY_FILE_RESTARTABLE)
End Function
Private Function CopyProgressHandler(ByVal total As Long, ByVal transferred As Long, ByVal streamSize As Long, ByVal StreamByteTrans As Long, ByVal dwStreamNumber As UInteger, ByVal reason As ECopyProgressCallbackReason, _
ByVal hSourceFile As IntPtr, ByVal hDestinationFile As IntPtr, ByVal lpData As IntPtr) As ECopyProgressResult
Label1.Text = String.Format("進度: {0}%", CInt(transferred / total * 100))
Application.DoEvents()
Return ECopyProgressResult.PROGRESS_CONTINUE
End Function
Private Sub btnCopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCopy.Click
If XCopy("C:\Source.avi", "D:\New.avi") Then
MsgBox("複製成功")
Else
MsgBox("複製失敗")
End If
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
pbCancel = 1
Application.DoEvents()
End Sub
End Class