internal ShellItem(ShellBrowser browser, ShellAPI.CSIDL specialFolder) { IntPtr pidl = IntPtr.Zero; ShellAPI.SHGetSpecialFolderLocation(IntPtr.Zero, specialFolder, out pidl); // IntPtr shellFolderPtr; this.browser = browser; // if (specialFolder == ShellAPI.CSIDL.DESKTOP) { ShellAPI.SHGetDesktopFolder(out shellFolderPtr); // this.shellFolderPtr = shellFolderPtr; this.shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(shellFolderPtr, typeof(IShellFolder)); } else { this.shellFolder = GetShellFolderFromPidl(pidl, out shellFolderPtr); // this.parentItem = browser.DesktopItem; } // subFiles = new ShellItemCollection(this); subFolders = new ShellItemCollection(this); pidlRel = new PIDL(pidl, false); ShellAPI.SHFILEINFO info = new ShellAPI.SHFILEINFO(); ShellAPI.SHGetFileInfo(pidlRel.Ptr, 0, ref info, ShellAPI.cbFileInfo, ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.TYPENAME | ShellAPI.SHGFI.SYSICONINDEX | ShellAPI.SHGFI.DISPLAYNAME); type = info.szTypeName; text = info.szDisplayName; // StringBuilder pathBuilder = new StringBuilder(ShellAPI.MAX_PATH); ShellAPI.SHGetFolderPath( IntPtr.Zero, specialFolder, IntPtr.Zero, ShellAPI.SHGFP.TYPE_CURRENT, pathBuilder); this.path = pathBuilder.ToString(); // if (specialFolder == ShellAPI.CSIDL.DESKTOP) { ShellImageList.SetIconIndex(this, info.iIcon, false); ShellImageList.SetIconIndex(this, info.iIcon, true); // SetAttributesDesktop(this); } else { SetAttributesFolder(this); SetInfo(this); } 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 } } } }