https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9a1487f3a8997e3ea1032…
commit 9a1487f3a8997e3ea10328749dada70222868e54
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Wed Jul 12 22:24:04 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Wed Jul 12 22:24:04 2023 +0900
[SHELL32] Update the status bar asynchronously (#5420)
- Selecting all in system32 was too slow.
- Make CDefView::UpdateStatusbar function asynchronized by using a thread.
- It makes selecting all very quick.
- Add m_hUpdateStatusbarThread to asynchronize.
CORE-18663
---
dll/win32/shell32/CDefView.cpp | 71 +++++++++++++++++++++++++++++++++---------
1 file changed, 57 insertions(+), 14 deletions(-)
diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp
index ebcfa767090..708ce00e060 100644
--- a/dll/win32/shell32/CDefView.cpp
+++ b/dll/win32/shell32/CDefView.cpp
@@ -36,6 +36,7 @@ TODO:
#include "precomp.h"
+#include <process.h>
#include <atlwin.h>
#include <ui/rosctrls.h>
@@ -153,6 +154,7 @@ class CDefView :
SFVM_CUSTOMVIEWINFO_DATA m_viewinfo_data;
HICON m_hMyComputerIcon;
+ HANDLE m_hUpdateStatusbarThread;
private:
HRESULT _MergeToolbar();
@@ -171,6 +173,8 @@ class CDefView :
HRESULT IncludeObject(PCUITEMID_CHILD pidl);
HRESULT OnDefaultCommand();
HRESULT OnStateChange(UINT uFlags);
+ static unsigned __stdcall _UpdateStatusbarProc(void *args);
+ void UpdateStatusbarWorker(HANDLE hThread);
void UpdateStatusbar();
void CheckToolbar();
BOOL CreateList();
@@ -428,7 +432,9 @@ CDefView::CDefView() :
m_cScrollDelay(0),
m_isEditing(FALSE),
m_isParentFolderSpecial(FALSE),
- m_Destroyed(FALSE)
+ m_Destroyed(FALSE),
+ m_hMyComputerIcon(::LoadIconW(shell32_hInstance,
MAKEINTRESOURCEW(IDI_SHELL_COMPUTER_DESKTOP))),
+ m_hUpdateStatusbarThread(NULL)
{
ZeroMemory(&m_FolderSettings, sizeof(m_FolderSettings));
ZeroMemory(&m_sortInfo, sizeof(m_sortInfo));
@@ -437,8 +443,6 @@ CDefView::CDefView() :
m_viewinfo_data.clrText = GetSysColor(COLOR_WINDOWTEXT);
m_viewinfo_data.clrTextBack = GetSysColor(COLOR_WINDOW);
m_viewinfo_data.hbmBack = NULL;
-
- m_hMyComputerIcon = LoadIconW(shell32_hInstance,
MAKEINTRESOURCEW(IDI_SHELL_COMPUTER_DESKTOP));
}
CDefView::~CDefView()
@@ -539,10 +543,9 @@ void CDefView::CheckToolbar()
}
}
-void CDefView::UpdateStatusbar()
+void CDefView::UpdateStatusbarWorker(HANDLE hThread)
{
- WCHAR szFormat[MAX_PATH] = {0};
- WCHAR szPartText[MAX_PATH] = {0};
+ WCHAR szFormat[MAX_PATH], szPartText[MAX_PATH];
UINT cSelectedItems;
cSelectedItems = m_ListView.GetSelectedCount();
@@ -571,12 +574,13 @@ void CDefView::UpdateStatusbar()
/* If we have something selected then only count selected file sizes. */
if (cSelectedItems)
- {
uFileFlags = LVNI_SELECTED;
- }
while ((nItem = m_ListView.GetNextItem(nItem, uFileFlags)) >= 0)
{
+ if (hThread != m_hUpdateStatusbarThread)
+ return;
+
PCUITEMID_CHILD pidl = _PidlByItem(nItem);
uTotalFileSize += _ILGetFileSize(pidl, NULL, 0);
@@ -589,18 +593,14 @@ void CDefView::UpdateStatusbar()
/* Don't show the file size text if there is 0 bytes in the folder
* OR we only have folders selected. */
+ szPartText[0] = UNICODE_NULL;
if ((cSelectedItems && !bIsOnlyFoldersSelected) || uTotalFileSize)
- {
StrFormatByteSizeW(uTotalFileSize, szPartText, _countof(szPartText));
- }
- else
- {
- *szPartText = 0;
- }
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 1, (LPARAM)szPartText,
&lResult);
/* If we are in a Recycle Bin folder then show no text for the location part. */
+ szPartText[0] = UNICODE_NULL;
if (!_ILIsBitBucket(m_pidlParent))
{
LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szPartText,
_countof(szPartText));
@@ -612,6 +612,38 @@ void CDefView::UpdateStatusbar()
}
}
+unsigned __stdcall CDefView::_UpdateStatusbarProc(void *args)
+{
+ CDefView* pView = static_cast<CDefView*>(args);
+ pView->UpdateStatusbarWorker(pView->m_hUpdateStatusbarThread);
+ pView->Release();
+ return 0;
+}
+
+void CDefView::UpdateStatusbar()
+{
+ HANDLE hOldThread = m_hUpdateStatusbarThread;
+
+ AddRef();
+
+ // We have to initialize m_hUpdateStatusbarThread before the target thread begins.
+ // So, we use CREATE_SUSPENDED.
+ HANDLE hNewThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0,
_UpdateStatusbarProc,
+ this, CREATE_SUSPENDED,
NULL));
+ if (hNewThread)
+ {
+ m_hUpdateStatusbarThread = hNewThread;
+ ::ResumeThread(hNewThread);
+
+ if (hOldThread)
+ ::CloseHandle(hOldThread);
+ }
+ else
+ {
+ Release();
+ }
+}
+
/**********************************************************
*
* ##### helperfunctions for initializing the view #####
@@ -2582,6 +2614,17 @@ HRESULT WINAPI CDefView::DestroyViewWindow()
{
TRACE("(%p)\n", this);
+ if (m_hUpdateStatusbarThread)
+ {
+ HANDLE hOldThread = m_hUpdateStatusbarThread;
+
+ // Assigning NULL to m_hUpdateStatusbarThread will terminate the target thread
immediately
+ m_hUpdateStatusbarThread = NULL;
+ ::WaitForSingleObject(hOldThread, INFINITE);
+
+ ::CloseHandle(hOldThread);
+ }
+
/* Make absolutely sure all our UI is cleaned up */
UIActivate(SVUIA_DEACTIVATE);