internal ShellItem(ShellBrowser browser, IntPtr pidl, IntPtr shellFolderPtr) { this.browser = browser; this.shellFolderPtr = shellFolderPtr; this.shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(shellFolderPtr, typeof(IShellFolder)); subFiles = new ShellItemCollection(this); subFolders = new ShellItemCollection(this); pidlRel = new PIDL(pidl, false); text = "Desktop"; path = "Desktop"; SetAttributesDesktop(this); ShellAPI.SHFILEINFO info = new ShellAPI.SHFILEINFO(); ShellAPI.SHGetFileInfo(pidlRel.Ptr, 0, ref info, ShellAPI.cbFileInfo, ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.TYPENAME | ShellAPI.SHGFI.SYSICONINDEX); type = info.szTypeName; ShellImageList.SetIconIndex(this, info.iIcon, false); ShellImageList.SetIconIndex(this, info.iIcon, true); sortFlag = 1; }
internal ShellItem(ShellBrowser browser, ShellItem parentItem, IntPtr pidl, IntPtr shellFolderPtr) { this.browser = browser; this.parentItem = parentItem; this.shellFolderPtr = shellFolderPtr; this.shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(shellFolderPtr, typeof(IShellFolder)); subFiles = new ShellItemCollection(this); subFolders = new ShellItemCollection(this); pidlRel = new PIDL(pidl, false); SetText(this); SetPath(this); SetAttributesFolder(this); SetInfo(this); sortFlag = MakeSortFlag(this); }
internal void Update(bool updateFiles, bool updateFolders) { if(browser.UpdateCondition.ContinueUpdate && (updateFiles || updateFolders) && ShellFolder != null && !disposed) { lock(browser) { #region Fields IntPtr fileEnumPtr = IntPtr.Zero, folderEnumPtr = IntPtr.Zero; IEnumIDList fileEnum = null, folderEnum = null; IntPtr pidlSubItem; int celtFetched; ShellAPI.SHCONTF fileFlag = ShellAPI.SHCONTF.NONFOLDERS | ShellAPI.SHCONTF.INCLUDEHIDDEN; ShellAPI.SHCONTF folderFlag = ShellAPI.SHCONTF.FOLDERS | ShellAPI.SHCONTF.INCLUDEHIDDEN; bool[] fileExists; fileExists = new bool[subFiles.Count]; bool[] folderExists; folderExists = new bool[subFolders.Count]; int index; #endregion try { #region Update Files if(browser.UpdateCondition.ContinueUpdate && updateFiles) { ShellItemCollection add = new ShellItemCollection(this); ShellItemCollection remove = new ShellItemCollection(this); bool fileEnumCompleted = false; #region Add Files if(this.Equals(browser.DesktopItem) || parentItem.Equals(browser.DesktopItem)) { if(ShellFolder.EnumObjects( IntPtr.Zero, fileFlag, out fileEnumPtr) == ShellAPI.S_OK) { fileEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(fileEnumPtr, typeof(IEnumIDList)); ShellAPI.SFGAO attribs = ShellAPI.SFGAO.FOLDER; while(browser.UpdateCondition.ContinueUpdate && fileEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1) { ShellFolder.GetAttributesOf(1, new IntPtr[] {pidlSubItem}, ref attribs); if((attribs & ShellAPI.SFGAO.FOLDER) == 0) { if((index = subFiles.IndexOf(pidlSubItem)) == -1) { ShellItem newItem = new ShellItem(browser, this, pidlSubItem); if(!subFolders.Contains(newItem.Text)) { add.Add(newItem); } } else if(index < fileExists.Length) { fileExists[index] = true; Marshal.FreeCoTaskMem(pidlSubItem); } } else Marshal.FreeCoTaskMem(pidlSubItem); } fileEnumCompleted = true; } } else { if(ShellFolder.EnumObjects( IntPtr.Zero, fileFlag, out fileEnumPtr) == ShellAPI.S_OK) { fileEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(fileEnumPtr, typeof(IEnumIDList)); while(browser.UpdateCondition.ContinueUpdate && fileEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1) { if((index = subFiles.IndexOf(pidlSubItem)) == -1) { add.Add(new ShellItem(browser, this, pidlSubItem)); } else if(index < fileExists.Length) { fileExists[index] = true; Marshal.FreeCoTaskMem(pidlSubItem); } } fileEnumCompleted = true; } } #endregion #region Remove Files for(int i = 0; fileEnumCompleted && browser.UpdateCondition.ContinueUpdate && i < fileExists.Length; i++) { if(!fileExists[i] && subFiles[i] != null) { remove.Add(subFiles[i]); } } #endregion #region Do Events if(fileEnumCompleted && browser.UpdateCondition.ContinueUpdate) { int newIndex; foreach(ShellItem oldItem in remove) { if((newIndex = add.IndexOf(oldItem.Text)) > -1) { ShellItem newItem = add[newIndex]; add.Remove(newItem); oldItem.pidlRel.Free(); oldItem.pidlRel = new PIDL(newItem.pidlRel.Ptr, true); oldItem.shellFolder = newItem.shellFolder; oldItem.shellFolderPtr = newItem.shellFolderPtr; ((IDisposable)newItem).Dispose(); browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(oldItem, oldItem, ShellItemUpdateType.Updated)); } else { subFiles.Remove(oldItem); browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(oldItem, null, ShellItemUpdateType.Deleted)); ((IDisposable)oldItem).Dispose(); } } foreach(ShellItem newItem in add) { subFiles.Add(newItem); browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(null, newItem, ShellItemUpdateType.Created)); } subFiles.Capacity = subFiles.Count; subFiles.Sort(); filesExpanded = true; } #endregion } #endregion #region Update Folders if(browser.UpdateCondition.ContinueUpdate && updateFolders) { ShellItemCollection add = new ShellItemCollection(this); ShellItemCollection remove = new ShellItemCollection(this); bool folderEnumCompleted = false; #region Add Folders if(ShellFolder.EnumObjects( IntPtr.Zero, folderFlag, out folderEnumPtr) == ShellAPI.S_OK) { folderEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(folderEnumPtr, typeof(IEnumIDList)); while(browser.UpdateCondition.ContinueUpdate && folderEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1) { if((index = subFolders.IndexOf(pidlSubItem)) == -1) { IntPtr shellFolderPtr; if(ShellFolder.BindToObject( pidlSubItem, IntPtr.Zero, ref ShellAPI.IID_IShellFolder, out shellFolderPtr) == ShellAPI.S_OK) { add.Add(new ShellItem( browser, this, pidlSubItem, shellFolderPtr)); } } else if(index < folderExists.Length) { folderExists[index] = true; Marshal.FreeCoTaskMem(pidlSubItem); } } folderEnumCompleted = true; } #endregion #region Remove Folders for(int i = 0; folderEnumCompleted && browser.UpdateCondition.ContinueUpdate && i < folderExists.Length; i++) { if(!folderExists[i] && subFolders[i] != null) { remove.Add(subFolders[i]); } } #endregion #region Do Events if(folderEnumCompleted && browser.UpdateCondition.ContinueUpdate) { int newIndex; foreach(ShellItem oldItem in remove) { if((newIndex = add.IndexOf(oldItem.Text)) > -1) { ShellItem newItem = add[newIndex]; add.Remove(newItem); oldItem.pidlRel.Free(); oldItem.pidlRel = new PIDL(newItem.pidlRel, true); Marshal.ReleaseComObject(oldItem.shellFolder); Marshal.Release(oldItem.shellFolderPtr); oldItem.shellFolder = newItem.shellFolder; oldItem.shellFolderPtr = newItem.shellFolderPtr; newItem.shellFolder = null; newItem.shellFolderPtr = IntPtr.Zero; ((IDisposable)newItem).Dispose(); browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(oldItem, oldItem, ShellItemUpdateType.Updated)); } else { subFolders.Remove(oldItem); browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(oldItem, null, ShellItemUpdateType.Deleted)); ((IDisposable)oldItem).Dispose(); } } foreach(ShellItem newItem in add) { subFolders.Add(newItem); browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(null, newItem, ShellItemUpdateType.Created)); } subFolders.Capacity = subFolders.Count; subFolders.Sort(); foldersExpanded = true; } #endregion } #endregion } catch(Exception) { } finally { #region Free if(folderEnum != null) { Marshal.ReleaseComObject(folderEnum); Marshal.Release(folderEnumPtr); } if(fileEnum != null) { Marshal.ReleaseComObject(fileEnum); if(!(type == browser.SystemFolderName && string.Compare(text, "Control Panel", true) == 0)) Marshal.Release(fileEnumPtr); } #endregion } } } }