Или так всё-таки, не знаю, как лучше.
CopyFile.Start( "source.txt" ; путь к файлу
, "dest.txt" ; путь копирования
, 250 ; ширина прогрессбара
, 400 ; x-координата окна
, 300 ) ; y-координата окна
while !CopyFile.end
Sleep, 500
ExitApp
class CopyFile
{
Start(source, dest, w = 300, x = "", y = "") {
this.end := 0
if FileExist(dest) {
MsgBox, 0x34,, Файл "%dest%" уже существует.`nПерезаписать?
IfMsgBox, No
Return,, this.end := 1
}
Gui, New, +hwndhGui
this.hGui := hGui
Gui, Margin,, 10
Gui, Add, Progress, w%w% h20 -Smooth, 0
Gui, Add, Button, gCancelCopy x+-80 y+10 w80, Cancel
Gui, Show, % (x != "" && y != "") ? "x" x " y" y : "", Идёт копирование...
OnMessage(DllCall("RegisterWindowMessage", Str, "WM_INFO"), "WM_INFO")
this.CopyPID := ExecScript(this.GetScript(source, dest))
OnExit("CancelCopy")
}
GetScript(source, dest) {
CopyScript =
(
#NoTrayIcon
ERROR_REQUEST_ABORTED := 1235, COPY_FILE_NO_BUFFERING := 0x1000
source := "%source%", dest := "%dest%"
WM_INFO := DllCall("RegisterWindowMessage", Str, "WM_INFO")
DetectHiddenWindows, On
WinWait, ahk_id %A_ScriptHwnd%
VarSetCapacity(cancel, 4, 0)
PostMessage, WM_INFO, 1, &cancel
addr := RegisterCallback("ProgressControl", "F", 4, WM_INFO)
FileGetSize, size, `% source, M
if !DllCall("CopyFileEx", Str, source, Str, dest, Ptr, addr, Ptr, 0, Ptr, &cancel, UInt, size > 1024 ? COPY_FILE_NO_BUFFERING : 0)
PostMessage, WM_INFO, 0, A_LastError = ERROR_REQUEST_ABORTED ? 0 : A_LastError
else
PostMessage, WM_INFO, 3
ExitApp
ProgressControl(TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred) {
PostMessage, A_EventInfo, 2, Round((A_PtrSize = 8 ? TotalBytesTransferred : StreamSize)/TotalFileSize * 100)
}
)
Return CopyScript
}
}
CancelCopy()
{
static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20
Process, Exist, % CopyFile.CopyPID
if !ErrorLevel
Return
hProc := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_WRITE, Int, 0, UInt, CopyFile.CopyPID, Ptr)
DllCall("WriteProcessMemory", Ptr, hProc, Ptr, CopyFile.CancelPtr, UIntP, 1, Ptr, 4, PtrP, Written)
DllCall("CloseHandle", Ptr, hProc)
OnExit("CancelCopy", 0)
}
WM_INFO(wp, lp)
{
Critical
Gui, % CopyFile.hGui ":Default"
if (wp = 1)
CopyFile.CancelPtr := lp
if (wp = 2) {
GuiControl,, msctls_progress321, % lp
Gui, Show, NA, % "Идёт копирование... " . lp . "%"
}
if (wp = 0 && lp = 0) {
GuiControl,, msctls_progress321, 0
Gui, Show, NA, Отменено
Sleep, 1000
Gui, Destroy
}
if (wp = 0 && lp != 0) {
GuiControl,, msctls_progress321, 0
Gui, Show, NA, Ошибка
MsgBox, 16, Error, Ошибка копирования %lp%
Gui, Destroy
}
if (wp = 3) {
GuiControl,, msctls_progress321, 100
Gui, Show, NA, Успешно завершено
Sleep, 1000
Gui, Destroy
}
if wp in 0,3
OnExit("CancelCopy", 0), CopyFile.end := 1
}
ExecScript(Script)
{
shell := ComObjCreate("WScript.Shell")
exec := shell.Exec(A_AhkPath " *")
exec.StdIn.Write(script)
exec.StdIn.Close()
return exec.ProcessID
}
Так можно параллельно с копированием делать что-то ещё.