mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 20:25:39 +00:00
[BROWSEUI] CExplorerBand: Use SHCNRF_NewDelivery method (#7133)
Refactoring. Optimize for speed. JIRA issue: CORE-12619 - Update file headers. - Make some parameter type LPITEMIDLIST LPCITEMIDLIST (Add const). - Add OnChangeNotify method. - Use SHCNRF_NewDelivery method for speed. - Add some SAL annotations.
This commit is contained in:
parent
4093d0e164
commit
7bec458077
2 changed files with 85 additions and 64 deletions
|
@ -1,22 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* ReactOS Explorer
|
* PROJECT: ReactOS Explorer
|
||||||
*
|
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||||
* Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com>
|
* PURPOSE: Explorer bar
|
||||||
* Copyright 2020 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
* COPYRIGHT: Copyright 2016 Sylvain Deverre <deverre.sylv@gmail.com>
|
||||||
*
|
* Copyright 2020-2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
@ -87,7 +74,9 @@ HRESULT GetDisplayName(LPCITEMIDLIST pidlDirectory,TCHAR *szDisplayName,UINT cch
|
||||||
ill-formed PIDL stripped from useful data that parses incorrectly with SHGetFileInfo.
|
ill-formed PIDL stripped from useful data that parses incorrectly with SHGetFileInfo.
|
||||||
So we need to re-enumerate subfolders until we find one with the same name.
|
So we need to re-enumerate subfolders until we find one with the same name.
|
||||||
*/
|
*/
|
||||||
HRESULT _ReparsePIDL(LPITEMIDLIST buggyPidl, LPITEMIDLIST *cleanPidl)
|
HRESULT _ReparsePIDL(
|
||||||
|
_In_ LPCITEMIDLIST buggyPidl,
|
||||||
|
_Out_ LPITEMIDLIST *cleanPidl)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
CComPtr<IShellFolder> folder;
|
CComPtr<IShellFolder> folder;
|
||||||
|
@ -187,7 +176,7 @@ void CExplorerBand::InitializeExplorerBand()
|
||||||
TreeView_SetImageList(m_hWnd, (HIMAGELIST)piml, TVSIL_NORMAL);
|
TreeView_SetImageList(m_hWnd, (HIMAGELIST)piml, TVSIL_NORMAL);
|
||||||
|
|
||||||
// Insert the root node
|
// Insert the root node
|
||||||
m_hRoot = InsertItem(0, m_pDesktop, pidl, pidl, FALSE);
|
m_hRoot = InsertItem(NULL, m_pDesktop, pidl, pidl, FALSE);
|
||||||
if (!m_hRoot)
|
if (!m_hRoot)
|
||||||
{
|
{
|
||||||
ERR("Failed to create root item\n");
|
ERR("Failed to create root item\n");
|
||||||
|
@ -208,7 +197,7 @@ void CExplorerBand::InitializeExplorerBand()
|
||||||
shcne.fRecursive = TRUE;
|
shcne.fRecursive = TRUE;
|
||||||
m_shellRegID = SHChangeNotifyRegister(
|
m_shellRegID = SHChangeNotifyRegister(
|
||||||
m_hWnd,
|
m_hWnd,
|
||||||
SHCNRF_ShellLevel | SHCNRF_InterruptLevel | SHCNRF_RecursiveInterrupt,
|
SHCNRF_NewDelivery | SHCNRF_ShellLevel | SHCNRF_InterruptLevel | SHCNRF_RecursiveInterrupt,
|
||||||
SHCNE_DISKEVENTS | SHCNE_RENAMEFOLDER | SHCNE_RMDIR | SHCNE_MKDIR,
|
SHCNE_DISKEVENTS | SHCNE_RENAMEFOLDER | SHCNE_RMDIR | SHCNE_MKDIR,
|
||||||
WM_USER_SHELLEVENT,
|
WM_USER_SHELLEVENT,
|
||||||
1,
|
1,
|
||||||
|
@ -580,35 +569,59 @@ LRESULT CExplorerBand::ContextMenuHack(UINT uMsg, WPARAM wParam, LPARAM lParam,
|
||||||
return FALSE; /* let the wndproc process the message */
|
return FALSE; /* let the wndproc process the message */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WM_USER_SHELLEVENT
|
||||||
LRESULT CExplorerBand::OnShellEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
|
LRESULT CExplorerBand::OnShellEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
|
||||||
{
|
{
|
||||||
LPITEMIDLIST *dest;
|
// We use SHCNRF_NewDelivery method
|
||||||
|
HANDLE hChange = (HANDLE)wParam;
|
||||||
|
DWORD dwProcID = (DWORD)lParam;
|
||||||
|
|
||||||
|
PIDLIST_ABSOLUTE *ppidl = NULL;
|
||||||
|
LONG lEvent;
|
||||||
|
HANDLE hLock = SHChangeNotification_Lock(hChange, dwProcID, &ppidl, &lEvent);
|
||||||
|
if (hLock == NULL)
|
||||||
|
{
|
||||||
|
ERR("hLock == NULL\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnChangeNotify(ppidl[0], ppidl[1], (lEvent & ~SHCNE_INTERRUPT));
|
||||||
|
|
||||||
|
SHChangeNotification_Unlock(hLock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CExplorerBand::OnChangeNotify(
|
||||||
|
_In_opt_ LPCITEMIDLIST pidl0,
|
||||||
|
_In_opt_ LPCITEMIDLIST pidl1,
|
||||||
|
_In_ LONG lEvent)
|
||||||
|
{
|
||||||
LPITEMIDLIST clean;
|
LPITEMIDLIST clean;
|
||||||
HTREEITEM pItem;
|
HTREEITEM pItem;
|
||||||
|
|
||||||
dest = (LPITEMIDLIST*)wParam;
|
|
||||||
/* TODO: handle shell notifications */
|
/* TODO: handle shell notifications */
|
||||||
switch(lParam & ~SHCNE_INTERRUPT)
|
switch (lEvent)
|
||||||
{
|
{
|
||||||
case SHCNE_MKDIR:
|
case SHCNE_MKDIR:
|
||||||
if (!SUCCEEDED(_ReparsePIDL(dest[0], &clean)))
|
if (!SUCCEEDED(_ReparsePIDL(pidl0, &clean)))
|
||||||
{
|
{
|
||||||
ERR("Can't reparse PIDL to a valid one\n");
|
ERR("Can't reparse PIDL to a valid one\n");
|
||||||
return FALSE;
|
break;
|
||||||
}
|
}
|
||||||
NavigateToPIDL(clean, &pItem, FALSE, TRUE, FALSE);
|
NavigateToPIDL(clean, &pItem, FALSE, TRUE, FALSE);
|
||||||
ILFree(clean);
|
ILFree(clean);
|
||||||
break;
|
break;
|
||||||
case SHCNE_RMDIR:
|
case SHCNE_RMDIR:
|
||||||
DeleteItem(dest[0]);
|
DeleteItem(pidl0);
|
||||||
break;
|
break;
|
||||||
case SHCNE_RENAMEFOLDER:
|
case SHCNE_RENAMEFOLDER:
|
||||||
if (!SUCCEEDED(_ReparsePIDL(dest[1], &clean)))
|
if (!SUCCEEDED(_ReparsePIDL(pidl1, &clean)))
|
||||||
{
|
{
|
||||||
ERR("Can't reparse PIDL to a valid one\n");
|
ERR("Can't reparse PIDL to a valid one\n");
|
||||||
return FALSE;
|
break;
|
||||||
}
|
}
|
||||||
if (NavigateToPIDL(dest[0], &pItem, FALSE, FALSE, FALSE))
|
if (NavigateToPIDL(pidl0, &pItem, FALSE, FALSE, FALSE))
|
||||||
RenameItem(pItem, clean);
|
RenameItem(pItem, clean);
|
||||||
ILFree(clean);
|
ILFree(clean);
|
||||||
break;
|
break;
|
||||||
|
@ -619,7 +632,6 @@ LRESULT CExplorerBand::OnShellEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOO
|
||||||
default:
|
default:
|
||||||
TRACE("Unhandled message\n");
|
TRACE("Unhandled message\n");
|
||||||
}
|
}
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CExplorerBand::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
|
LRESULT CExplorerBand::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
|
||||||
|
@ -638,7 +650,13 @@ LRESULT CExplorerBand::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL
|
||||||
}
|
}
|
||||||
|
|
||||||
// *** Helper functions ***
|
// *** Helper functions ***
|
||||||
HTREEITEM CExplorerBand::InsertItem(HTREEITEM hParent, IShellFolder *psfParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort)
|
HTREEITEM
|
||||||
|
CExplorerBand::InsertItem(
|
||||||
|
_In_opt_ HTREEITEM hParent,
|
||||||
|
_Inout_ IShellFolder *psfParent,
|
||||||
|
_In_ LPCITEMIDLIST pElt,
|
||||||
|
_In_ LPCITEMIDLIST pEltRelative,
|
||||||
|
_In_ BOOL bSort)
|
||||||
{
|
{
|
||||||
TV_INSERTSTRUCT tvInsert;
|
TV_INSERTSTRUCT tvInsert;
|
||||||
HTREEITEM htiCreated;
|
HTREEITEM htiCreated;
|
||||||
|
@ -707,7 +725,12 @@ HTREEITEM CExplorerBand::InsertItem(HTREEITEM hParent, IShellFolder *psfParent,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the slow version of the above method */
|
/* This is the slow version of the above method */
|
||||||
HTREEITEM CExplorerBand::InsertItem(HTREEITEM hParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort)
|
HTREEITEM
|
||||||
|
CExplorerBand::InsertItem(
|
||||||
|
_In_opt_ HTREEITEM hParent,
|
||||||
|
_In_ LPCITEMIDLIST pElt,
|
||||||
|
_In_ LPCITEMIDLIST pEltRelative,
|
||||||
|
_In_ BOOL bSort)
|
||||||
{
|
{
|
||||||
CComPtr<IShellFolder> psfFolder;
|
CComPtr<IShellFolder> psfFolder;
|
||||||
HRESULT hr = SHBindToParent(pElt, IID_PPV_ARG(IShellFolder, &psfFolder), NULL);
|
HRESULT hr = SHBindToParent(pElt, IID_PPV_ARG(IShellFolder, &psfFolder), NULL);
|
||||||
|
@ -805,7 +828,7 @@ BOOL CExplorerBand::InsertSubitems(HTREEITEM hItem, NodeInfo *pNodeInfo)
|
||||||
* - bInsert: insert the element at the right place if we don't find it
|
* - bInsert: insert the element at the right place if we don't find it
|
||||||
* - bSelect: select the item after we found it
|
* - bSelect: select the item after we found it
|
||||||
*/
|
*/
|
||||||
BOOL CExplorerBand::NavigateToPIDL(LPITEMIDLIST dest, HTREEITEM *item, BOOL bExpand, BOOL bInsert,
|
BOOL CExplorerBand::NavigateToPIDL(LPCITEMIDLIST dest, HTREEITEM *item, BOOL bExpand, BOOL bInsert,
|
||||||
BOOL bSelect)
|
BOOL bSelect)
|
||||||
{
|
{
|
||||||
HTREEITEM current;
|
HTREEITEM current;
|
||||||
|
@ -917,7 +940,7 @@ BOOL CExplorerBand::NavigateToCurrentFolder()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CExplorerBand::DeleteItem(LPITEMIDLIST idl)
|
BOOL CExplorerBand::DeleteItem(LPCITEMIDLIST idl)
|
||||||
{
|
{
|
||||||
HTREEITEM toDelete;
|
HTREEITEM toDelete;
|
||||||
TVITEM tvItem;
|
TVITEM tvItem;
|
||||||
|
@ -950,7 +973,7 @@ BOOL CExplorerBand::DeleteItem(LPITEMIDLIST idl)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CExplorerBand::RenameItem(HTREEITEM toRename, LPITEMIDLIST newPidl)
|
BOOL CExplorerBand::RenameItem(HTREEITEM toRename, LPCITEMIDLIST newPidl)
|
||||||
{
|
{
|
||||||
WCHAR wszDisplayName[MAX_PATH];
|
WCHAR wszDisplayName[MAX_PATH];
|
||||||
TVITEM itemInfo;
|
TVITEM itemInfo;
|
||||||
|
@ -1000,7 +1023,7 @@ BOOL CExplorerBand::RenameItem(HTREEITEM toRename, LPITEMIDLIST newPidl)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CExplorerBand::RefreshTreePidl(HTREEITEM tree, LPITEMIDLIST pidlParent)
|
BOOL CExplorerBand::RefreshTreePidl(HTREEITEM tree, LPCITEMIDLIST pidlParent)
|
||||||
{
|
{
|
||||||
HTREEITEM tmp;
|
HTREEITEM tmp;
|
||||||
NodeInfo *pInfo;
|
NodeInfo *pInfo;
|
||||||
|
@ -1340,7 +1363,6 @@ HRESULT STDMETHODCALLTYPE CExplorerBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// *** IWinEventHandler methods ***
|
// *** IWinEventHandler methods ***
|
||||||
HRESULT STDMETHODCALLTYPE CExplorerBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
|
HRESULT STDMETHODCALLTYPE CExplorerBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,28 +1,14 @@
|
||||||
/*
|
/*
|
||||||
* ReactOS Explorer
|
* PROJECT: ReactOS Explorer
|
||||||
*
|
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||||
* Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com>
|
* PURPOSE: Explorer bar
|
||||||
* Copyright 2020 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
* COPYRIGHT: Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com>
|
||||||
*
|
* Copyright 2020-2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define WM_USER_SHELLEVENT WM_USER+88
|
#define WM_USER_SHELLEVENT (WM_USER + 88)
|
||||||
#define WM_USER_FOLDEREVENT WM_USER+88
|
|
||||||
|
|
||||||
class CExplorerBand :
|
class CExplorerBand :
|
||||||
public CComCoClass<CExplorerBand, &CLSID_ExplorerBand>,
|
public CComCoClass<CExplorerBand, &CLSID_ExplorerBand>,
|
||||||
|
@ -95,16 +81,29 @@ private:
|
||||||
// *** Helper functions ***
|
// *** Helper functions ***
|
||||||
NodeInfo* GetNodeInfo(HTREEITEM hItem);
|
NodeInfo* GetNodeInfo(HTREEITEM hItem);
|
||||||
HRESULT UpdateBrowser(LPITEMIDLIST pidlGoto);
|
HRESULT UpdateBrowser(LPITEMIDLIST pidlGoto);
|
||||||
HTREEITEM InsertItem(HTREEITEM hParent, IShellFolder *psfParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort);
|
HTREEITEM InsertItem(
|
||||||
HTREEITEM InsertItem(HTREEITEM hParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort);
|
_In_opt_ HTREEITEM hParent,
|
||||||
|
_Inout_ IShellFolder *psfParent,
|
||||||
|
_In_ LPCITEMIDLIST pElt,
|
||||||
|
_In_ LPCITEMIDLIST pEltRelative,
|
||||||
|
_In_ BOOL bSort);
|
||||||
|
HTREEITEM InsertItem(
|
||||||
|
_In_opt_ HTREEITEM hParent,
|
||||||
|
_In_ LPCITEMIDLIST pElt,
|
||||||
|
_In_ LPCITEMIDLIST pEltRelative,
|
||||||
|
_In_ BOOL bSort);
|
||||||
BOOL InsertSubitems(HTREEITEM hItem, NodeInfo *pNodeInfo);
|
BOOL InsertSubitems(HTREEITEM hItem, NodeInfo *pNodeInfo);
|
||||||
BOOL NavigateToPIDL(LPITEMIDLIST dest, HTREEITEM *item, BOOL bExpand, BOOL bInsert, BOOL bSelect);
|
BOOL NavigateToPIDL(LPCITEMIDLIST dest, HTREEITEM *item, BOOL bExpand, BOOL bInsert, BOOL bSelect);
|
||||||
BOOL DeleteItem(LPITEMIDLIST toDelete);
|
BOOL DeleteItem(LPCITEMIDLIST toDelete);
|
||||||
BOOL RenameItem(HTREEITEM toRename, LPITEMIDLIST newPidl);
|
BOOL RenameItem(HTREEITEM toRename, LPCITEMIDLIST newPidl);
|
||||||
BOOL RefreshTreePidl(HTREEITEM tree, LPITEMIDLIST pidlParent);
|
BOOL RefreshTreePidl(HTREEITEM tree, LPCITEMIDLIST pidlParent);
|
||||||
BOOL NavigateToCurrentFolder();
|
BOOL NavigateToCurrentFolder();
|
||||||
HRESULT GetCurrentLocation(PIDLIST_ABSOLUTE &pidl);
|
HRESULT GetCurrentLocation(PIDLIST_ABSOLUTE &pidl);
|
||||||
HRESULT IsCurrentLocation(PCIDLIST_ABSOLUTE pidl);
|
HRESULT IsCurrentLocation(PCIDLIST_ABSOLUTE pidl);
|
||||||
|
void OnChangeNotify(
|
||||||
|
_In_opt_ LPCITEMIDLIST pidl0,
|
||||||
|
_In_opt_ LPCITEMIDLIST pidl1,
|
||||||
|
_In_ LONG lEvent);
|
||||||
|
|
||||||
// *** Tree item sorting callback ***
|
// *** Tree item sorting callback ***
|
||||||
static int CALLBACK CompareTreeItems(LPARAM p1, LPARAM p2, LPARAM p3);
|
static int CALLBACK CompareTreeItems(LPARAM p1, LPARAM p2, LPARAM p3);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue