Skip to content

Commit

Permalink
[SHELL32] Update the status bar asynchronously (reactos#5420)
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
katahiromz authored Jul 12, 2023
1 parent 8d82129 commit 9a1487f
Showing 1 changed file with 57 additions and 14 deletions.
71 changes: 57 additions & 14 deletions dll/win32/shell32/CDefView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#include "precomp.h"

#include <process.h>
#include <atlwin.h>
#include <ui/rosctrls.h>

Expand Down Expand Up @@ -153,6 +154,7 @@ class CDefView :
SFVM_CUSTOMVIEWINFO_DATA m_viewinfo_data;

HICON m_hMyComputerIcon;
HANDLE m_hUpdateStatusbarThread;

private:
HRESULT _MergeToolbar();
Expand All @@ -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();
Expand Down Expand Up @@ -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));
Expand All @@ -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()
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand All @@ -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));
Expand All @@ -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 #####
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit 9a1487f

Please sign in to comment.