/* TODO: This code should be coalesced with the code that adds items as well as the code that finds their icons. ALL changes to an items name/internal properties/icon/overlay icon should go through a central function. */ void CFolderView::RenameItem(int iItemInternal,TCHAR *szNewFileName) { IShellFolder *pShellFolder = NULL; LPITEMIDLIST pidlFull = NULL; LPITEMIDLIST pidlRelative = NULL; SHFILEINFO shfi; LVFINDINFO lvfi; TCHAR szDisplayName[MAX_PATH]; LVITEM lvItem; TCHAR szFullFileName[MAX_PATH]; DWORD_PTR res; HRESULT hr; int iItem; if(iItemInternal == -1) return; StringCchCopy(szFullFileName,MAX_PATH,m_CurDir); PathAppend(szFullFileName,szNewFileName); hr = GetIdlFromParsingName(szFullFileName,&pidlFull); if(SUCCEEDED(hr)) { hr = SHBindToParent(pidlFull,IID_IShellFolder,(void **)&pShellFolder,(LPCITEMIDLIST *)&pidlRelative); if(SUCCEEDED(hr)) { hr = GetDisplayName(szFullFileName,szDisplayName,SHGDN_INFOLDER|SHGDN_FORPARSING); if(SUCCEEDED(hr)) { m_pExtraItemInfo[iItemInternal].pridl = ILClone(pidlRelative); StringCchCopy(m_pExtraItemInfo[iItemInternal].szDisplayName, SIZEOF_ARRAY(m_pExtraItemInfo[iItemInternal].szDisplayName), szDisplayName); /* Need to update internal storage for the item, since it's name has now changed. */ StringCchCopy(m_pwfdFiles[iItemInternal].cFileName, SIZEOF_ARRAY(m_pwfdFiles[iItemInternal].cFileName), szNewFileName); /* The files' type may have changed, so retrieve the files' icon again. */ res = SHGetFileInfo((LPTSTR)pidlFull,0,&shfi, sizeof(SHFILEINFO),SHGFI_PIDL|SHGFI_ICON| SHGFI_OVERLAYINDEX); if(res != 0) { /* Locate the item within the listview. */ lvfi.flags = LVFI_PARAM; lvfi.lParam = iItemInternal; iItem = ListView_FindItem(m_hListView,-1,&lvfi); if(iItem != -1) { lvItem.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_STATE; lvItem.iItem = iItem; lvItem.iSubItem = 0; lvItem.iImage = shfi.iIcon; lvItem.pszText = ProcessItemFileName(iItemInternal); lvItem.stateMask = LVIS_OVERLAYMASK; /* As well as resetting the items icon, we'll also set it's overlay again (the overlay could change, for example, if the file is changed to a shortcut). */ lvItem.state = INDEXTOOVERLAYMASK(shfi.iIcon >> 24); /* Update the item in the listview. */ ListView_SetItem(m_hListView,&lvItem); /* TODO: Does the file need to be filtered out? */ if(IsFileFiltered(iItemInternal)) { RemoveFilteredItem(iItem,iItemInternal); } } DestroyIcon(shfi.hIcon); } } pShellFolder->Release(); }
void inline CShellBrowser::InsertAwaitingItems(BOOL bInsertIntoGroup) { LVITEM lv; ULARGE_INTEGER ulFileSize; unsigned int nPrevItems; int nAdded = 0; int iItemIndex; nPrevItems = ListView_GetItemCount(m_hListView); m_nAwaitingAdd = (int)m_AwaitingAddList.size(); if((nPrevItems + m_nAwaitingAdd) == 0) { if(m_bApplyFilter) SendMessage(m_hOwner,WM_USER_FILTERINGAPPLIED,m_ID,TRUE); else SendMessage(m_hOwner,WM_USER_FOLDEREMPTY,m_ID,TRUE); m_nTotalItems = 0; return; } else if(!m_bApplyFilter) { SendMessage(m_hOwner,WM_USER_FOLDEREMPTY,m_ID,FALSE); } /* Make the listview allocate space (for internal data structures) for all the items at once, rather than individually. Acts as a speed optimization. */ ListView_SetItemCount(m_hListView,m_nAwaitingAdd + nPrevItems); lv.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM; if(bInsertIntoGroup) lv.mask |= LVIF_GROUPID; /* Constant for each item. */ lv.iSubItem = 0; if(m_bAutoArrange) NListView::ListView_SetAutoArrange(m_hListView,FALSE); for(auto itr = m_AwaitingAddList.begin();itr != m_AwaitingAddList.end();itr++) { if(!IsFileFiltered(itr->iItemInternal)) { lv.iItem = itr->iItem; lv.pszText = ProcessItemFileName(itr->iItemInternal); lv.iImage = I_IMAGECALLBACK; lv.lParam = itr->iItemInternal; if(bInsertIntoGroup) { lv.iGroupId = DetermineItemGroup(itr->iItemInternal); } /* Insert the item into the list view control. */ iItemIndex = ListView_InsertItem(m_hListView,&lv); if(itr->bPosition && m_ViewMode != VM_DETAILS) { POINT ptItem; if(itr->iAfter != -1) { ListView_GetItemPosition(m_hListView,itr->iAfter,&ptItem); } else { ptItem.x = 0; ptItem.y = 0; } /* The item will end up in the position AFTER iAfter. */ ListView_SetItemPosition32(m_hListView,iItemIndex,ptItem.x,ptItem.y); } if(m_ViewMode == VM_TILES) { SetTileViewItemInfo(iItemIndex,itr->iItemInternal); } if(m_bNewItemCreated) { LPITEMIDLIST pidlComplete = NULL; pidlComplete = ILCombine(m_pidlDirectory,m_pExtraItemInfo[(int)itr->iItemInternal].pridl); if(CompareIdls(pidlComplete,m_pidlNewItem)) m_bNewItemCreated = FALSE; m_iIndexNewItem = iItemIndex; CoTaskMemFree(pidlComplete); } /* If the file is marked as hidden, ghost it out. */ if(m_pwfdFiles[itr->iItemInternal].dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) { ListView_SetItemState(m_hListView,iItemIndex,LVIS_CUT,LVIS_CUT); } /* Add the current file's size to the running size of the current directory. */ /* A folder may or may not have 0 in its high file size member. It should either be zeroed, or never counted. */ ulFileSize.LowPart = m_pwfdFiles[itr->iItemInternal].nFileSizeLow; ulFileSize.HighPart = m_pwfdFiles[itr->iItemInternal].nFileSizeHigh; m_ulTotalDirSize.QuadPart += ulFileSize.QuadPart; nAdded++; } else { m_FilteredItemsList.push_back(itr->iItemInternal); } } if(m_bAutoArrange) NListView::ListView_SetAutoArrange(m_hListView,TRUE); m_nTotalItems = nPrevItems + nAdded; if(m_ViewMode == VM_DETAILS) { TCHAR szDrive[MAX_PATH]; BOOL bNetworkRemovable = FALSE; QueueUserAPC(SetAllColumnDataAPC,m_hThread,(ULONG_PTR)this); StringCchCopy(szDrive,SIZEOF_ARRAY(szDrive),m_CurDir); PathStripToRoot(szDrive); if(GetDriveType(szDrive) == DRIVE_REMOVABLE || GetDriveType(szDrive) == DRIVE_REMOTE) { bNetworkRemovable = TRUE; } /* If the user has selected to disable folder sizes on removable drives or networks, and we are currently on such a drive, do not calculate folder sizes. */ if(m_bShowFolderSizes && !(m_bDisableFolderSizesNetworkRemovable && bNetworkRemovable)) QueueUserAPC(SetAllFolderSizeColumnDataAPC,m_hFolderSizeThread,(ULONG_PTR)this); } PositionDroppedItems(); m_AwaitingAddList.clear(); m_nAwaitingAdd = 0; }