https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9a1487f3a8997e3ea10328...
commit 9a1487f3a8997e3ea10328749dada70222868e54 Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Wed Jul 12 22:24:04 2023 +0900 Commit: GitHub noreply@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);