+ rfc: IconThread code refactoring

This commit is contained in:
Rainer Kottenhoff 2021-04-23 12:30:38 +02:00
parent 7d68851b35
commit 63657fa440
6 changed files with 105 additions and 173 deletions

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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() ===============================================================

View File

@ -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;
}

View File

@ -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);
}
//=============================================================================
//

View File

@ -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);