Alex Sokolek
Member
- Joined
- Apr 5, 2024
- Messages
- 44
- Thread Author
- #1
I have solved the problem! When the AI Bot told me that I was stalling the message loop, I looked deeper. In the original code I was calling PeekMessage() with PM_REMOVE, filtering for WM_KEYDOWN, and then checking for VK_ESCAPE. This consumed the WM_KEYDOWN message but not any other messages. Now, I am calling PeekMessage() with PM_REMOVE, with no filtering, and then checking for WM_KEYDOWN and VK_ESCAPE. The result is that I am consuming all messages, and detecting WM_KEYDOWN/VK_ESCAPE.
becomes...
Now the program works properly, in both debug executions and in non-debug executions.
I still don't know why it worked in debug mode, but I'm not "going to look a gift-horse in the mouth".
I have left the original post intact, for reference...
Hi. I'm having a problem with modeless dialog boxes. I have one in a loop that scans files in a directory, adding the files to a linked list class for later processing. This used to work just fine. Now, without making any changes, it freezes part way through and stops updating. I know the loop is still running, because after a period of time (the same time it used to take) the loop terminates and I see the results. Sometimes the point of freeze moves around, but ususally it happens at the same spot.
The strange part of this is that it only occurs with a Release build. A Debug build works just fine.
This has all the hallmarks of uninitialized memory and/or buffer overrun, but for the life of me I can't find it. I have spent the last three days instrumenting the loop, trying to find evidence of where the problem is, but no help.
Anyway, here is the code for the command handler. I apologize for the length of this posting, but I ahve no idea where I'm going wrong, so I thought it best to post the whole routine. The dialog box gets updated in the section "Update the user about progress". Please take a look and see what you can see. Thank you.
Code:
// Check for ESC pressed - Abort if so.
MSG msg;
if (!PeekMessage(&msg, NULL, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE)) continue;
if (msg.wParam != VK_ESCAPE) continue;
pCHashedFiles->Reset();
bEscapePressed = true;
break;
becomes...
Code:
// Check for ESC pressed - Abort if so.
MSG msg;
if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) continue;
if (msg.message != WM_KEYDOWN || msg.wParam != VK_ESCAPE) continue;
pCHashedFiles->Reset();
bEscapePressed = true;
break;
Now the program works properly, in both debug executions and in non-debug executions.
I still don't know why it worked in debug mode, but I'm not "going to look a gift-horse in the mouth".
I have left the original post intact, for reference...
Hi. I'm having a problem with modeless dialog boxes. I have one in a loop that scans files in a directory, adding the files to a linked list class for later processing. This used to work just fine. Now, without making any changes, it freezes part way through and stops updating. I know the loop is still running, because after a period of time (the same time it used to take) the loop terminates and I see the results. Sometimes the point of freeze moves around, but ususally it happens at the same spot.
The strange part of this is that it only occurs with a Release build. A Debug build works just fine.
This has all the hallmarks of uninitialized memory and/or buffer overrun, but for the life of me I can't find it. I have spent the last three days instrumenting the loop, trying to find evidence of where the problem is, but no help.
Anyway, here is the code for the command handler. I apologize for the length of this posting, but I ahve no idea where I'm going wrong, so I thought it best to post the whole routine. The dialog box gets updated in the section "Update the user about progress". Please take a look and see what you can see. Thank you.
Code:
case ID_FILE_SCAN:
/////////////////////////////////////////////////////////////////////////////////////////////////
// Select directory and then scan, hash, and sort.
/////////////////////////////////////////////////////////////////////////////////////////////////
{
MessageBox(hWnd, _T("Navigate to the desired directory and double\n"
"click on any file to process the directory."), szTitle, MB_OK);
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
// Initially, _T(""), replaced by the path to scan via ofn.lpstrFile
TCHAR* pszOpenFileName = new TCHAR[MAX_PATH];
ZeroMemory(pszOpenFileName, sizeof(pszOpenFileName));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = pszOpenFileName;
ofn.nMaxFile = MAX_PATH;
// Save original current directory.
GetCurrentDirectory(MAX_PATH, szOldDirectoryName);
int LastAPICallLine = __LINE__ + 1;
if (!GetOpenFileName(&ofn)) // Retrieves the fully qualified file name that was selected.
{
if (CommDlgExtendedError() == 0)
{
delete[] pszOpenFileName;
break;
}
TCHAR sz[MAX_ERROR_MESSAGE_LEN];
StringCchPrintf(sz, MAX_ERROR_MESSAGE_LEN,
_T("API Error occurred at line %ld error code %ld"), LastAPICallLine, CommDlgExtendedError());
MessageBox(hWnd, sz, _T("ApplicationRegistry.cpp"), MB_OK + MB_ICONSTOP);
break;
}
ofn.lpstrFile[ofn.nFileOffset] = TCHAR('\0'); // We only want the path, so eliminate the file name.
WIN32_FIND_DATA Win32FindData;
FILETIME LocalFileTime;
SYSTEMTIME LocalSystemTime;
#define FORMATTED_FILE_DATE_LEN 11
TCHAR* pszFileDate = new TCHAR[FORMATTED_FILE_DATE_LEN];
#define FORMATTED_FILE_TIME_LEN 6
TCHAR* pszFileTime = new TCHAR[FORMATTED_FILE_TIME_LEN];
#define FORMATTED_FILE_SIZE_LEN 21
TCHAR* pszFileSize = new TCHAR[FORMATTED_FILE_SIZE_LEN];
pCHashedFiles->Reset();
// Save directory name in global array for use by other routines
StringCchCopy(szDirectoryName, MAX_PATH, ofn.lpstrFile);
SetCurrentDirectory(ofn.lpstrFile);
// Count the files in the directory.
int iTotalFiles = 0;
HANDLE hFind = FindFirstFile(_T(".\\*.*"), &Win32FindData);
if (hFind == INVALID_HANDLE_VALUE) break;
do iTotalFiles += Win32FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? 0 : 1;
while (FindNextFile(hFind, &Win32FindData) != 0);
FindClose(hFind);
// Setup to use the modeless dialog box to display progress.
dc = GetDC(hWndProgressBox);
TCHAR szFilesProcessed[200];
RECT WindowRect;
GetWindowRect(hWnd, &WindowRect);
ShowWindow(hWndProgressBox, SW_SHOW);
SetWindowPos(hWndProgressBox, HWND_NOTOPMOST, WindowRect.left+50, WindowRect.top+50, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
uint64_t FileSize;
// Get the first file in the directory
hFind = FindFirstFile(_T(".\\*.*"), &Win32FindData);
if (hFind == INVALID_HANDLE_VALUE)
{
ShowWindow(hWndProgressBox, SW_HIDE);
delete[] pszFileDate;
delete[] pszFileTime;
delete[] pszFileSize;
delete[] pszOpenFileName;
break;
}
BOOL bEscapePressed = false;
BytesProcessed = 0;
// Process this and all of the rest of the files in the deirectory.
do
{
// Ignore subdirectories.
if (Win32FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
// Get the last write time and format the local time equivalent of it.
FileTimeToLocalFileTime(&Win32FindData.ftLastWriteTime, &LocalFileTime);
FileTimeToSystemTime(&LocalFileTime, &LocalSystemTime);
StringCchPrintf(pszFileDate, FORMATTED_FILE_DATE_LEN, _T("%02d/%02d/%04d"),
LocalSystemTime.wMonth, LocalSystemTime.wDay, LocalSystemTime.wYear);
StringCchPrintf(pszFileTime, FORMATTED_FILE_TIME_LEN, _T("%02d:%02d"),
LocalSystemTime.wHour, LocalSystemTime.wMinute);
// Get the file size and format it.
FileSize = (uint64_t)Win32FindData.nFileSizeHigh * ((uint64_t)MAXDWORD + 1) +
(uint64_t)Win32FindData.nFileSizeLow;
StringCchPrintf(pszFileSize, FORMATTED_FILE_SIZE_LEN, _T("%9llu"), FileSize);
BytesProcessed += FileSize;
// Generate sha1 digest.
SHAFile.Process(Win32FindData.cFileName, 0, pszMessageDigest, NULL);
// Add the file information to the HashedFiles class.
pCHashedFiles->AddNode(pszMessageDigest, pszFileDate, pszFileTime, pszFileSize, Win32FindData.cFileName);
// Update the user about progress.
int iPercent = (int)((float)pCHashedFiles->GetNodeCount() * 100.f / iTotalFiles + 0.5f);
StringCchPrintf(szFilesProcessed, 200,
_T("Files processed: %u %d%% of %d MBytes processed: %llu"),
pCHashedFiles->GetNodeCount(), iPercent, iTotalFiles, BytesProcessed/1024/1024);
SetBkColor(dc, RGB(240, 240, 240));
TextOut(dc, 16, 16, szFilesProcessed, lstrlen(szFilesProcessed));
TextOut(dc, 16, 40, _T("Press ESC to abort."), 19);
// Check for ESC pressed - Abort if so.
MSG msg;
if (!PeekMessage(&msg, NULL, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE)) continue;
if (msg.wParam != VK_ESCAPE) continue;
pCHashedFiles->Reset();
bEscapePressed = true;
break;
} while (FindNextFile(hFind, &Win32FindData) != 0);
MessageBeep(MB_ICONASTERISK);
FindClose(hFind);
ReleaseDC(hWndProgressBox, dc);
// Sort by hash then file.
iSortMode = 0;
if (!bEscapePressed) pCHashedFiles->SortAndCheck(iSortMode);
// Setup initial view.
bMarked = false;
iStartNode = 0;
iSelectedFile = 0;
InvalidateRect(hWnd, NULL, true); // Generate paint message.
delete[] pszFileDate;
delete[] pszFileTime;
delete[] pszFileSize;
delete[] pszOpenFileName;
// Restore original current directory.
SetCurrentDirectory(szOldDirectoryName);
// Set a 3 second timer to close the modeless dialog box.
if (!bEscapePressed) uiTimer = SetTimer(hWnd, 1, 3000, NULL);
else uiTimer = SetTimer(hWnd, 1, 30, NULL);
}
break;