// Informs Microsoft Windows Explorer to browse to another folder. int NativeMethods.IShellBrowser.BrowseObject(IntPtr pidl, uint wFlags) { int hr; IntPtr folderTmpPtr; NativeMethods.IShellFolder folderTmp; IntPtr pidlTmp; if (NativeMethods.Shell32.ILIsEqual(pidl, m_desktopPidl)) { // pidl is desktop folder pidlTmp = NativeMethods.Shell32.ILClone(m_desktopPidl); folderTmp = m_desktopFolder; } else if ((wFlags & NativeMethods.SBSP_RELATIVE) != 0) { // SBSP_RELATIVE - pidl is relative from the current folder if ((hr = m_currentFolder.BindToObject(pidl, IntPtr.Zero, ref NativeMethods.IID_IShellFolder, out folderTmpPtr)) != NativeMethods.S_OK) return hr; pidlTmp = NativeMethods.Shell32.ILCombine(m_pidlAbsCurrent, pidl); folderTmp = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(folderTmpPtr); } else if ((wFlags & NativeMethods.SBSP_PARENT) != 0) { // SBSP_PARENT - Browse the parent folder (ignores the pidl) pidlTmp = GetParentPidl(m_pidlAbsCurrent); string pathTmp = GetDisplayName(m_desktopFolder, pidlTmp, NativeMethods.SHGNO.SHGDN_FORPARSING); if (pathTmp.Equals(m_desktopPath)) { pidlTmp = NativeMethods.Shell32.ILClone(m_desktopPidl); folderTmp = m_desktopFolder; } else { if ((hr = m_desktopFolder.BindToObject(pidlTmp, IntPtr.Zero, ref NativeMethods.IID_IShellFolder, out folderTmpPtr)) != NativeMethods.S_OK) return hr; folderTmp = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(folderTmpPtr); } } else { // SBSP_ABSOLUTE - pidl is an absolute pidl (relative from desktop) pidlTmp = NativeMethods.Shell32.ILClone(pidl); if ((hr = m_desktopFolder.BindToObject(pidlTmp, IntPtr.Zero, ref NativeMethods.IID_IShellFolder, out folderTmpPtr)) != NativeMethods.S_OK) return hr; folderTmp = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(folderTmpPtr); } if (folderTmp == null) { NativeMethods.Shell32.ILFree(pidlTmp); return NativeMethods.E_FAIL; } string path = GetDisplayName(m_desktopFolder, pidlTmp, NativeMethods.SHGNO.SHGDN_FORPARSING); // FIX: Force the special folder My documents if (path == m_myDocsPath && !NativeMethods.Shell32.ILIsEqual(pidlTmp, m_myDocsPidl)) { NativeMethods.Shell32.ILFree(pidlTmp); pidlTmp = NativeMethods.Shell32.ILClone(m_myDocsPidl); } // If the path root is a drive make sure it's available string driveName; if (PathUtils.PathRootIsDrive(path, out driveName)) { DriveInfo di = new DriveInfo(driveName); if (di.DriveType == DriveType.CDRom) { // The drive is an optical disk drive string message = "The selected disk drive is not in use. Check to make sure a disk is inserted."; while (!di.IsReady) { // Loop until a disk is inserted or cancel is clicked if (MessageBoxWithFocusRestore(message, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) == DialogResult.Cancel) return NativeMethods.S_OK; } } else if (di.DriveType == DriveType.NoRootDirectory) { // The drive does not have a root directory, e.g. an unconnected network drive string message = string.Format("The drive '{0}' is not valid. Enter a valid drive letter.", driveName.Substring(0, 2)); MessageBoxWithFocusRestore(message, MessageBoxButtons.OK, MessageBoxIcon.Information); return NativeMethods.S_OK; } } m_currentFolder = folderTmp; NativeMethods.FOLDERSETTINGS fs = new NativeMethods.FOLDERSETTINGS(); NativeMethods.IShellView lastIShellView = m_shellView; if (lastIShellView != null) lastIShellView.GetCurrentInfo(ref fs); // Copy the old folder settings else { fs = new NativeMethods.FOLDERSETTINGS(); fs.fFlags = (uint)m_flags; fs.ViewMode = (uint)m_viewMode; } // Create the IShellView IntPtr iShellViewPtr; hr = folderTmp.CreateViewObject(Handle, ref NativeMethods.IID_IShellView, out iShellViewPtr); if (hr == NativeMethods.S_OK) { m_shellView = (NativeMethods.IShellView)Marshal.GetObjectForIUnknown(iShellViewPtr); m_hWndListView = IntPtr.Zero; NativeMethods.RECT rc = new NativeMethods.RECT(FileViewPadding.Left, FileViewPadding.Top, ClientSize.Width - FileViewPadding.Right, ClientSize.Height - FileViewPadding.Bottom); int res; try { // Create the list view res = m_shellView.CreateViewWindow(lastIShellView, ref fs, this, ref rc, ref m_hWndListView); } catch (COMException) { return NativeMethods.E_FAIL; } if (res < 0) return NativeMethods.E_FAIL; bool shellViewHasFocus = m_shellViewHasFocus; // Release the old IShellView if (lastIShellView != null) { lastIShellView.GetCurrentInfo(ref fs); lastIShellView.UIActivate((uint)NativeMethods.SVUIA_STATUS.SVUIA_DEACTIVATE); lastIShellView.DestroyViewWindow(); Marshal.ReleaseComObject(lastIShellView); } // Give the new IShellView focus if the old one had focus m_shellView.UIActivate(shellViewHasFocus ? (uint)NativeMethods.SVUIA_STATUS.SVUIA_ACTIVATE_FOCUS : (uint)NativeMethods.SVUIA_STATUS.SVUIA_ACTIVATE_NOFOCUS); IntPtr previousPidl = m_pidlAbsCurrent; m_pidlAbsCurrent = pidlTmp; UpdateUI(previousPidl); // Clear the selection m_selectedPidls = null; OnSelectionChanged(); } return NativeMethods.S_OK; }
protected override void OnHandleDestroyed(EventArgs e) { m_pidlAbsCurrent = IntPtr.Zero; m_selectedPidls = null; // Release the IShellView if (m_shellView != null) { if (m_restoreLastViewMode) { // Saves the view mode if the RestoreLastViewMode property is set to true NativeMethods.FOLDERSETTINGS fs = new NativeMethods.FOLDERSETTINGS(); m_shellView.GetCurrentInfo(ref fs); m_viewMode = (FileDialogViewMode)fs.ViewMode; } m_shellView.UIActivate((uint)NativeMethods.SVUIA_STATUS.SVUIA_DEACTIVATE); m_shellView.DestroyViewWindow(); Marshal.ReleaseComObject(m_shellView); m_shellView = null; } m_backItemsOverflow.Clear(); backToolStripSplitButton.DropDownItems.Clear(); backToolStripSplitButton.Enabled = false; base.OnHandleDestroyed(e); }