Skip to content

Commit e766f09

Browse files
committed
Fix Copy/move files progress dialog, smoother progress bar
1 parent f2bedcb commit e766f09

4 files changed

Lines changed: 95 additions & 49 deletions

File tree

src/CmdLineContextMenu.cpp

Lines changed: 90 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@
3030
// added drop handler for copy/move items to target folder
3131
// Version 1.8.1 (c) 2023 thomas694
3232
// fixed deleting empty subfolders
33-
// Version 1.8.2 (c) 2024 thomas694
33+
// Version 1.8.2 (c) Feb 2024 thomas694
3434
// fixed copy/move files progress dialog
35-
// Version 1.8.3 (c) 2024 thomas694
35+
// Version 1.8.3 (c) Mar 2024 thomas694
3636
// fixed problem moving items across volumes
37+
// Version 1.8.4 (c) Nov 2024 thomas694
38+
// fixed copy/move files progress dialog, smoother progress bar
3739
//
3840
// DFTContextMenuHandler is free software: you can redistribute it and/or modify
3941
// it under the terms of the GNU General Public License as published by
@@ -1708,20 +1710,45 @@ int CCmdLineContextMenu::StartMoveFilesHere()
17081710
return 1;
17091711
}
17101712

1711-
void DoWork()
1713+
void CCmdLineContextMenu::DoEvents()
17121714
{
1715+
if (m_lastExec == -1) {
1716+
time(&m_lastExec);
1717+
return;
1718+
}
1719+
time_t now;
1720+
time(&now);
1721+
double diff = difftime(now, m_lastExec);
1722+
if (diff < 10) return;
1723+
m_lastExec = now;
1724+
17131725
MSG msg;
1714-
if (PeekMessage(&msg, NULL, 0, 0, 1)) {
1715-
TranslateMessage(&msg);
1716-
DispatchMessageW(&msg);
1726+
BOOL result;
1727+
1728+
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
1729+
{
1730+
result = GetMessage(&msg, NULL, 0, 0);
1731+
if (result == 0)
1732+
{
1733+
PostQuitMessage(msg.wParam);
1734+
break;
1735+
}
1736+
else if (result == -1)
1737+
{
1738+
}
1739+
else
1740+
{
1741+
TranslateMessage(&msg);
1742+
DispatchMessage(&msg);
1743+
}
17171744
}
17181745
}
17191746

17201747
int CCmdLineContextMenu::CopyFilesHere(StringArray strFilenames, string szFolderDroppedIn)
17211748
{
1722-
size_t lTotalItems, lFiles;
1723-
lTotalItems = lFiles = strFilenames.size();
1724-
size_t lDoneItems = 0;
1749+
size_t lDoneItems, lTotalItems, lFiles;
1750+
lFiles = strFilenames.size();
1751+
lDoneItems = lTotalItems = 0;
17251752

17261753
IProgressDialog* pProgressDlg;
17271754
HRESULT hr = CoCreateInstance(CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pProgressDlg));
@@ -1730,7 +1757,14 @@ int CCmdLineContextMenu::CopyFilesHere(StringArray strFilenames, string szFolder
17301757
pProgressDlg->SetTitle(_T("Copying items..."));
17311758
pProgressDlg->StartProgressDialog(NULL, NULL, PROGDLG_AUTOTIME, NULL);
17321759
pProgressDlg->SetProgress(lDoneItems, lTotalItems);
1733-
DoWork();
1760+
DoEvents();
1761+
1762+
pProgressDlg->SetLine(2, _T("Preparing to copy..."), true, NULL);
1763+
for (int i = 0; i < lFiles; i++) {
1764+
lTotalItems += CountFilesInSubfolders(strFilenames[i].data());
1765+
if (pProgressDlg->HasUserCancelled())
1766+
lFiles = 0;
1767+
}
17341768
}
17351769

17361770
int i;
@@ -1747,7 +1781,7 @@ int CCmdLineContextMenu::CopyFilesHere(StringArray strFilenames, string szFolder
17471781
break;
17481782
lDoneItems++;
17491783
pProgressDlg->SetProgress(lDoneItems, lTotalItems);
1750-
DoWork();
1784+
DoEvents();
17511785
string sItem = _T("");
17521786
sItem.append(sName).append(sExt);
17531787
pProgressDlg->SetLine(2, sItem.data(), true, NULL);
@@ -1759,7 +1793,7 @@ int CCmdLineContextMenu::CopyFilesHere(StringArray strFilenames, string szFolder
17591793
sNewFilename = _T("\\\\?\\") + sNewFilename;
17601794

17611795
if (PathIsDirectory(strFilenames[i].data())) {
1762-
CopyDirectory(strFilenames[i].data(), sNewFilename, pProgressDlg, &lDoneItems, &lTotalItems);
1796+
CopyDirectory(strFilenames[i].data(), sNewFilename, pProgressDlg, &lDoneItems, lTotalItems);
17631797

17641798
} else {
17651799
bool ret = CopyFile(strFilenames[i].data(), sNewFilename.c_str(), true);
@@ -1774,7 +1808,33 @@ int CCmdLineContextMenu::CopyFilesHere(StringArray strFilenames, string szFolder
17741808
return 1;
17751809
}
17761810

1777-
int CCmdLineContextMenu::CopyDirectory(string sourceDir, string destDir, IProgressDialog* pProgressDlg, size_t* currentItems, size_t* totalItems)
1811+
size_t CCmdLineContextMenu::CountFilesInSubfolders(string sourceDir)
1812+
{
1813+
size_t itemsCnt = 0;
1814+
HANDLE hFind;
1815+
WIN32_FIND_DATA fd;
1816+
string searchFolder = sourceDir + _T("\\*");
1817+
1818+
hFind = ::FindFirstFile(searchFolder.c_str(), &fd);
1819+
if (hFind != INVALID_HANDLE_VALUE)
1820+
{
1821+
do
1822+
{
1823+
if (_tcscmp(fd.cFileName, _T(".")) == 0 || _tcscmp(fd.cFileName, _T("..")) == 0) { continue; }
1824+
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1825+
itemsCnt += CountFilesInSubfolders(sourceDir + _T("\\") + fd.cFileName);
1826+
}
1827+
else {
1828+
itemsCnt++;
1829+
}
1830+
} while (::FindNextFile(hFind, &fd) == TRUE);
1831+
::FindClose(hFind);
1832+
hFind = NULL;
1833+
}
1834+
return itemsCnt;
1835+
}
1836+
1837+
int CCmdLineContextMenu::CopyDirectory(string sourceDir, string destDir, IProgressDialog* pProgressDlg, size_t* currentItems, size_t totalItems)
17781838
{
17791839
string strSource;
17801840
string strDest;
@@ -1786,23 +1846,6 @@ int CCmdLineContextMenu::CopyDirectory(string sourceDir, string destDir, IProgre
17861846
return ::GetLastError();
17871847

17881848
string searchFolder = sourceDir + _T("\\*");
1789-
1790-
if (pProgressDlg != NULL) {
1791-
hFind = ::FindFirstFile(searchFolder.c_str(), &fd);
1792-
if (hFind != INVALID_HANDLE_VALUE)
1793-
{
1794-
do
1795-
{
1796-
if (_tcscmp(fd.cFileName, _T(".")) == 0 || _tcscmp(fd.cFileName, _T("..")) == 0) { continue; }
1797-
(*totalItems)++;
1798-
} while (!pProgressDlg->HasUserCancelled() && ::FindNextFile(hFind, &fd) == TRUE);
1799-
::FindClose(hFind);
1800-
hFind = NULL;
1801-
}
1802-
if (pProgressDlg->HasUserCancelled())
1803-
return -1;
1804-
}
1805-
18061849
hFind = ::FindFirstFile(searchFolder.c_str(), &fd);
18071850
if (hFind != INVALID_HANDLE_VALUE)
18081851
{
@@ -1823,8 +1866,8 @@ int CCmdLineContextMenu::CopyDirectory(string sourceDir, string destDir, IProgre
18231866
if (pProgressDlg != NULL) {
18241867
if (pProgressDlg->HasUserCancelled())
18251868
break;
1826-
pProgressDlg->SetProgress(*currentItems, *totalItems);
1827-
DoWork();
1869+
pProgressDlg->SetProgress(*currentItems, totalItems);
1870+
DoEvents();
18281871
}
18291872

18301873
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
@@ -1886,17 +1929,25 @@ BOOL CCmdLineContextMenu::RemoveDirectory(string strDirectory)
18861929

18871930
int CCmdLineContextMenu::MoveFilesHere(StringArray strFilenames, string szFolderDroppedIn)
18881931
{
1889-
size_t lFiles;
1932+
size_t lDoneItems, lTotalItems, lFiles;
18901933
lFiles = strFilenames.size();
1934+
lDoneItems = lTotalItems = 0;
18911935

18921936
IProgressDialog* pProgressDlg;
18931937
HRESULT hr = CoCreateInstance(CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pProgressDlg));
18941938
if (FAILED(hr)) pProgressDlg = NULL;
18951939
if (pProgressDlg != NULL) {
18961940
pProgressDlg->SetTitle(_T("Moving items..."));
18971941
pProgressDlg->StartProgressDialog(NULL, NULL, PROGDLG_AUTOTIME, NULL);
1898-
pProgressDlg->SetProgress(0, lFiles);
1899-
DoWork();
1942+
pProgressDlg->SetProgress(lDoneItems, lTotalItems);
1943+
DoEvents();
1944+
1945+
pProgressDlg->SetLine(2, _T("Preparing to move..."), true, NULL);
1946+
for (int i = 0; i < lFiles; i++) {
1947+
lTotalItems += CountFilesInSubfolders(strFilenames[i].data());
1948+
if (pProgressDlg->HasUserCancelled())
1949+
lFiles = 0;
1950+
}
19001951
}
19011952

19021953
bool isSameVolume = true;
@@ -1924,8 +1975,9 @@ int CCmdLineContextMenu::MoveFilesHere(StringArray strFilenames, string szFolder
19241975
if (pProgressDlg != NULL) {
19251976
if (pProgressDlg->HasUserCancelled())
19261977
break;
1927-
pProgressDlg->SetProgress(i + 1, lFiles);
1928-
DoWork();
1978+
lDoneItems++;
1979+
pProgressDlg->SetProgress(lDoneItems, lTotalItems);
1980+
DoEvents();
19291981
string sItem = _T("");
19301982
sItem.append(sName).append(sExt);
19311983
pProgressDlg->SetLine(2, sItem.data(), true, NULL);
@@ -1944,18 +1996,9 @@ int CCmdLineContextMenu::MoveFilesHere(StringArray strFilenames, string szFolder
19441996
ret = MoveFile(sOldFilename.c_str(), sNewFilename.c_str());
19451997
if (!ret)
19461998
break;
1947-
/*
1948-
if (ret == false) {
1949-
DWORD error = ::GetLastError();
1950-
std::string sMessage = std::system_category().message(error);
1951-
string message = string(sMessage.begin(), sMessage.end());
1952-
MessageBox(NULL, message.c_str(), _T("Error"), 0);
1953-
}
1954-
*/
19551999
}
19562000
else {
1957-
size_t dummy;
1958-
int result = CopyDirectory(sOldFilename, sNewFilename, NULL, &dummy, &dummy);
2001+
int result = CopyDirectory(sOldFilename, sNewFilename, pProgressDlg, &lDoneItems, lTotalItems);
19592002
if (result == 0)
19602003
CCmdLineContextMenu::RemoveDirectory(sOldFilename.c_str());
19612004
else

src/CmdLineContextMenu.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,11 @@ END_COM_MAP()
9090
void FlattenTree(string baseFolder, bool useFolderNames);
9191
StringArray GetSubfolders(string folder);
9292
bool IsEmptyDirectory(string folder);
93-
int CopyDirectory(string sourceDir, string destDir, IProgressDialog* pProgressDlg, size_t* currentFiles, size_t* totalFiles);
93+
int CopyDirectory(string sourceDir, string destDir, IProgressDialog* pProgressDlg, size_t* currentFiles, size_t totalFiles);
9494
BOOL RemoveDirectory(string strDir);
95+
void DoEvents();
96+
time_t m_lastExec = (time_t)(-1);
97+
size_t CountFilesInSubfolders(string sourceDir);
9598

9699
string m_strBaseFolder;
97100
StringArray m_lstFolders;

src/CmdLineExt.rc

0 Bytes
Binary file not shown.

src/app.manifest

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
22
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
3-
<assemblyIdentity type='win32' name='DFTContextMenuHandler' version='1.8.3.0' processorArchitecture="amd64" />
3+
<assemblyIdentity type='win32' name='DFTContextMenuHandler' version='1.8.4.0' processorArchitecture="amd64" />
44
<asmv3:application>
55
<asmv3:windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
66
<ws2:longPathAware>true</ws2:longPathAware>

0 commit comments

Comments
 (0)