mirror of
https://github.com/reactos/reactos.git
synced 2024-07-08 05:35:06 +00:00
[SHELL32] brfolder.cpp: Refresh items (#6965)
Refresh the items in the tree-view control of SHBrowseForFolderA/W functions against change notifications. JIRA issue: CORE-17340 - Add BrFolder_IsTreeItemInEnum and BrFolder_TreeItemHasThisChild helper functions. - Add BrFolder_Refresh, BrFolder_RefreshRecurse, and BrFolder_UpdateItem functions to refresh items. - Call BrFolder_Refresh in BrFolder_OnChangeEx function and on keyboard F5 and Ctrl+R actions.
This commit is contained in:
parent
c3ec1b9ac6
commit
b50ab0dc68
|
@ -254,6 +254,73 @@ BrFolder_GetName(
|
||||||
return bSuccess;
|
return bSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
BrFolder_IsTreeItemInEnum(
|
||||||
|
_Inout_ BrFolder *info,
|
||||||
|
_In_ HTREEITEM hItem,
|
||||||
|
_Inout_ IEnumIDList *pEnum)
|
||||||
|
{
|
||||||
|
BrItemData *pItemData = BrFolder_GetItemData(info, hItem);
|
||||||
|
if (!pItemData)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pEnum->Reset();
|
||||||
|
|
||||||
|
CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
|
||||||
|
while (pEnum->Next(1, &pidlTemp, NULL) == S_OK)
|
||||||
|
{
|
||||||
|
if (ILIsEqual(pidlTemp, pItemData->pidlChild))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
pidlTemp.Free();
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
BrFolder_TreeItemHasThisChild(
|
||||||
|
_In_ BrFolder *info,
|
||||||
|
_In_ HTREEITEM hItem,
|
||||||
|
_Outptr_opt_ PITEMID_CHILD pidlChild)
|
||||||
|
{
|
||||||
|
for (hItem = TreeView_GetChild(info->hwndTreeView, hItem); hItem;
|
||||||
|
hItem = TreeView_GetNextSibling(info->hwndTreeView, hItem))
|
||||||
|
{
|
||||||
|
BrItemData *pItemData = BrFolder_GetItemData(info, hItem);
|
||||||
|
if (ILIsEqual(pItemData->pidlChild, pidlChild))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
BrFolder_UpdateItem(
|
||||||
|
_In_ BrFolder *info,
|
||||||
|
_In_ HTREEITEM hItem)
|
||||||
|
{
|
||||||
|
BrItemData *pItemData = BrFolder_GetItemData(info, hItem);
|
||||||
|
if (!pItemData)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TVITEMW item = { TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN };
|
||||||
|
item.hItem = hItem;
|
||||||
|
|
||||||
|
BrFolder_GetIconPair(pItemData->pidlFull, &item);
|
||||||
|
|
||||||
|
item.cChildren = 0;
|
||||||
|
CComPtr<IEnumIDList> pEnum;
|
||||||
|
if (BrFolder_GetChildrenEnum(info, pItemData, &pEnum) == S_OK)
|
||||||
|
{
|
||||||
|
CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
|
||||||
|
if (pEnum->Next(1, &pidlTemp, NULL) == S_OK)
|
||||||
|
++item.cChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeView_SetItem(info->hwndTreeView, &item);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* BrFolder_InsertItem [Internal]
|
* BrFolder_InsertItem [Internal]
|
||||||
*
|
*
|
||||||
|
@ -335,7 +402,7 @@ BrFolder_Expand(
|
||||||
SetCapture(info->hWnd);
|
SetCapture(info->hWnd);
|
||||||
SetCursor(LoadCursorW(NULL, (LPWSTR)IDC_WAIT));
|
SetCursor(LoadCursorW(NULL, (LPWSTR)IDC_WAIT));
|
||||||
|
|
||||||
CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlTemp;
|
CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
|
||||||
ULONG ulFetched;
|
ULONG ulFetched;
|
||||||
while (S_OK == pEnum->Next(1, &pidlTemp, &ulFetched))
|
while (S_OK == pEnum->Next(1, &pidlTemp, &ulFetched))
|
||||||
{
|
{
|
||||||
|
@ -474,7 +541,7 @@ BrFolder_Treeview_Rename(BrFolder *info, NMTVDISPINFOW *pnmtv)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
LPITEMIDLIST newFull;
|
LPITEMIDLIST newFull;
|
||||||
if (SUCCEEDED(hr = SHILClone((LPITEMIDLIST)data->pidlFull, &newFull)))
|
if (SUCCEEDED(hr = SHILClone(data->pidlFull, &newFull)))
|
||||||
{
|
{
|
||||||
ILRemoveLastID(newFull);
|
ILRemoveLastID(newFull);
|
||||||
if (SUCCEEDED(hr = SHILAppend(newChild, &newFull)))
|
if (SUCCEEDED(hr = SHILAppend(newChild, &newFull)))
|
||||||
|
@ -525,6 +592,9 @@ BrFolder_Delete(BrFolder *info, HTREEITEM hItem)
|
||||||
SHFileOperationW(&fileop);
|
SHFileOperationW(&fileop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
BrFolder_Refresh(_Inout_ BrFolder *info);
|
||||||
|
|
||||||
static LRESULT
|
static LRESULT
|
||||||
BrFolder_Treeview_Keydown(BrFolder *info, LPNMTVKEYDOWN keydown)
|
BrFolder_Treeview_Keydown(BrFolder *info, LPNMTVKEYDOWN keydown)
|
||||||
{
|
{
|
||||||
|
@ -542,6 +612,17 @@ BrFolder_Treeview_Keydown(BrFolder *info, LPNMTVKEYDOWN keydown)
|
||||||
case VK_DELETE:
|
case VK_DELETE:
|
||||||
BrFolder_Delete(info, hItem);
|
BrFolder_Delete(info, hItem);
|
||||||
break;
|
break;
|
||||||
|
case 'R':
|
||||||
|
{
|
||||||
|
if (GetKeyState(VK_CONTROL) < 0) // Ctrl+R
|
||||||
|
BrFolder_Refresh(info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VK_F5:
|
||||||
|
{
|
||||||
|
BrFolder_Refresh(info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1024,24 +1105,63 @@ BrFolder_OnDestroy(BrFolder *info)
|
||||||
SHChangeNotifyDeregister(info->hChangeNotify);
|
SHChangeNotifyDeregister(info->hChangeNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find a treeview node by recursively walking the treeview
|
static void
|
||||||
static HTREEITEM
|
BrFolder_RefreshRecurse(
|
||||||
BrFolder_FindItemByPidl(BrFolder *info, PCIDLIST_ABSOLUTE pidlFull, HTREEITEM hItem)
|
_Inout_ BrFolder *info,
|
||||||
|
_In_ HTREEITEM hTarget)
|
||||||
{
|
{
|
||||||
BrItemData *item_data = BrFolder_GetItemData(info, hItem);
|
// Get enum
|
||||||
|
CComPtr<IEnumIDList> pEnum;
|
||||||
|
BrItemData *pItemData = BrFolder_GetItemData(info, hTarget);
|
||||||
|
HRESULT hrEnum = BrFolder_GetChildrenEnum(info, pItemData, &pEnum);
|
||||||
|
|
||||||
if (ILIsEqual(item_data->pidlFull, pidlFull))
|
// Insert new items
|
||||||
return hItem;
|
if (SUCCEEDED(hrEnum))
|
||||||
|
|
||||||
for (hItem = TreeView_GetChild(info->hwndTreeView, hItem); hItem;
|
|
||||||
hItem = TreeView_GetNextSibling(info->hwndTreeView, hItem))
|
|
||||||
{
|
{
|
||||||
HTREEITEM newItem = BrFolder_FindItemByPidl(info, pidlFull, hItem);
|
CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
|
||||||
if (newItem)
|
while (S_OK == pEnum->Next(1, &pidlTemp, NULL))
|
||||||
return newItem;
|
{
|
||||||
|
if (!BrFolder_TreeItemHasThisChild(info, hTarget, pidlTemp))
|
||||||
|
{
|
||||||
|
BrFolder_InsertItem(info, pItemData->lpsfParent, pidlTemp, pItemData->pidlFull,
|
||||||
|
hTarget);
|
||||||
|
}
|
||||||
|
pidlTemp.Free();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
// Delete zombie items and update items
|
||||||
|
HTREEITEM hItem, hNextItem;
|
||||||
|
for (hItem = TreeView_GetChild(info->hwndTreeView, hTarget); hItem; hItem = hNextItem)
|
||||||
|
{
|
||||||
|
hNextItem = TreeView_GetNextSibling(info->hwndTreeView, hItem);
|
||||||
|
|
||||||
|
if (FAILED(hrEnum) || !BrFolder_IsTreeItemInEnum(info, hItem, pEnum))
|
||||||
|
{
|
||||||
|
TreeView_DeleteItem(info->hwndTreeView, hItem);
|
||||||
|
hNextItem = TreeView_GetChild(info->hwndTreeView, hTarget);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BrFolder_UpdateItem(info, hItem);
|
||||||
|
BrFolder_RefreshRecurse(info, hItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hrEnum))
|
||||||
|
TreeView_SortChildren(info->hwndTreeView, hTarget, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
BrFolder_Refresh(_Inout_ BrFolder *info)
|
||||||
|
{
|
||||||
|
HTREEITEM hRoot = TreeView_GetRoot(info->hwndTreeView);
|
||||||
|
|
||||||
|
SendMessageW(info->hwndTreeView, WM_SETREDRAW, FALSE, 0);
|
||||||
|
|
||||||
|
BrFolder_RefreshRecurse(info, hRoot);
|
||||||
|
|
||||||
|
SendMessageW(info->hwndTreeView, WM_SETREDRAW, TRUE, 0);
|
||||||
|
InvalidateRect(info->hwndTreeView, NULL, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1058,30 +1178,16 @@ BrFolder_OnChangeEx(
|
||||||
case SHCNE_DRIVEADD:
|
case SHCNE_DRIVEADD:
|
||||||
case SHCNE_MKDIR:
|
case SHCNE_MKDIR:
|
||||||
case SHCNE_CREATE:
|
case SHCNE_CREATE:
|
||||||
{
|
|
||||||
// FIXME
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHCNE_DRIVEREMOVED:
|
case SHCNE_DRIVEREMOVED:
|
||||||
case SHCNE_RMDIR:
|
case SHCNE_RMDIR:
|
||||||
case SHCNE_DELETE:
|
case SHCNE_DELETE:
|
||||||
{
|
|
||||||
HTREEITEM hRoot = TreeView_GetRoot(info->hwndTreeView);
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
HTREEITEM hItem = BrFolder_FindItemByPidl(info, pidl0, hRoot);
|
|
||||||
if (!hItem)
|
|
||||||
break;
|
|
||||||
TreeView_DeleteItem(info->hwndTreeView, hItem);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHCNE_RENAMEFOLDER:
|
case SHCNE_RENAMEFOLDER:
|
||||||
case SHCNE_RENAMEITEM:
|
case SHCNE_RENAMEITEM:
|
||||||
case SHCNE_UPDATEDIR:
|
case SHCNE_UPDATEDIR:
|
||||||
case SHCNE_UPDATEITEM:
|
case SHCNE_UPDATEITEM:
|
||||||
{
|
{
|
||||||
// FIXME
|
// FIXME: Avoid full refresh and optimize for speed. Use pidl0 and pidl1
|
||||||
|
BrFolder_Refresh(info);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue