diff --git a/src/Dialogs.c b/src/Dialogs.c index 8312ffcf9..d07f110ab 100644 --- a/src/Dialogs.c +++ b/src/Dialogs.c @@ -2132,20 +2132,16 @@ typedef struct tagIconThreadInfo { DWORD WINAPI FileMRUIconThread(LPVOID lpParam) { + BackgroundWorker *worker = (BackgroundWorker *)lpParam; WCHAR tch[MAX_PATH] = { L'\0' }; DWORD dwFlags = SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_ATTRIBUTES | SHGFI_ATTR_SPECIFIED; - LPICONTHREADINFO lpit = (LPICONTHREADINFO)lpParam; - ResetEvent(lpit->hTerminatedThread); - - HWND hwnd = lpit->hwnd; + HWND hwnd = worker->hwnd; int iMaxItem = ListView_GetItemCount(hwnd); - (void)CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY); - int iItem = 0; - while (iItem < iMaxItem && WaitForSingleObject(lpit->hExitThread,0) != WAIT_OBJECT_0) { + while (iItem < iMaxItem && BackgroundWorker_Continue(worker)) { LV_ITEM lvi = { 0 }; lvi.mask = LVIF_TEXT; @@ -2204,13 +2200,7 @@ DWORD WINAPI FileMRUIconThread(LPVOID lpParam) iItem++; } - CoUninitialize(); - - SetEvent(lpit->hTerminatedThread); - lpit->hThread = NULL; - - ExitThread(0); - //return(0); + return 0; } #define IDC_FILEMRU_UPDATE_VIEW (WM_USER+1) @@ -2238,6 +2228,7 @@ static INT_PTR CALLBACK FileMRUDlgProc(HWND hwnd, UINT umsg, WPARAM wParam, LPAR } } #endif + // sync with other instances if (Settings.SaveRecentFiles && Globals.bCanSaveIniFile) { if (MRU_MergeSave(Globals.pFileMRU, true, Flags.RelativeFileMRU, Flags.PortableMyDocs)) { @@ -2249,19 +2240,14 @@ static INT_PTR CALLBACK FileMRUDlgProc(HWND hwnd, UINT umsg, WPARAM wParam, LPAR InitWindowCommon(hwndLV, true); InitListView(hwndLV); // DarkMode - SHFILEINFO shfi = { 0 }; - LVCOLUMN lvc = {LVCF_FMT | LVCF_TEXT, LVCFMT_LEFT, 0, L"", -1, 0, 0, 0}; + BackgroundWorker *worker = (BackgroundWorker *)GlobalAlloc(GPTR, sizeof(BackgroundWorker)); + SetProp(hwnd, L"it", (HANDLE)worker); + BackgroundWorker_Init(worker, hwndLV); - LPICONTHREADINFO lpit = (LPICONTHREADINFO)AllocMem(sizeof(ICONTHREADINFO), HEAP_ZERO_MEMORY); - if (lpit) { - SetProp(hwnd, L"it", (HANDLE)lpit); - lpit->hwnd = hwndLV; - lpit->hThread = NULL; - lpit->hExitThread = CreateEvent(NULL, true, false, NULL); - lpit->hTerminatedThread = CreateEvent(NULL, true, true, NULL); - } ResizeDlg_Init(hwnd, Settings.FileMRUDlgSizeX, Settings.FileMRUDlgSizeY, IDC_RESIZEGRIP); + SHFILEINFO shfi = { 0 }; + LVCOLUMN lvc = { LVCF_FMT | LVCF_TEXT, LVCFMT_LEFT, 0, L"", -1, 0, 0, 0 }; ListView_SetImageList(hwndLV, (HIMAGELIST)SHGetFileInfo(L"C:\\", FILE_ATTRIBUTE_DIRECTORY, @@ -2289,25 +2275,11 @@ static INT_PTR CALLBACK FileMRUDlgProc(HWND hwnd, UINT umsg, WPARAM wParam, LPAR } return TRUE; - case WM_DPICHANGED: - UpdateWindowLayoutForDPI(hwnd, (RECT*)lParam, 0); - return TRUE; - case WM_DESTROY: { - LPICONTHREADINFO lpit = (LPVOID)GetProp(hwnd, L"it"); - SetEvent(lpit->hExitThread); - while (WaitForSingleObject(lpit->hTerminatedThread, 0) != WAIT_OBJECT_0) { - MSG msg; - if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - CloseHandle(lpit->hExitThread); - CloseHandle(lpit->hTerminatedThread); - lpit->hThread = NULL; + BackgroundWorker *worker = (BackgroundWorker *)GetProp(hwnd, L"it"); + BackgroundWorker_Destroy(worker); RemoveProp(hwnd, L"it"); - FreeMem(lpit); + GlobalFree(worker); if (Settings.SaveRecentFiles) { MRU_Save(Globals.pFileMRU); // last instance on save wins @@ -2338,6 +2310,10 @@ static INT_PTR CALLBACK FileMRUDlgProc(HWND hwnd, UINT umsg, WPARAM wParam, LPAR } return TRUE; + case WM_DPICHANGED: + UpdateWindowLayoutForDPI(hwnd, (RECT *)lParam, 0); + return TRUE; + case WM_GETMINMAXINFO: ResizeDlg_GetMinMaxInfo(hwnd, lParam); return TRUE; @@ -2505,18 +2481,9 @@ CASE_WM_CTLCOLOR_SET: switch (LOWORD(wParam)) { case IDC_FILEMRU_UPDATE_VIEW: { - LPICONTHREADINFO lpit = (LPVOID)GetProp(hwnd, L"it"); - SetEvent(lpit->hExitThread); - while (WaitForSingleObject(lpit->hTerminatedThread, 0) != WAIT_OBJECT_0) { - MSG msg; - if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - ResetEvent(lpit->hExitThread); - SetEvent(lpit->hTerminatedThread); - lpit->hThread = NULL; + + BackgroundWorker *worker = (BackgroundWorker *)GetProp(hwnd, L"it"); + BackgroundWorker_Cancel(worker); ListView_DeleteAllItems(hwndLV); @@ -2526,7 +2493,6 @@ CASE_WM_CTLCOLOR_SET: SHFILEINFO shfi = { 0 }; SHGetFileInfo(L"Icon", FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(SHFILEINFO), SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES); - lvi.iImage = shfi.iIcon; WCHAR tch[MAX_PATH] = { L'\0' }; @@ -2552,12 +2518,10 @@ CASE_WM_CTLCOLOR_SET: // ListView_SetItemState(hwndLV, idx + 1, LVIS_SELECTED, LVIS_SELECTED); //} } - - DWORD dwtid; - lpit->hThread = CreateThread(NULL, 0, FileMRUIconThread, (LPVOID)lpit, 0, &dwtid); - DialogEnableControl(hwnd, IDOK, (cnt > 0)); DialogEnableControl(hwnd, IDC_REMOVE, (cnt > 0)); + + worker->workerThread = CreateThread(NULL, 0, FileMRUIconThread, (LPVOID)worker, 0, NULL); } break; @@ -6024,6 +5988,7 @@ void UpdateWindowLayoutForDPI(HWND hwnd, const RECT *pNewRect, const UINT adpi) Scintilla_AdjustWindowRectForDpi((LPWRECT)&rc, uWndFlags, 0, dpi); SetWindowPos(hwnd, NULL, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), uWndFlags); } + RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_INTERNALPAINT | RDW_ALLCHILDREN | RDW_UPDATENOW); } diff --git a/src/Dlapi.c b/src/Dlapi.c index baeae58b2..d4d2de411 100644 --- a/src/Dlapi.c +++ b/src/Dlapi.c @@ -31,16 +31,13 @@ typedef struct tagDLDATA { // dl - HWND hwnd; // HWND of ListView Control + BackgroundWorker worker; // where HWND is ListView Control UINT cbidl; // Size of pidl LPITEMIDLIST pidl; // Directory Id LPSHELLFOLDER lpsf; // IShellFolder Interface to pidl int iDefIconFolder; // Default Folder Icon int iDefIconFile; // Default File Icon bool bNoFadeHidden; // Flag passed from GetDispInfo() - HANDLE hThread; // Thread Handle - HANDLE hExitThread; // Flag is set when Icon Thread should terminate - HANDLE hTerminatedThread; // Flag is set when Icon Thread has terminated WCHAR szPath[MAX_PATH]; // Pathname to Directory Id @@ -62,24 +59,22 @@ bool DirList_Init(HWND hwnd,LPCWSTR pszHeader) { UNREFERENCED_PARAMETER(pszHeader); - HIMAGELIST hil; - SHFILEINFO shfi = { 0 }; - // Allocate DirListData Property - LPDLDATA lpdl = (LPDLDATA)AllocMem(sizeof(DLDATA),HEAP_ZERO_MEMORY); + LPDLDATA lpdl = (LPDLDATA)GlobalAlloc(GPTR, sizeof(DLDATA)); if (lpdl) { SetProp(hwnd, pDirListProp, (HANDLE)lpdl); // Setup dl - lpdl->hwnd = hwnd; + BackgroundWorker_Init(&lpdl->worker, hwnd); lpdl->cbidl = 0; lpdl->pidl = NULL; lpdl->lpsf = NULL; StringCchCopy(lpdl->szPath, COUNTOF(lpdl->szPath), L""); // Add Imagelists - hil = (HIMAGELIST)SHGetFileInfo(L"C:\\", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(SHFILEINFO), - SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES); + SHFILEINFO shfi = { 0 }; + HIMAGELIST hil = (HIMAGELIST)SHGetFileInfo(L"C:\\", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(SHFILEINFO), + SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES); ListView_SetImageList(hwnd, hil, LVSIL_SMALL); @@ -99,10 +94,6 @@ bool DirList_Init(HWND hwnd,LPCWSTR pszHeader) lpdl->iDefIconFolder = 0; lpdl->iDefIconFile = 0; - - // Icon thread control - lpdl->hExitThread = CreateEvent(NULL, true, false, NULL); - lpdl->hTerminatedThread = CreateEvent(NULL, true, true, NULL); } return true; @@ -117,11 +108,9 @@ bool DirList_Init(HWND hwnd,LPCWSTR pszHeader) // bool DirList_Destroy(HWND hwnd) { - LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp); - // Release multithreading objects - DirList_TerminateIconThread(hwnd); - CloseHandle(lpdl->hExitThread); - CloseHandle(lpdl->hTerminatedThread); + LPDLDATA lpdl = (LPDLDATA)GetProp(hwnd, pDirListProp); + + BackgroundWorker_Destroy(&lpdl->worker); if (lpdl->pidl) { CoTaskMemFree((LPVOID)lpdl->pidl); @@ -131,7 +120,7 @@ bool DirList_Destroy(HWND hwnd) } // Free DirListData Property RemoveProp(hwnd,pDirListProp); - FreeMem(lpdl); + GlobalFree(lpdl); return false; } @@ -143,57 +132,12 @@ bool DirList_Destroy(HWND hwnd) // // Start thread to extract file icons in the background // -bool DirList_StartIconThread(HWND hwnd) +void DirList_StartIconThread(HWND hwnd) { - DWORD dwtid; - LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp); + LPDLDATA lpdl = (LPDLDATA)GetProp(hwnd, pDirListProp); - DirList_TerminateIconThread(hwnd); - - ResetEvent(lpdl->hExitThread); - //ResetEvent(lpdl->hTerminatedThread); - - lpdl->hThread = CreateThread(NULL, 0, DirList_IconThread, (LPVOID)lpdl, 0, &dwtid); - - if (lpdl->hThread == NULL) { - ResetEvent(lpdl->hExitThread); - SetEvent(lpdl->hTerminatedThread); - return false; - } - return true; -} - - -//============================================================================= -// -// DirList_TerminateIconThread() -// -// Terminate Icon Thread and reset multithreading control structures -// -bool DirList_TerminateIconThread(HWND hwnd) -{ - LPDLDATA lpdl = (LPDLDATA)GetProp(hwnd,pDirListProp); - - if (!lpdl->hThread) { - return false; - } - - SetEvent(lpdl->hExitThread); - - //WaitForSingleObject(lpdl->hTerminatedThread,INFINITE); - while (WaitForSingleObject(lpdl->hTerminatedThread,0) != WAIT_OBJECT_0) { - MSG msg; - if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - ResetEvent(lpdl->hExitThread); - SetEvent(lpdl->hTerminatedThread); - lpdl->hThread = NULL; - - return true; + BackgroundWorker_Cancel(&lpdl->worker); + lpdl->worker.workerThread = CreateThread(NULL, 0, DirList_IconThread, (LPVOID)lpdl, 0, NULL); } @@ -208,24 +152,10 @@ int DirList_Fill(HWND hwnd,LPCWSTR lpszDir,DWORD grfFlags,LPCWSTR lpszFileSpec, int iSortFlags,bool fSortRev) { + LPDLDATA lpdl = (LPDLDATA)GetProp(hwnd, pDirListProp); + WCHAR wszDir[MAX_PATH] = { L'\0' }; - LPSHELLFOLDER lpsfDesktop = NULL; - LPSHELLFOLDER lpsf = NULL; - - LPITEMIDLIST pidl = NULL; - LPITEMIDLIST pidlEntry = NULL; - - LPENUMIDLIST lpe = NULL; - - ULONG chParsed = 0; - ULONG dwAttributes = 0; - - // First of all terminate running icon thread - DirList_TerminateIconThread(hwnd); - - LPDLDATA lpdl = (LPDLDATA)GetProp(hwnd,pDirListProp); - // Initialize default icons SHFILEINFO shfi = { 0 }; SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO), @@ -236,6 +166,9 @@ int DirList_Fill(HWND hwnd,LPCWSTR lpszDir,DWORD grfFlags,LPCWSTR lpszFileSpec, SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX); lpdl->iDefIconFile = shfi.iIcon; + // First of all terminate running icon thread + BackgroundWorker_Cancel(&lpdl->worker); + // A Directory is strongly required if (!lpszDir || !*lpszDir) { return(-1); @@ -269,9 +202,14 @@ int DirList_Fill(HWND hwnd,LPCWSTR lpszDir,DWORD grfFlags,LPCWSTR lpszFileSpec, StringCchCopy(wszDir,COUNTOF(wszDir),lpszDir); // Get Desktop Folder + LPSHELLFOLDER lpsf = NULL; + LPSHELLFOLDER lpsfDesktop = NULL; if (NOERROR == SHGetDesktopFolder(&lpsfDesktop)) { // Convert wszDir into a pidl + ULONG chParsed = 0; + LPITEMIDLIST pidl = NULL; + ULONG dwAttributes = 0; if (NOERROR == lpsfDesktop->lpVtbl->ParseDisplayName( lpsfDesktop, hwnd, @@ -294,6 +232,7 @@ int DirList_Fill(HWND hwnd,LPCWSTR lpszDir,DWORD grfFlags,LPCWSTR lpszFileSpec, { // Create an Enumeration object for lpsf + LPENUMIDLIST lpe = NULL; if (NOERROR == lpsf->lpVtbl->EnumObjects( lpsf, hwnd, @@ -303,6 +242,7 @@ int DirList_Fill(HWND hwnd,LPCWSTR lpszDir,DWORD grfFlags,LPCWSTR lpszFileSpec, { // Enumerate the contents of lpsf + LPITEMIDLIST pidlEntry = NULL; while (NOERROR == lpe->lpVtbl->Next( lpe, 1, @@ -370,6 +310,7 @@ int DirList_Fill(HWND hwnd,LPCWSTR lpszDir,DWORD grfFlags,LPCWSTR lpszFileSpec, } // Set lpdl + LPITEMIDLIST pidl = NULL; lpdl->cbidl = IL_GetSize(pidl); lpdl->pidl = pidl; lpdl->lpsf = lpsf; @@ -397,31 +338,23 @@ int DirList_Fill(HWND hwnd,LPCWSTR lpszDir,DWORD grfFlags,LPCWSTR lpszFileSpec, // DWORD WINAPI DirList_IconThread(LPVOID lpParam) { - if (!lpParam) { - return(0); - } - LPDLDATA lpdl = (LPDLDATA)lpParam; - ResetEvent(lpdl->hTerminatedThread); + BackgroundWorker *worker = &lpdl->worker; // Exit immediately if DirList_Fill() hasn't been called if (!(lpdl->lpsf)) { - SetEvent(lpdl->hTerminatedThread); - ExitThread(0); - //return(0); + return(0); } - HWND hwnd = lpdl->hwnd; + HWND hwnd = worker->hwnd; int iMaxItem = ListView_GetItemCount(hwnd); - (void)CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY); - // Get IShellIcon IShellIcon* lpshi = NULL; lpdl->lpsf->lpVtbl->QueryInterface(lpdl->lpsf,&IID_IShellIcon, (void**)&lpshi); int iItem = 0; - while (iItem < iMaxItem && WaitForSingleObject(lpdl->hExitThread,0) != WAIT_OBJECT_0) { + while (iItem < iMaxItem && BackgroundWorker_Continue(worker)) { LV_ITEM lvi = { 0 }; @@ -499,11 +432,7 @@ DWORD WINAPI DirList_IconThread(LPVOID lpParam) lpshi->lpVtbl->Release(lpshi); } - CoUninitialize(); - - SetEvent(lpdl->hTerminatedThread); - ExitThread(0); - //return(0); + return 0; } @@ -516,6 +445,8 @@ DWORD WINAPI DirList_IconThread(LPVOID lpParam) // bool DirList_GetDispInfo(HWND hwnd,LPARAM lParam,bool bNoFadeHidden) { + UNREFERENCED_PARAMETER(hwnd); + UNREFERENCED_PARAMETER(bNoFadeHidden); LV_DISPINFO *lpdi = (LPVOID)lParam; @@ -534,9 +465,6 @@ bool DirList_GetDispInfo(HWND hwnd,LPARAM lParam,bool bNoFadeHidden) // Set values lpdi->item.mask |= LVIF_DI_SETITEM; - UNREFERENCED_PARAMETER(hwnd); - UNREFERENCED_PARAMETER(bNoFadeHidden); - return true; } diff --git a/src/Dlapi.h b/src/Dlapi.h index a43bcc5fe..85e731c9c 100644 --- a/src/Dlapi.h +++ b/src/Dlapi.h @@ -46,12 +46,7 @@ bool DirList_Destroy(HWND hwnd); //==== DlStartIconThread() ==================================================== -bool DirList_StartIconThread(HWND hwnd); - - -//==== DlTerminateIconThread() ================================================ - -bool DirList_TerminateIconThread(HWND hwnd); +void DirList_StartIconThread(HWND hwnd); //==== DlFill() =============================================================== diff --git a/src/Edit.c b/src/Edit.c index 4e2f508f4..0cb1ab5a2 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -6826,8 +6826,6 @@ static INT_PTR CALLBACK EditFindReplaceDlgProc(HWND hwnd, UINT umsg, WPARAM wPar // HWND EditFindReplaceDlg(HWND hwnd, LPEDITFINDREPLACE lpefr, bool bReplace) { - (void)CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY); - lpefr->hwnd = hwnd; HWND hDlg = CreateThemedDialogParam(Globals.hLngResContainer, (bReplace) ? MAKEINTRESOURCEW(IDD_MUI_REPLACE) : MAKEINTRESOURCEW(IDD_MUI_FIND), @@ -6838,7 +6836,6 @@ HWND EditFindReplaceDlg(HWND hwnd, LPEDITFINDREPLACE lpefr, bool bReplace) if (IS_VALID_HANDLE(hDlg)) { ShowWindow(hDlg, SW_SHOW); } - CoUninitialize(); return hDlg; } diff --git a/src/Helpers.c b/src/Helpers.c index 30529a36a..3524158bb 100644 --- a/src/Helpers.c +++ b/src/Helpers.c @@ -568,6 +568,41 @@ bool IsRunAsAdmin() return (bool)fIsRunAsAdmin; } +//============================================================================= + + +void BackgroundWorker_Init(BackgroundWorker *worker, HWND hwnd) { + worker->hwnd = hwnd; + worker->eventCancel = CreateEvent(NULL, TRUE, FALSE, NULL); + worker->workerThread = NULL; +} + +void BackgroundWorker_Stop(BackgroundWorker *worker) { + SetEvent(worker->eventCancel); + HANDLE workerThread = worker->workerThread; + if (workerThread) { + worker->workerThread = NULL; + while (WaitForSingleObject(workerThread, 0) != WAIT_OBJECT_0) { + MSG msg; + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + CloseHandle(workerThread); + } +} + +void BackgroundWorker_Cancel(BackgroundWorker *worker) { + BackgroundWorker_Stop(worker); + ResetEvent(worker->eventCancel); +} + +void BackgroundWorker_Destroy(BackgroundWorker *worker) { + BackgroundWorker_Stop(worker); + CloseHandle(worker->eventCancel); +} + //============================================================================= // diff --git a/src/Helpers.h b/src/Helpers.h index fa132ec13..a702d97a6 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -355,6 +355,18 @@ bool IsProcessElevated(); bool IsUserInAdminGroup(); bool IsRunAsAdmin(); +typedef struct BackgroundWorker { + HWND hwnd; + HANDLE eventCancel; + HANDLE workerThread; +} BackgroundWorker; + +void BackgroundWorker_Init(BackgroundWorker *worker, HWND hwnd); +void BackgroundWorker_Cancel(BackgroundWorker *worker); +void BackgroundWorker_Destroy(BackgroundWorker *worker); +#define BackgroundWorker_Continue(worker) \ + (WaitForSingleObject((worker)->eventCancel, 0) != WAIT_OBJECT_0) + bool BitmapMergeAlpha(HBITMAP hbmp,COLORREF crDest); bool BitmapAlphaBlend(HBITMAP hbmp,COLORREF crDest,BYTE alpha); bool BitmapGrayScale(HBITMAP hbmp);