VOID WINAPI WorkerThreadTogglePause( PCOMMONCONTEXT pcmnctx ) { if (pcmnctx->status == ACTIVE) { ResetEvent(pcmnctx->hUnpauseEvent); pcmnctx->status = PAUSED; if (!(pcmnctx->dwFlags & HCF_EXIT_PENDING)) { SetControlText(pcmnctx->hWnd, IDC_PAUSE, IDS_HC_RESUME); SetProgressBarPause(pcmnctx, PBST_PAUSED); } } else if (pcmnctx->status == PAUSED) { pcmnctx->status = ACTIVE; if (!(pcmnctx->dwFlags & HCF_EXIT_PENDING)) { SetControlText(pcmnctx->hWnd, IDC_PAUSE, IDS_HC_PAUSE); SetProgressBarPause(pcmnctx, PBST_NORMAL); } SetEvent(pcmnctx->hUnpauseEvent); } }
INT_PTR CALLBACK HashSaveDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { PHASHSAVECONTEXT phsctx; switch (uMsg) { case WM_INITDIALOG: { phsctx = (PHASHSAVECONTEXT)lParam; // Associate the window with the context and vice-versa phsctx->hWnd = hWnd; SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)phsctx); SetAppIDForWindow(hWnd, TRUE); HashSaveDlgInit(phsctx); phsctx->ex.pfnWorkerMain = HashSaveWorkerMain; phsctx->hThread = CreateThreadCRT(NULL, phsctx); if (!phsctx->hThread || WaitForSingleObject(phsctx->hThread, 1000) != WAIT_TIMEOUT) { WorkerThreadCleanup((PCOMMONCONTEXT)phsctx); EndDialog(hWnd, 0); } return(TRUE); } case WM_DESTROY: { SetAppIDForWindow(hWnd, FALSE); break; } case WM_ENDSESSION: case WM_CLOSE: { phsctx = (PHASHSAVECONTEXT)GetWindowLongPtr(hWnd, DWLP_USER); goto cleanup_and_exit; } case WM_COMMAND: { phsctx = (PHASHSAVECONTEXT)GetWindowLongPtr(hWnd, DWLP_USER); switch (LOWORD(wParam)) { case IDC_PAUSE: { WorkerThreadTogglePause((PCOMMONCONTEXT)phsctx); return(TRUE); } case IDC_CANCEL: { cleanup_and_exit: phsctx->dwFlags |= HCF_EXIT_PENDING; WorkerThreadStop((PCOMMONCONTEXT)phsctx); WorkerThreadCleanup((PCOMMONCONTEXT)phsctx); EndDialog(hWnd, 0); break; } } break; } case WM_TIMER: { // Vista: Workaround to fix their buggy progress bar KillTimer(hWnd, TIMER_ID_PAUSE); phsctx = (PHASHSAVECONTEXT)GetWindowLongPtr(hWnd, DWLP_USER); if (phsctx->status == PAUSED) SetProgressBarPause((PCOMMONCONTEXT)phsctx, PBST_PAUSED); return(TRUE); } case HM_WORKERTHREAD_DONE: { phsctx = (PHASHSAVECONTEXT)wParam; WorkerThreadCleanup((PCOMMONCONTEXT)phsctx); EndDialog(hWnd, 0); return(TRUE); } case HM_WORKERTHREAD_UPDATE: { phsctx = (PHASHSAVECONTEXT)wParam; ++phsctx->cHandledMsgs; SendMessage(phsctx->hWndPBTotal, PBM_SETPOS, phsctx->cHandledMsgs, 0); return(TRUE); } case HM_WORKERTHREAD_TOGGLEPREP: { HashCalcTogglePrep((PHASHSAVECONTEXT)wParam, (BOOL)lParam); return(TRUE); } } return(FALSE); }
INT_PTR CALLBACK HashVerifyDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { PHASHVERIFYCONTEXT phvctx; switch (uMsg) { case WM_INITDIALOG: { phvctx = (PHASHVERIFYCONTEXT)lParam; // Associate the window with the context and vice-versa phvctx->hWnd = hWnd; SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)phvctx); SetAppIDForWindow(hWnd, TRUE); HashVerifyDlgInit(phvctx); phvctx->ex.pfnWorkerMain = HashVerifyWorkerMain; phvctx->hThread = CreateThreadCRT(NULL, phvctx); if (!phvctx->hThread) WorkerThreadCleanup((PCOMMONCONTEXT)phvctx); // Initialize the summary SendMessage(phvctx->hWndPBTotal, PBM_SETRANGE32, 0, phvctx->cTotal); HashVerifyUpdateSummary(phvctx, NULL); return(TRUE); } case WM_DESTROY: { SetAppIDForWindow(hWnd, FALSE); break; } case WM_ENDSESSION: case WM_CLOSE: { phvctx = (PHASHVERIFYCONTEXT)GetWindowLongPtr(hWnd, DWLP_USER); goto cleanup_and_exit; } case WM_COMMAND: { phvctx = (PHASHVERIFYCONTEXT)GetWindowLongPtr(hWnd, DWLP_USER); switch (LOWORD(wParam)) { case IDC_PAUSE: { WorkerThreadTogglePause((PCOMMONCONTEXT)phvctx); return(TRUE); } case IDC_STOP: { WorkerThreadStop((PCOMMONCONTEXT)phvctx); return(TRUE); } case IDC_EXIT: { cleanup_and_exit: phvctx->dwFlags |= HCF_EXIT_PENDING; WorkerThreadStop((PCOMMONCONTEXT)phvctx); WorkerThreadCleanup((PCOMMONCONTEXT)phvctx); EndDialog(hWnd, 0); break; } } break; } case WM_NOTIFY: { LPNMHDR pnm = (LPNMHDR)lParam; if (pnm && pnm->idFrom == IDC_LIST) { phvctx = (PHASHVERIFYCONTEXT)GetWindowLongPtr(hWnd, DWLP_USER); switch (pnm->code) { case LVN_GETDISPINFO: { HashVerifyListInfo(phvctx, (LPNMLVDISPINFO)lParam); return(TRUE); } case NM_CUSTOMDRAW: { SetWindowLongPtr(hWnd, DWLP_MSGRESULT, HashVerifySetColor(phvctx, (LPNMLVCUSTOMDRAW)lParam)); return(TRUE); } case LVN_ODFINDITEM: { SetWindowLongPtr(hWnd, DWLP_MSGRESULT, HashVerifyFindItem(phvctx, (LPNMLVFINDITEM)lParam)); return(TRUE); } case LVN_COLUMNCLICK: { HashVerifySortColumn(phvctx, (LPNMLISTVIEW)lParam); return(TRUE); } case LVN_ITEMCHANGED: { if (((LPNMLISTVIEW)lParam)->uChanged & LVIF_STATE) phvctx->bFreshStates = FALSE; break; } case LVN_ODSTATECHANGED: { phvctx->bFreshStates = FALSE; break; } } } break; } case WM_TIMER: { // Vista: Workaround to fix their buggy progress bar KillTimer(hWnd, TIMER_ID_PAUSE); phvctx = (PHASHVERIFYCONTEXT)GetWindowLongPtr(hWnd, DWLP_USER); if (phvctx->status == PAUSED) SetProgressBarPause((PCOMMONCONTEXT)phvctx, PBST_PAUSED); return(TRUE); } case HM_WORKERTHREAD_DONE: { phvctx = (PHASHVERIFYCONTEXT)wParam; WorkerThreadCleanup((PCOMMONCONTEXT)phvctx); return(TRUE); } case HM_WORKERTHREAD_UPDATE: { phvctx = (PHASHVERIFYCONTEXT)wParam; ++phvctx->cHandledMsgs; HashVerifyUpdateSummary(phvctx, (PHASHVERIFYITEM)lParam); return(TRUE); } case HM_WORKERTHREAD_SETSIZE: { phvctx = (PHASHVERIFYCONTEXT)wParam; // At the time we receive this message, cSentMsgs will be the ID of // the item the worker thread is currently working on, and // cHandledMsgs will be the ID of the item for which the SETSIZE // message was intended for; we need to update the UI only if // the worker thread is still working on this item when we process // this message; otherwise, we can just wait for the UPDATE message. if (phvctx->cSentMsgs == phvctx->cHandledMsgs) ListView_RedrawItems(phvctx->hWndList, phvctx->cHandledMsgs, phvctx->cHandledMsgs); return(TRUE); } } return(FALSE); }