https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9a1487f3a8997e3ea10328749dada70222868e54

commit 9a1487f3a8997e3ea10328749dada70222868e54
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Wed Jul 12 22:24:04 2023 +0900
Commit:     GitHub <[email protected]>
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);
 

Reply via email to