PageRenderTime 73ms CodeModel.GetById 5ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 1ms

/verve patch/base/Applications/BetterExplorer/BExplorer/BetterExplorer/MainWindow.xaml.cs

https://bitbucket.org/jdm7dvmoore/msft-research-verve
C# | 4158 lines | 3239 code | 628 blank | 291 comment | 747 complexity | 4806bfa8d44f4dae5cca83557fa289ee MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1// --------------------------------------------------------------------------------------------------------------------
   2// <copyright file="MainWindow.xaml.cs" company="Gainedge ORG">
   3//   Better Explorer (c)2016
   4// </copyright>
   5// <summary>
   6//   Interaction logic for MainWindow.xaml
   7// </summary>
   8// --------------------------------------------------------------------------------------------------------------------
   9
  10using System;
  11using System.Collections.Generic;
  12using System.Collections.Specialized;
  13using System.ComponentModel;
  14using System.Diagnostics;
  15using System.Drawing;
  16using System.Drawing.Imaging;
  17using System.IO;
  18using System.Linq;
  19using System.Net;
  20using System.Reflection;
  21using System.Runtime.InteropServices;
  22using System.ServiceModel;
  23using System.Text;
  24using System.Threading;
  25using System.Threading.Tasks;
  26using System.Windows;
  27using System.Windows.Controls;
  28using System.Windows.Controls.Primitives;
  29using System.Windows.Input;
  30using System.Windows.Interop;
  31using System.Windows.Media;
  32using System.Windows.Media.Imaging;
  33using System.Windows.Shell;
  34using System.Windows.Threading;
  35using System.Xml;
  36using System.Xml.Linq;
  37using BEHelper;
  38using BetterExplorer.UsbEject;
  39using BetterExplorerControls;
  40using BExplorer.Shell;
  41using BExplorer.Shell._Plugin_Interfaces;
  42using BExplorer.Shell.CommonFileDialogs;
  43using BExplorer.Shell.DropTargetHelper;
  44using BExplorer.Shell.Interop;
  45using Fluent;
  46using LTR.IO.ImDisk;
  47using Microsoft.Win32;
  48using Settings;
  49using SevenZip;
  50using Shell32;
  51using TaskDialogInterop;
  52using wyDay.Controls;
  53
  54using Clipboards = System.Windows.Forms.Clipboard;
  55using ContextMenu = Fluent.ContextMenu;
  56using Image = System.Windows.Controls.Image;
  57using MenuItem = Fluent.MenuItem;
  58using WIN = System.Windows;
  59
  60namespace BetterExplorer {
  61
  62  /// <summary>
  63  /// Interaction logic for MainWindow.xaml
  64  /// </summary>
  65  public partial class MainWindow : Fluent.RibbonWindow {
  66
  67    #region DLLImports
  68
  69    [DllImport("user32.dll")]
  70    [return: MarshalAs(UnmanagedType.Bool)]
  71    internal static extern bool GetCursorPos(ref BExplorer.Shell.DataObject.Win32Point pt);
  72
  73    //[DllImport("user32.dll", SetLastError = true)]
  74    //private static extern int RegisterHotKey(IntPtr hwnd, int id, int fsModifiers, int vk);
  75
  76    //[DllImport("user32.dll", SetLastError = true)]
  77    //private static extern int UnregisterHotKey(IntPtr hwnd, int id);
  78
  79    [DllImport("winmm.dll")]
  80    static extern Int32 mciSendString(String command, StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);
  81
  82    #endregion
  83
  84    #region Private Members
  85    private bool _IsCalledFromLoading, isOnLoad;
  86    private MenuItem misa, misd, misag, misdg;
  87    private ShellTreeViewEx ShellTree = new ShellTreeViewEx();
  88    private ShellView _ShellListView = new ShellView();
  89    private bool IsNeedEnsureVisible;
  90    private ClipboardMonitor cbm = new ClipboardMonitor();
  91    private ContextMenu _CMHistory = new ContextMenu();
  92    private WIN.Shell.JumpList AppJL = new WIN.Shell.JumpList();
  93    //private List<string> Archives = new List<string>(new[] { ".rar", ".zip", ".7z", ".tar", ".gz", ".xz", ".bz2" });
  94    private List<string> Images = new List<string>(new[] { ".jpg", ".jpeg", ".png", ".bmp", ".gif", ".wmf" });
  95    private string SelectedArchive = "";
  96    private bool KeepBackstageOpen = false;
  97    string sessionid = DateTime.UtcNow.ToFileTimeUtc().ToString();
  98    string logdir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\BExplorer\\ActionLog\\";
  99    WIN.Forms.Timer updateCheckTimer = new WIN.Forms.Timer();
 100    Double CommandPromptWinHeight;
 101
 102    //List<LVItemColor> LVItemsColor { get; set; }
 103    ContextMenu chcm;
 104
 105    WIN.Forms.Timer focusTimer = new WIN.Forms.Timer() { Interval = 500 };
 106    private WIN.Forms.Timer _ProgressTimer = new WIN.Forms.Timer() { Interval = 1000, Enabled = false };
 107    private string _DBPath = Path.Combine(KnownFolders.RoamingAppData.ParsingName, @"BExplorer\Settings.sqlite");
 108
 109    private IntPtr Handle;
 110    private ObservableCollectionEx<LVItemColor> LVItemsColorCol { get; set; }
 111    public Dictionary<String, Dictionary<IListItemEx, List<string>>> Badges { get; set; }
 112    #endregion
 113
 114    public bool IsMultipleWindowsOpened { get; set; }
 115
 116    #region Events
 117
 118    private void btnAbout_Click(object sender, RoutedEventArgs e) => new fmAbout(this).ShowDialog();
 119    private void btnBugtracker_Click(object sender, RoutedEventArgs e) => Process.Start("http://bugs.gainedge.org/public/betterexplorer");
 120    private void TheRibbon_CustomizeQuickAccessToolbar(object sender, EventArgs e) => CustomizeQAT.Open(this, TheRibbon);
 121
 122    private void btnConsolePane_Click(object sender, RoutedEventArgs e) {
 123      Settings.BESettings.IsConsoleShown = btnConsolePane.IsChecked.Value;
 124      Settings.BESettings.SaveSettings();
 125      if (btnConsolePane.IsChecked.Value) {
 126        rCommandPrompt.Height = new GridLength(this.CommandPromptWinHeight);
 127        rCommandPrompt.MinHeight = 100;
 128        spCommandPrompt.Height = GridLength.Auto;
 129        if (!ctrlConsole.IsProcessRunning)
 130          ctrlConsole.ChangeFolder(_ShellListView.CurrentFolder.ParsingName, _ShellListView.CurrentFolder.IsFileSystem);
 131      } else {
 132        rCommandPrompt.MinHeight = 0;
 133        rCommandPrompt.Height = new GridLength(0);
 134        spCommandPrompt.Height = new GridLength(0);
 135        ctrlConsole.StopProcess();
 136      }
 137    }
 138    private void backstage_IsOpenChanged(object sender, DependencyPropertyChangedEventArgs e) {
 139      if ((Boolean)e.NewValue) {
 140        this._ShellListView.IsFocusAllowed = false;
 141        this.backstage.Focus();
 142      } else {
 143        this._ShellListView.IsFocusAllowed = true;
 144      }
 145      this.autoUpdater.Visibility = Visibility.Visible;
 146      this.autoUpdater.UpdateLayout();
 147
 148      if (this.KeepBackstageOpen) {
 149        this.backstage.IsOpen = true;
 150        this.KeepBackstageOpen = false;
 151      }
 152    }
 153
 154    /// <summary>
 155    /// Loads initial position of the main window
 156    /// </summary>
 157    private void LoadInitialWindowPositionAndState() {
 158      this.Width = BESettings.LastWindowWidth;
 159      this.Height = BESettings.LastWindowHeight;
 160
 161      var location = new System.Drawing.Point();
 162      try {
 163        location = new System.Drawing.Point((int)BESettings.LastWindowPosLeft, (int)BESettings.LastWindowPosTop);
 164      } catch { }
 165
 166      this.Left = location.X;
 167      this.Top = location.Y;
 168
 169      switch (BESettings.LastWindowState) {
 170        case 2:
 171          this.WindowState = WindowState.Maximized;
 172          break;
 173        case 1:
 174          this.WindowState = WindowState.Minimized;
 175          break;
 176        case 0:
 177          this.WindowState = WindowState.Normal;
 178          break;
 179        default:
 180          this.WindowState = WindowState.Maximized;
 181          break;
 182      }
 183
 184      this.chkRibbonMinimizedGlass.IsChecked = BESettings.IsGlassOnRibonMinimized;
 185      this.TheRibbon.IsMinimized = BESettings.IsRibonMinimized;
 186
 187      //CommandPrompt window size
 188      this.CommandPromptWinHeight = BESettings.CmdWinHeight;
 189      this.rCommandPrompt.Height = new GridLength(this.CommandPromptWinHeight);
 190
 191      if (BESettings.IsConsoleShown) {
 192        this.rCommandPrompt.MinHeight = 100;
 193        this.rCommandPrompt.Height = new GridLength(this.CommandPromptWinHeight);
 194        this.spCommandPrompt.Height = GridLength.Auto;
 195      } else {
 196        this.rCommandPrompt.MinHeight = 0;
 197        this.rCommandPrompt.Height = new GridLength(0);
 198        this.spCommandPrompt.Height = new GridLength(0);
 199      }
 200    }
 201
 202    private void LoadColorCodesFromFile() {
 203      Task.Run(() => {
 204        var itemColorSettingsLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"BExplorer\itemcolors.cfg");
 205
 206        if (File.Exists(itemColorSettingsLocation)) {
 207          var docs = XDocument.Load(itemColorSettingsLocation);
 208
 209          docs.Root.Elements("ItemColorRow")
 210            .Select(
 211              element =>
 212                new LVItemColor(
 213                  element.Elements().ToArray()[0].Value,
 214                  WIN.Media.Color.FromArgb(
 215                    BitConverter.GetBytes(Convert.ToInt32(element.Elements().ToArray()[1].Value))[0],
 216                    BitConverter.GetBytes(Convert.ToInt32(element.Elements().ToArray()[1].Value))[1],
 217                    BitConverter.GetBytes(Convert.ToInt32(element.Elements().ToArray()[1].Value))[2],
 218                    BitConverter.GetBytes(Convert.ToInt32(element.Elements().ToArray()[1].Value))[3])))
 219            .ToList().ForEach(e => this.LVItemsColorCol.Add(e));
 220
 221        }
 222      });
 223    }
 224
 225    private void RibbonWindow_Initialized(object sender, EventArgs e) {
 226      this.LoadInitialWindowPositionAndState();
 227      this.LoadColorCodesFromFile();
 228
 229      AppCommands.RoutedNewTab.InputGestures.Add(new KeyGesture(Key.T, ModifierKeys.Control));
 230      AppCommands.RoutedEnterInBreadCrumbCombo.InputGestures.Add(new KeyGesture(Key.E, ModifierKeys.Alt));
 231      AppCommands.RoutedChangeTab.InputGestures.Add(new KeyGesture(Key.Tab, ModifierKeys.Control));
 232      AppCommands.RoutedCloseTab.InputGestures.Add(new KeyGesture(Key.W, ModifierKeys.Control));
 233      AppCommands.RoutedNavigateBack.InputGestures.Add(new KeyGesture(Key.Left, ModifierKeys.Alt));
 234      AppCommands.RoutedNavigateFF.InputGestures.Add(new KeyGesture(Key.Right, ModifierKeys.Alt));
 235      AppCommands.RoutedNavigateUp.InputGestures.Add(new KeyGesture(Key.Up, ModifierKeys.Alt));
 236      AppCommands.RoutedGotoSearch.InputGestures.Add(new KeyGesture(Key.F, ModifierKeys.Control));
 237    }
 238
 239    #region ViewEnumerationComplete
 240
 241    /// <summary>
 242    /// Sets up btnSort and btnGroup so they have the correct items after navigating 
 243    /// </summary>
 244    private void SetSortingAndGroupingButtons() {
 245      btnSort.Items.Clear();
 246      btnGroup.Items.Clear();
 247
 248      try {
 249        foreach (Collumns item in _ShellListView.Collumns.Where(x => x != null)) {
 250          var lastSortedColumn = _ShellListView.Collumns.FirstOrDefault(w => w.ID == this._ShellListView.LastSortedColumnId);
 251          if (lastSortedColumn != null) {
 252            var IsChecked1 = (item.pkey.fmtid == lastSortedColumn.pkey.fmtid) && (item.pkey.pid == lastSortedColumn.pkey.pid);
 253            btnSort.Items.Add(Utilities.Build_MenuItem(item.Name, item, checkable: true, isChecked: IsChecked1, GroupName: "GR2", onClick: mi_Click));
 254          }
 255          var IsCheckable2 = _ShellListView.LastGroupCollumn != null && (item.pkey.fmtid == _ShellListView.LastGroupCollumn.pkey.fmtid) && (item.pkey.pid == _ShellListView.LastGroupCollumn.pkey.pid);
 256          btnGroup.Items.Add(Utilities.Build_MenuItem(item.Name, item, checkable: true, isChecked: IsCheckable2, GroupName: "GR3", onClick: mig_Click));
 257        }
 258      } catch (Exception ex) {
 259        //FIXME: I disable this message because of strange null after filter
 260        MessageBox.Show("BetterExplorer had an issue loading the visible columns for the current view. You might not be able to sort or group items.", ex.ToString(), MessageBoxButton.OK, MessageBoxImage.Error);
 261      }
 262
 263      btnSort.Items.Add(new Separator() { Focusable = false });
 264      misa = Utilities.Build_MenuItem(FindResource("miAscending"), checkable: true, GroupName: "GR1", onClick: misa_Click);
 265      misd = Utilities.Build_MenuItem(FindResource("miDescending"), checkable: true, GroupName: "GR1", onClick: misd_Click);
 266
 267      if (this._ShellListView.LastSortOrder == WIN.Forms.SortOrder.Ascending)
 268        misa.IsChecked = true;
 269      else
 270        misd.IsChecked = true;
 271
 272      btnSort.Items.Add(misa);
 273      btnSort.Items.Add(misd);
 274
 275      btnGroup.Items.Add(Utilities.Build_MenuItem("(none)", GroupName: "GR3", checkable: true, isChecked: _ShellListView.LastGroupCollumn == null, onClick: misng_Click));
 276      btnGroup.Items.Add(new Separator());
 277
 278      misag = Utilities.Build_MenuItem(FindResource("miAscending"), checkable: true, GroupName: "GR4", onClick: misag_Click);
 279      misdg = Utilities.Build_MenuItem(FindResource("miDescending"), checkable: true, GroupName: "GR4", onClick: misag_Click);
 280
 281      if (this._ShellListView.LastGroupOrder == WIN.Forms.SortOrder.Ascending)
 282        misag.IsChecked = true;
 283      else
 284        misdg.IsChecked = true;
 285
 286      btnGroup.Items.Add(misag);
 287      btnGroup.Items.Add(misdg);
 288    }
 289
 290    void misag_Click(object sender, RoutedEventArgs e) {
 291      this._ShellListView.SetGroupOrder();
 292    }
 293
 294    private void SetupColumnsButton() {
 295      var allAvailColls = this._ShellListView.AllAvailableColumns.Values.ToList();
 296      btnMoreColls.Items.Clear();
 297      chcm.Items.Clear();
 298
 299      for (int j = 1; j < 10; j++) {
 300        //TODO: Try to remove this Try Catch!!
 301        try {
 302          var IsChecked = _ShellListView.Collumns.Any(col => col.pkey.fmtid == allAvailColls[j].pkey.fmtid && col.pkey.pid == allAvailColls[j].pkey.pid);
 303          btnMoreColls.Items.Add(Utilities.Build_MenuItem(allAvailColls[j].Name, allAvailColls[j], checkable: true, onClick: mic_Click, isChecked: IsChecked));
 304          chcm.Items.Add(Utilities.Build_MenuItem(allAvailColls[j].Name, allAvailColls[j], checkable: true, onClick: mic_Click, isChecked: IsChecked));
 305        } catch (Exception) {
 306        }
 307      }
 308
 309      int ItemsCount = _ShellListView.Items.Count;
 310      sbiItemsCount.Visibility = ItemsCount == 0 ? Visibility.Collapsed : Visibility.Visible;
 311      sbiItemsCount.Content = ItemsCount == 1 ? "1 item" : ItemsCount + " items";
 312      sbiSelItemsCount.Visibility = _ShellListView.GetSelectedCount() == 0 ? Visibility.Collapsed : Visibility.Visible;
 313      spSelItems.Visibility = sbiSelItemsCount.Visibility;
 314
 315      btnMoreColls.Items.Add(new Separator());
 316      btnMoreColls.Items.Add(Utilities.Build_MenuItem(FindResource("btnMoreColCP"), allAvailColls, onClick: micm_Click));
 317      btnMoreColls.Tag = allAvailColls;
 318
 319      chcm.Items.Add(new Separator());
 320      chcm.Items.Add(Utilities.Build_MenuItem(FindResource("btnMoreColCP"), allAvailColls, onClick: micm_Click));
 321    }
 322
 323    #endregion
 324
 325    void misd_Click(object sender, RoutedEventArgs e) {
 326      foreach (var item in btnSort.Items.OfType<MenuItem>().Where(item => item.IsChecked && item != (sender as MenuItem))) {
 327        _ShellListView.SetSortCollumn(true, (Collumns)item.Tag, WIN.Forms.SortOrder.Descending);
 328      }
 329    }
 330
 331    void misa_Click(object sender, RoutedEventArgs e) {
 332      foreach (var item in btnSort.Items.OfType<MenuItem>().Where(item => item.IsChecked && item != (sender as MenuItem))) {
 333        _ShellListView.SetSortCollumn(true, (Collumns)item.Tag, WIN.Forms.SortOrder.Ascending);
 334      }
 335    }
 336
 337    void micm_Click(object sender, RoutedEventArgs e) {
 338      var fMoreCollumns = new MoreColumns();
 339      fMoreCollumns.PopulateAvailableColumns((List<Collumns>)(sender as FrameworkElement).Tag, this._ShellListView, this.PointToScreen(Mouse.GetPosition(this)));
 340    }
 341
 342    void mic_Click(object sender, RoutedEventArgs e) {
 343      var mi = (sender as MenuItem);
 344      Collumns col = (Collumns)mi.Tag;
 345      _ShellListView.SetColInView(col, !mi.IsChecked);
 346    }
 347
 348    void miItem_Click(object sender, RoutedEventArgs e) {
 349      MenuItem mi = sender as MenuItem;
 350      ShellItem SaveLoc = mi.Tag as ShellItem;
 351
 352      if (_ShellListView.CurrentFolder.ParsingName.Contains(KnownFolders.Libraries.ParsingName) && _ShellListView.CurrentFolder.ParsingName.EndsWith("library-ms")) {
 353        var lib = ShellLibrary.Load(Path.GetFileNameWithoutExtension(_ShellListView.CurrentFolder.ParsingName), false);
 354        lib.DefaultSaveFolder = SaveLoc.ParsingName;
 355        lib.Close();
 356      } else if (_ShellListView.GetFirstSelectedItem().ParsingName.Contains(KnownFolders.Libraries.ParsingName)) {
 357        var lib = ShellLibrary.Load(Path.GetFileNameWithoutExtension(_ShellListView.GetFirstSelectedItem().ParsingName), false);
 358        lib.DefaultSaveFolder = SaveLoc.ParsingName;
 359        lib.Close();
 360      }
 361    }
 362
 363    void LinksFolderWarcher_Renamed(object sender, RenamedEventArgs e) {
 364      Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(
 365          () => btnFavorites.Items.OfType<MenuItem>().First(x => (x.Tag as ShellItem).ParsingName == e.OldFullPath).Header = Path.GetFileNameWithoutExtension(e.Name)));
 366    }
 367
 368    void LinksFolderWarcher_Deleted(object sender, FileSystemEventArgs e) {
 369      Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(
 370          () => btnFavorites.Items.Remove(btnFavorites.Items.OfType<MenuItem>().First(item => item.Header.ToString() == Path.GetFileNameWithoutExtension(e.Name)))));
 371    }
 372
 373    void LinksFolderWarcher_Created(object sender, FileSystemEventArgs e) {
 374      Dispatcher.BeginInvoke(DispatcherPriority.Normal,
 375                      (Action)(() => {
 376                        if (Path.GetExtension(e.FullPath).ToLowerInvariant() == ".lnk") {
 377                          var so = new ShellItem(e.FullPath);
 378                          so.Thumbnail.FormatOption = ShellThumbnailFormatOption.IconOnly;
 379                          so.Thumbnail.CurrentSize = new WIN.Size(16, 16);
 380                          ImageSource icon = so.Thumbnail.BitmapSource;
 381
 382                          btnFavorites.Items.Add(Utilities.Build_MenuItem(so.DisplayName, so, icon, onClick: mif_Click));
 383                        }
 384                      }));
 385    }
 386
 387    /// <summary>
 388    /// Sets up each ribbon tab after select or navigate in ShellListView
 389    /// </summary>
 390    /// <param name="selectedItemsCount">The number of items selected</param>
 391    /// <param name="selectedItem">The last selected item</param>
 392    /// <remarks>
 393    /// Only used in SetupUIOnSelectOrNavigate
 394    /// </remarks>
 395    private void SetUpRibbonTabsVisibilityOnSelectOrNavigate(int selectedItemsCount, IListItemEx selectedItem) {
 396      #region Search Contextual Tab
 397      ctgSearch.Visibility = BooleanToVisibiliy(_ShellListView.CurrentFolder.IsSearchFolder);
 398      if (ctgSearch.Visibility == Visibility.Visible && !_ShellListView.CurrentFolder.IsSearchFolder) {
 399        ctgSearch.Visibility = Visibility.Collapsed;
 400        TheRibbon.SelectedTabItem = HomeTab;
 401      }
 402      #endregion
 403
 404      #region Folder Tools Context Tab
 405      ctgFolderTools.Visibility = BooleanToVisibiliy((selectedItemsCount == 1 && selectedItem.IsFolder && selectedItem.IsFileSystem && !selectedItem.IsDrive && !selectedItem.IsNetworkPath));
 406
 407      if (BESettings.AutoSwitchFolderTools && ctgFolderTools.Visibility == Visibility.Visible) {
 408        TheRibbon.SelectedTabItem = ctgFolderTools.Items[0];
 409      }
 410      #endregion
 411
 412      #region Drive Contextual Tab
 413      ctgDrive.Visibility = BooleanToVisibiliy(_ShellListView.CurrentFolder.IsDrive || (selectedItemsCount == 1 && (selectedItem.IsDrive || (selectedItem.Parent != null && selectedItem.Parent.IsDrive))));
 414      if (BESettings.AutoSwitchDriveTools && ctgDrive.Visibility == Visibility.Visible && selectedItemsCount == 1 && selectedItem.IsDrive) {
 415        TheRibbon.SelectedTabItem = ctgDrive.Items[0];
 416      }
 417      #endregion
 418
 419      #region Library Context Tab
 420      ctgLibraries.Visibility = BooleanToVisibiliy((selectedItemsCount == 1 && _ShellListView.CurrentFolder.ParsingName.Equals(KnownFolders.Libraries.ParsingName)) || (selectedItemsCount == 1 && selectedItem.Parent != null && selectedItem.Parent.ParsingName.Equals(KnownFolders.Libraries.ParsingName)));
 421
 422      if (ctgLibraries.Visibility == Visibility.Visible && BESettings.AutoSwitchLibraryTools) {
 423        TheRibbon.SelectedTabItem = ctgLibraries.Items[0];
 424      }
 425
 426      /*
 427        if (ctgLibraries.Visibility == Visibility.Visible && _ShellListView.CurrentFolder.ParsingName.Equals(KnownFolders.Libraries.ParsingName)) {
 428          if (selectedItem != null && selectedItemsCount == 1)
 429            SetupLibrariesTab(ShellLibrary.Load(Path.GetFileNameWithoutExtension(selectedItem.ParsingName), false));
 430        } else if (ctgLibraries.Visibility == Visibility.Visible && _ShellListView.CurrentFolder.Parent.ParsingName.Equals(KnownFolders.Libraries.ParsingName)) {
 431          if (selectedItemsCount == 1)
 432            SetupLibrariesTab(ShellLibrary.Load(Path.GetFileNameWithoutExtension(_ShellListView.CurrentFolder.ParsingName), false));
 433        }
 434        if (selectedItemsCount == 0) {
 435          ctgLibraries.Visibility = Visibility.Collapsed;
 436        }
 437      */
 438      if (selectedItemsCount == 0)
 439        ctgLibraries.Visibility = Visibility.Collapsed;
 440      else if (selectedItemsCount > 1) { } else if (ctgLibraries.Visibility == Visibility.Visible && _ShellListView.CurrentFolder.ParsingName.Equals(KnownFolders.Libraries.ParsingName))
 441        SetupLibrariesTab(ShellLibrary.Load(Path.GetFileNameWithoutExtension(selectedItem.ParsingName), false));
 442      else if (ctgLibraries.Visibility == Visibility.Visible && _ShellListView.CurrentFolder.Parent.ParsingName.Equals(KnownFolders.Libraries.ParsingName))
 443        SetupLibrariesTab(ShellLibrary.Load(Path.GetFileNameWithoutExtension(_ShellListView.CurrentFolder.ParsingName), false));
 444
 445      #endregion
 446
 447      #region Archive Contextual Tab
 448      ctgArchive.Visibility = WIN.Visibility.Collapsed; //TODO: Restore this: BooleanToVisibiliy(selectedItemsCount == 1 && Archives.Contains(Path.GetExtension(selectedItem.ParsingName).ToLowerInvariant()));
 449      if (BESettings.AutoSwitchArchiveTools && ctgArchive.Visibility == Visibility.Visible)
 450        TheRibbon.SelectedTabItem = ctgArchive.Items[0];
 451
 452      #endregion
 453
 454      #region Application Context Tab
 455      ctgExe.Visibility = BooleanToVisibiliy(selectedItemsCount == 1 && !selectedItem.IsFolder && (Path.GetExtension(selectedItem.ParsingName).ToLowerInvariant() == ".exe" || Path.GetExtension(selectedItem.ParsingName).ToLowerInvariant() == ".msi"));
 456      if (BESettings.AutoSwitchApplicationTools && ctgExe.Visibility == Visibility.Visible) {
 457        TheRibbon.SelectedTabItem = ctgExe.Items[0];
 458      }
 459      #endregion
 460
 461      #region Image Context Tab
 462      ctgImage.Visibility = BooleanToVisibiliy(selectedItemsCount == 1 && !selectedItem.IsFolder && Images.Contains(Path.GetExtension(selectedItem.ParsingName).ToLowerInvariant()));
 463      if (ctgImage.Visibility == Visibility.Visible) {
 464        try {
 465          if (new FileInfo(selectedItem.ParsingName).Length != 0) {
 466            using (var cvt = new Bitmap(selectedItem.ParsingName)) {
 467              imgSizeDisplay.WidthData = cvt.Width.ToString();
 468              imgSizeDisplay.HeightData = cvt.Height.ToString();
 469
 470              if (BESettings.AutoSwitchImageTools) TheRibbon.SelectedTabItem = ctgImage.Items[0];
 471            }
 472          }
 473        } catch (Exception) {
 474          MessageBox.Show("Image was invalid");
 475        }
 476      }
 477      #endregion
 478
 479      #region Virtual Disk Context Tab
 480      ctgVirtualDisk.Visibility = BooleanToVisibiliy(selectedItemsCount == 1 && !selectedItem.IsFolder && Path.GetExtension(selectedItem.ParsingName).ToLowerInvariant() == ".iso");
 481      if (BESettings.AutoSwitchVirtualDriveTools && ctgVirtualDisk.Visibility == Visibility.Visible) {
 482        TheRibbon.SelectedTabItem = ctgVirtualDisk.Items[0];
 483      }
 484      #endregion
 485
 486    }
 487
 488    /// <summary>
 489    /// Sets up the status bar
 490    /// </summary>
 491    /// <param name="selectedItemsCount">The number of items currently selected</param>
 492    private void SetUpStatusBarOnSelectOrNavigate(int selectedItemsCount) {
 493      spSelItems.Visibility = BooleanToVisibiliy(selectedItemsCount > 0);
 494      sbiSelItemsCount.Visibility = BooleanToVisibiliy(selectedItemsCount > 0);
 495      if (selectedItemsCount == 1)
 496        sbiSelItemsCount.Content = "1 item selected";
 497      else if (selectedItemsCount > 1)
 498        sbiSelItemsCount.Content = selectedItemsCount.ToString() + " items selected";
 499    }
 500
 501    private void SetUpButtonsStateOnSelectOrNavigate(int selectedItemsCount, IListItemEx selectedItem) {
 502      btnBadges.IsEnabled = selectedItemsCount > 0;
 503      btnCopy.IsEnabled = selectedItemsCount > 0;
 504      btnCopyto.IsEnabled = selectedItemsCount > 0;
 505      btnMoveto.IsEnabled = selectedItemsCount > 0;
 506      btnCut.IsEnabled = selectedItemsCount > 0;
 507      btnDelete.IsEnabled = selectedItem != null && selectedItem.IsFileSystem;
 508      btnRename.IsEnabled = selectedItem != null && (selectedItem.IsFileSystem || (selectedItem.Parent != null && selectedItem.Parent.Equals(KnownFolders.Libraries)));
 509      btnProperties3.IsEnabled = selectedItemsCount > 0;
 510      if (selectedItem != null) {
 511        var rg = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" + Path.GetExtension(selectedItem.ParsingName) + @"\OpenWithProgids");
 512        if (rg == null)
 513          btnEdit.IsEnabled = false;
 514        else {
 515          string filetype = rg.GetValueNames()[0];
 516          rg.Close();
 517
 518          using (var rgtype = Registry.ClassesRoot.OpenSubKey(filetype + @"\shell\edit\command")) {
 519            btnEdit.IsEnabled = !(rgtype == null);
 520          }
 521        }
 522      }
 523
 524      btnSelAll.IsEnabled = selectedItemsCount != _ShellListView.Items.Count;
 525      btnSelNone.IsEnabled = selectedItemsCount > 0;
 526      btnShare.IsEnabled = selectedItemsCount == 1 && selectedItem.IsFolder;
 527      btnAdvancedSecurity.IsEnabled = selectedItemsCount == 1;
 528      btnHideSelItems.IsEnabled = _ShellListView.CurrentFolder.IsFileSystem;
 529    }
 530
 531    private void SetupLibrariesTab(ShellLibrary lib) {
 532      IsFromSelectionOrNavigation = true;
 533      chkPinNav.IsChecked = lib.IsPinnedToNavigationPane;
 534      IsFromSelectionOrNavigation = false;
 535
 536      foreach (ShellItem item in lib) {
 537        item.Thumbnail.FormatOption = ShellThumbnailFormatOption.IconOnly;
 538        item.Thumbnail.CurrentSize = new WIN.Size(16, 16);
 539
 540        btnDefSave.Items.Add(Utilities.Build_MenuItem(item.GetDisplayName(SIGDN.NORMALDISPLAY), item, item.Thumbnail.BitmapSource, GroupName: "GRDS1", checkable: true,
 541                                                      isChecked: item.ParsingName == lib.DefaultSaveFolder, onClick: miItem_Click));
 542      }
 543
 544      btnDefSave.IsEnabled = lib.Count != 0;
 545      lib.Close();
 546    }
 547
 548    /// <summary>
 549    /// Does setup required for the UI when navigation occurs to a new folder
 550    /// </summary>
 551    private void SetupUIOnSelectOrNavigate() {
 552      Dispatcher.BeginInvoke(DispatcherPriority.Background, (ThreadStart)(() => {
 553        btnDefSave.Items.Clear();
 554        var selItemsCount = _ShellListView.GetSelectedCount();
 555        var selectedItem = this._ShellListView.GetFirstSelectedItem();
 556
 557        if (selectedItem == null) {
 558          btnOpenWith.IsEnabled = false;
 559        } else {
 560          var mnu = new ShellContextMenu(this._ShellListView, false);
 561
 562          try {
 563            var tempPoint = btnOpenWith.PointToScreen(new WIN.Point(0, 0));
 564            var itemMenuCount = mnu.ShowContextMenu(new System.Drawing.Point((int)tempPoint.X, (int)tempPoint.Y + (int)btnOpenWith.ActualHeight), 1, false);
 565            btnOpenWith.IsEnabled = itemMenuCount > 0 && selItemsCount == 1;
 566          } catch {
 567            btnOpenWith.IsEnabled = false;
 568          }
 569        }
 570
 571        btnNewItem.IsEnabled = this._ShellListView.CurrentFolder.IsFileSystem || this._ShellListView.CurrentFolder.ParsingName == KnownFolders.Libraries.ParsingName;
 572        if (selectedItem != null && selectedItem.IsFileSystem && BESettings.IsPreviewPaneEnabled && !selectedItem.IsFolder && selItemsCount == 1)
 573          this.Previewer.FileName = selectedItem.ParsingName;
 574        else if (!String.IsNullOrEmpty(this.Previewer.FileName))
 575          this.Previewer.FileName = null;
 576
 577        //Set up ribbon contextual tabs on selection changed
 578        SetUpRibbonTabsVisibilityOnSelectOrNavigate(selItemsCount, selectedItem);
 579        SetUpButtonsStateOnSelectOrNavigate(selItemsCount, selectedItem);
 580      }));
 581    }
 582
 583    bool IsFromSelectionOrNavigation = false;
 584
 585    void cbm_ClipboardChanged(object sender, Tuple<WIN.Forms.IDataObject> e) {
 586      btnPaste.IsEnabled = e.Item1.GetDataPresent(DataFormats.FileDrop) || e.Item1.GetDataPresent("Shell IDList Array");
 587      btnPasetShC.IsEnabled = e.Item1.GetDataPresent(DataFormats.FileDrop) || e.Item1.GetDataPresent("Shell IDList Array");
 588    }
 589
 590    #endregion
 591
 592    #region Conditional Select
 593
 594    private void miSelAllByType_Click(object sender, RoutedEventArgs e) {
 595      if (_ShellListView.GetSelectedCount() > 0) {
 596        var typePK = new PROPERTYKEY() { fmtid = Guid.Parse("B725F130-47EF-101A-A5F1-02608C9EEBAC"), pid = 4 };
 597        var flt = _ShellListView.SelectedItems.Select(item => item.GetPropertyValue(typePK, typeof(String)).Value.ToString().ToLowerInvariant());
 598        var items = _ShellListView.Items.Where(w => flt.Contains(w.GetPropertyValue(typePK, typeof(String)).Value.ToString().ToLowerInvariant())).ToArray();
 599        _ShellListView.SelectItems(items);
 600        btnCondSel.IsDropDownOpen = false;
 601      }
 602    }
 603
 604    private void miSelAllByDate_Click(object sender, RoutedEventArgs e) {
 605      if (_ShellListView.GetSelectedCount() > 0) {
 606        var typePK = new PROPERTYKEY() { fmtid = Guid.Parse("b725f130-47ef-101a-a5f1-02608c9eebac"), pid = 15 };
 607        var flt = _ShellListView.SelectedItems.Select(item => DateTime.Parse(item.GetPropertyValue(typePK, typeof(String)).Value.ToString().ToLowerInvariant()).Date);
 608        var items = _ShellListView.Items.Where(w => flt.Contains(DateTime.Parse(w.GetPropertyValue(typePK, typeof(String)).Value.ToString().ToLowerInvariant()).Date)).ToArray();
 609        _ShellListView.SelectItems(items);
 610        btnCondSel.IsDropDownOpen = false;
 611      }
 612    }
 613
 614    private void btnCondSel_Click(object sender, RoutedEventArgs e) {
 615      btnCondSel.IsDropDownOpen = false;
 616      ConditionalSelectForm.Open(_ShellListView);
 617    }
 618
 619    #endregion
 620
 621    #region Size Chart
 622
 623    private void btnFSizeChart_Click(object sender, RoutedEventArgs e) {
 624      if (_ShellListView.GetSelectedCount() > 0) {
 625        if ((_ShellListView.GetFirstSelectedItem().IsFolder || _ShellListView.GetFirstSelectedItem().IsDrive) && _ShellListView.GetFirstSelectedItem().IsFileSystem) {
 626          FolderSizeWindow.Open(_ShellListView.GetFirstSelectedItem().ParsingName, this);
 627          return;
 628        }
 629      } else if ((_ShellListView.CurrentFolder.IsFolder || _ShellListView.CurrentFolder.IsDrive) && _ShellListView.CurrentFolder.IsFileSystem) {
 630        FolderSizeWindow.Open(_ShellListView.CurrentFolder.ParsingName, this);
 631      }
 632    }
 633
 634    private void btnSizeChart_Click(object sender, RoutedEventArgs e) {
 635      FolderSizeWindow.Open(_ShellListView.CurrentFolder.ParsingName, this);
 636    }
 637
 638    #endregion
 639
 640    #region Home Tab
 641
 642    private void btnctDocuments_Click(object sender, RoutedEventArgs e) => SetFOperation(KnownFolders.Documents.ParsingName, OperationType.Copy);
 643    private void btnctDesktop_Click(object sender, RoutedEventArgs e) => SetFOperation(KnownFolders.Desktop.ParsingName, OperationType.Copy);
 644    private void btnctDounloads_Click(object sender, RoutedEventArgs e) => SetFOperation(KnownFolders.Downloads.ParsingName, OperationType.Copy);
 645    private void btnmtDocuments_Click(object sender, RoutedEventArgs e) => SetFOperation(KnownFolders.Documents.ParsingName, OperationType.Move);
 646    private void btnmtDesktop_Click(object sender, RoutedEventArgs e) => SetFOperation(KnownFolders.Desktop.ParsingName, OperationType.Move);
 647    private void btnmtDounloads_Click(object sender, RoutedEventArgs e) => SetFOperation(KnownFolders.Downloads.ParsingName, OperationType.Move);
 648    private void btnCopyto_Click(object sender, RoutedEventArgs e) => btnctOther_Click(sender, e);
 649    private void btnMoveto_Click(object sender, RoutedEventArgs e) => btnmtOther_Click(sender, e);
 650    private void btnCut_Click(object sender, RoutedEventArgs e) => _ShellListView.CutSelectedFiles();
 651    private void btnOpenWith_Click(object sender, RoutedEventArgs e) => Process.Start($"\"{_ShellListView.GetFirstSelectedItem().ParsingName}\"");
 652    private void btnPaste_Click(object sender, RoutedEventArgs e) => _ShellListView.PasteAvailableFiles();
 653    private void btnDelete_Click(object sender, RoutedEventArgs e) => MenuItem_Click(sender, e);
 654    private void btnRename_Click(object sender, RoutedEventArgs e) => _ShellListView.RenameSelectedItem();
 655    private void btnSelAll_Click(object sender, RoutedEventArgs e) => _ShellListView.SelectAll();
 656    private void btnSelNone_Click(object sender, RoutedEventArgs e) => _ShellListView.DeSelectAllItems();
 657    private void MenuItem_Click(object sender, RoutedEventArgs e) => _ShellListView.DeleteSelectedFiles(true);
 658    private void MenuItem_Click_1(object sender, RoutedEventArgs e) => _ShellListView.DeleteSelectedFiles(false);
 659    private void btnProperties_Click(object sender, RoutedEventArgs e) => _ShellListView.ShowPropPage(this.Handle, _ShellListView.GetFirstSelectedItem().ParsingName, "");
 660    private void btnInvSel_Click(object sender, RoutedEventArgs e) => _ShellListView.InvertSelection();
 661    private void btnNewWindow_Click(object sender, RoutedEventArgs e) => Process.Start(Assembly.GetExecutingAssembly().Location, "/nw");
 662    void miow_Click(object sender, RoutedEventArgs e) => ((AssociationItem)(sender as MenuItem).Tag).Invoke();
 663
 664
 665
 666    private void miJunctionpoint_Click(object sender, RoutedEventArgs e) {
 667      string pathForDrop = _ShellListView.CurrentFolder.ParsingName.Replace(@"\\", @"\");
 668      var files = new string[0];
 669      if (Clipboards.ContainsData("Shell IDList Array"))
 670        files = Clipboards.GetDataObject().ToShellItemArray().ToArray().Select(s => new ShellItem(s).ParsingName).ToArray();
 671      else
 672        files = Clipboards.GetFileDropList().OfType<string>().ToArray();
 673
 674      foreach (string item in files) {
 675        var o = new ShellItem(item);
 676        JunctionPointUtils.JunctionPoint.Create($@"{pathForDrop}\{o.GetDisplayName(SIGDN.NORMALDISPLAY)}", o.ParsingName, true);
 677        AddToLog($@"Created Junction Point at {pathForDrop}\{o.GetDisplayName(SIGDN.NORMALDISPLAY)} linked to {o.ParsingName}");
 678      }
 679    }
 680
 681    private void miCreateSymlink_Click(object sender, RoutedEventArgs e) {
 682      var items = new IListItemEx[0];
 683      items = Clipboards.ContainsData("Shell IDList Array") ? Clipboards.GetDataObject().ToShellItemArray().ToArray().Select(s => FileSystemListItem.InitializeWithIShellItem(this._ShellListView.LVHandle, s)).ToArray() : Clipboards.GetFileDropList().OfType<string>().ToArray().Select(s => FileSystemListItem.ToFileSystemItem(this._ShellListView.LVHandle, s)).ToArray();
 684      var pathForDrop = _ShellListView.CurrentFolder.ParsingName.Replace(@"\\", @"\");
 685      var exePath = Utilities.AppDirectoryItem("BetterExplorerOperations.exe");
 686      var linkItems = items.Select(s => new LinkItem() {
 687        IsDirectory = s.IsFolder,
 688        DestinationData = pathForDrop + @"\" + s.DisplayName,
 689        SourceData = s.ParsingName
 690      }).ToArray();
 691
 692      Task.Run(() => {
 693        using (var proc = new Process()) {
 694          proc.StartInfo = new ProcessStartInfo {
 695            FileName = exePath,
 696            Verb = "runas",
 697            UseShellExecute = true,
 698            Arguments = $"/env /user:Administrator \"{exePath}\""
 699          };
 700
 701          proc.Start();
 702          ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
 703          var address = new EndpointAddress(new Uri("net.tcp://localhost:60000/BEComChannel"));
 704          var binding = new NetTcpBinding() { MaxReceivedMessageSize = 4000000, MaxBufferPoolSize = 4000000, MaxBufferSize = 4000000 };
 705          binding.Security = new NetTcpSecurity() { Mode = SecurityMode.Message };
 706          var factory = new ChannelFactory<IBetterExplorerCommunication>(binding, address);
 707          var beSvc = factory.CreateChannel();
 708          try {
 709            beSvc.CreateLink(new LinkData() { Items = linkItems });
 710          } finally {
 711            Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => this._ShellListView.UnvalidateDirectory()));
 712          }
 713
 714          proc.WaitForExit();
 715          if (proc.ExitCode == 1)
 716            MessageBox.Show("Error in creating symlink", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
 717          else {
 718            Thread.Sleep(1000);
 719            Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => this._ShellListView.UnvalidateDirectory()));
 720          }
 721        }
 722      });
 723
 724    }
 725
 726    private void btnHistory_Click(object sender, RoutedEventArgs e) {
 727      _ShellListView.ShowPropPage(this.Handle, _ShellListView.GetFirstSelectedItem().ParsingName,
 728                                      User32.LoadResourceString(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "twext.dll"), 1024, "Previous Versions"));
 729    }
 730
 731    private void btnBackstageExit_Click(object sender, RoutedEventArgs e) {
 732      //! We call Shutdown() so to explicit shutdown the app regardless of windows closing cancel flag.
 733      if (this.IsMultipleWindowsOpened)
 734        this.Close();
 735      else
 736        Application.Current.Shutdown();
 737    }
 738
 739    void mif_Click(object sender, RoutedEventArgs e) {
 740      using (var obj = (sender as MenuItem).Tag as ShellItem)
 741      using (var lnk = new ShellLink(obj.ParsingName)) {
 742        NavigationController(FileSystemListItem.ToFileSystemItem(this._ShellListView.LVHandle, lnk.TargetPIDL));
 743      }
 744    }
 745
 746    private void btnCopy_Click(object sender, RoutedEventArgs e) {
 747      var sc = new StringCollection();
 748      sc.AddRange(_ShellListView.SelectedItems.Select(x => x.ParsingName).ToArray());
 749      Clipboards.SetFileDropList(sc);
 750    }
 751
 752
 753    private void btnPathCopy_Click(object sender, RoutedEventArgs e) {
 754      if (_ShellListView.SelectedItems.Count > 1)
 755        Clipboards.SetText(_ShellListView.SelectedItems.Select(item => "\r\n" + item.ParsingName).Aggregate((x, y) => x + y).Trim());
 756      else if (_ShellListView.SelectedItems.Count == 1)
 757        Clipboards.SetText(_ShellListView.GetFirstSelectedItem().ParsingName);
 758      else
 759        Clipboards.SetText(_ShellListView.CurrentFolder.ParsingName);
 760    }
 761
 762
 763    // New Folder/Library
 764    private void btnNewFolder_Library(object sender, RoutedEventArgs e) {
 765      //We should focus the ListView or on some circumstances new folder does not start renaming after folder is created
 766      this._ShellListView.Focus();
 767      _ShellListView.IsRenameNeeded = true;
 768
 769      if (_ShellListView.CurrentFolder.ParsingName == KnownFolders.Libraries.ParsingName)
 770        _ShellListView.CreateNewLibrary(FindResource("btnNewLibraryCP").ToString());
 771      else
 772        _ShellListView.CreateNewFolder(null);
 773    }
 774
 775    private void btnPasetShC_Click(object sender, RoutedEventArgs e) {
 776      string PathForDrop = _ShellListView.CurrentFolder.ParsingName;
 777      foreach (string item in Clipboards.GetFileDropList()) {
 778        using (var shortcut = new ShellLink()) {
 779          var o = new ShellItem(item);
 780          shortcut.Target = item;
 781          shortcut.WorkingDirectory = Path.GetDirectoryName(item);
 782          shortcut.Description = o.GetDisplayName(SIGDN.NORMALDISPLAY);
 783          shortcut.DisplayMode = ShellLink.LinkDisplayMode.edmNormal;
 784          shortcut.Save($"{PathForDrop}\\{o.GetDisplayName(SIGDN.NORMALDISPLAY)}.lnk");
 785          AddToLog($"Shortcut created at {PathForDrop}\\{o.GetDisplayName(SIGDN.NORMALDISPLAY)} from source {item}");
 786        }
 787      }
 788    }
 789
 790    private void btnmtOther_Click(object sender, RoutedEventArgs e) {
 791      var dlg = new FolderSelectDialog();
 792      if (dlg.ShowDialog())
 793        SetFOperation(dlg.FileName, OperationType.Move);
 794    }
 795
 796    private void SetFOperation(String fileName, OperationType opType) {
 797      var obj = FileSystemListItem.ToFileSystemItem(this._ShellListView.LVHandle, fileName.ToShellParsingName());
 798      if (opType == OperationType.Copy)
 799        _ShellListView.DoCopy(obj);
 800      else if (opType == OperationType.Move)
 801        _ShellListView.DoMove(obj);
 802    }
 803
 804    private void SetFOperation(IListItemEx obj, OperationType opType) {
 805      if (opType == OperationType.Copy)
 806        _ShellListView.DoCopy(obj);
 807      else if (opType == OperationType.Move)
 808        _ShellListView.DoMove(obj);
 809    }
 810
 811    private void btnctOther_Click(object sender, RoutedEventArgs e) {
 812      var dlg = new FolderSelectDialog();
 813      if (dlg.ShowDialog())
 814        SetFOperation(dlg.FileName, OperationType.Copy);
 815
 816      _ShellListView.Focus();
 817    }
 818
 819    private void btnNewItem_Click(object sender, RoutedEventArgs e) {
 820      var state = new BExplorer.Shell.Interop.Shell32.SHELLSTATE() { fShowAllObjects = 0 };
 821      BExplorer.Shell.Interop.Shell32.SHGetSetSettings(ref state, BExplorer.Shell.Interop.Shell32.SSF.SSF_SHOWALLOBJECTS, true);
 822    }
 823
 824    private void btnEdit_Click(object sender, RoutedEventArgs e) {
 825      new Process() {
 826        StartInfo = new ProcessStartInfo {
 827          FileName = _ShellListView.GetFirstSelectedItem().ParsingName,
 828          Verb = "edit",
 829          UseShellExecute = true,
 830        }
 831      }.Start();
 832    }
 833
 834    private void btnFavorites_Click(object sender, RoutedEventArgs e) {
 835      var selectedItems = _ShellListView.SelectedItems;
 836      if (selectedItems.Count == 1) {
 837        var link = new ShellLink();
 838        link.DisplayMode = ShellLink.LinkDisplayMode.edmNormal;
 839        link.Target = _ShellListView.GetFirstSelectedItem().ParsingName;
 840        link.Save($@"{KnownFolders.Links.ParsingName}\{_ShellListView.GetFirstSelectedItem().DisplayName}.lnk");
 841        link.Dispose();
 842      }
 843
 844      if (selectedItems.Count == 0) {
 845        var link = new ShellLink();
 846        link.DisplayMode = ShellLink.LinkDisplayMode.edmNormal;
 847        link.Target = _ShellListView.CurrentFolder.ParsingName;
 848        link.Save($@"{KnownFolders.Links.ParsingName}\{_ShellListView.CurrentFolder.DisplayName}.lnk");
 849        link.Dispose();
 850      }
 851    }
 852
 853    #endregion
 854
 855    #region Drive Tools / Virtual Disk Tools
 856
 857    private void btnDefragDrive_Click(object sender, RoutedEventArgs e) {
 858      string DriveLetter = "";
 859
 860      if (!_ShellListView.SelectedItems.Any())
 861        DriveLetter = _ShellListView.CurrentFolder.ParsingName;
 862      else if (Directory.GetLogicalDrives().Contains(_ShellListView.SelectedItems[0].ParsingName))
 863        DriveLetter = _ShellListView.SelectedItems[0].ParsingName;
 864      else
 865        DriveLetter = _ShellListView.CurrentFolder.ParsingName;
 866
 867      Process.Start(Path.Combine(Environment.SystemDirectory, "dfrgui.exe"), $"/u /v {DriveLetter.Replace("\\", "")}");
 868    }
 869
 870    private char GetDriveLetterFromDrivePath(string path) => path.Substring(0, 1).ToCharArray()[0];
 871
 872    private void btnFormatDrive_Click(object sender, RoutedEventArgs e) {
 873      if (MessageBox.Show("Are you sure you want to do this?", FindResource("btnFormatDriveCP").ToString(), MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) {
 874        var formatDriveThread = new Thread(() => {
 875          string DriveLetter =
 876          _ShellListView.SelectedItems.Any() ?
 877          DriveLetter = Directory.GetLogicalDrives().Contains(_ShellListView.SelectedItems[0].ParsingName) ? _ShellListView.SelectedItems[0].ParsingName : _ShellListView.CurrentFolder.ParsingName
 878          :
 879          DriveLetter = _ShellListView.CurrentFolder.ParsingName;
 880
 881          BExplorer.Shell.Interop.Shell32.FormatDrive(IntPtr.Zero, DriveLetter);
 882        });
 883
 884        formatDriveThread.Start();
 885      }
 886    }
 887
 888    private void btnCleanDrive_Click(object sender, RoutedEventArgs e) {
 889      string DriveLetter = "";
 890      if (_ShellListView.SelectedItems.Any())
 891        DriveLetter = Directory.GetLogicalDrives().Contains(_ShellListView.SelectedItems[0].ParsingName) ? _ShellListView.SelectedItems[0].ParsingName : _ShellListView.CurrentFolder.ParsingName;
 892      else
 893        DriveLetter = _ShellListView.CurrentFolder.ParsingName;
 894
 895      Process.Start("Cleanmgr.exe", "/d" + DriveLetter.Replace(":\\", ""));
 896    }
 897
 898    private void OpenCDTray(char DriveLetter) {
 899      mciSendString($"open {DriveLetter}: type CDAudio alias drive{DriveLetter}", null, 0, IntPtr.Zero);
 900      mciSendString($"set drive{DriveLetter} door open", null, 0, IntPtr.Zero);
 901    }
 902
 903    private void CloseCDTray(char DriveLetter) {
 904      mciSendString($"open {DriveLetter}: type CDAudio alias drive{DriveLetter}", null, 0, IntPtr.Zero);
 905      mciSendString($"set drive{DriveLetter} door closed", null, 0, IntPtr.Zero);
 906    }
 907
 908    private void btnOpenTray_Click(object sender, RoutedEventArgs e) {
 909      if (_ShellListView.GetFirstSelectedItem()?.GetDriveInfo().DriveType == DriveType.CDRom)
 910        OpenCDTray(GetDriveLetterFromDrivePath(_ShellListView.GetFirstSelectedItem().ParsingName));
 911    }
 912
 913    private void btnCloseTray_Click(object sender, RoutedEventArgs e) {
 914      if (_ShellListView.GetFirstSelectedItem()?.GetDriveInfo().DriveType == DriveType.CDRom)
 915        CloseCDTray(GetDriveLetterFromDrivePath(_ShellListView.GetFirstSelectedItem().ParsingName));
 916    }
 917
 918    private void EjectDisk(char DriveLetter) {
 919      Thread t = new Thread(() => {
 920        Thread.Sleep(10);
 921        var vdc = new VolumeDeviceClass();
 922        foreach (Volume item in vdc.Devices) {
 923          if (GetDriveLetterFromDrivePath(item.LogicalDrive) == DriveLetter) {
 924            var veto = item.Eject(false);
 925            if (veto != Native.PNP_VETO_TYPE.TypeUnknown) {
 926              if (veto == Native.PNP_VETO_TYPE.Ok) {
 927                Dispatcher.BeginInvoke(DispatcherPriority.Normal,
 928                                (Action)(() => {
 929                                  this.beNotifyIcon.ShowBalloonTip("Information", $"It is safe to remove {item.LogicalDrive}", Hardcodet.Wpf.TaskbarNotification.BalloonIcon.Info);
 930                                  var tabsForRemove = tcMain.Items.OfType<Wpf.Controls.TabItem>().Where(w => {
 931                                    var root = String.Empty;
 932                                    try {
 933                                      root = Path.GetPathRoot(w.ShellObject.ParsingName.ToShellParsingName());
 934                                    } catch { }
 935                                    return !String.IsNullOrEmpty(root) && (w.ShellObject.IsFileSystem &&
 936                                                    root.ToLowerInvariant() == $"{DriveLetter}:\\".ToLowerInvariant());
 937                                  }).ToArray();
 938
 939                                  foreach (Wpf.Controls.TabItem tab in tabsForRemove) {
 940                                    tcMain.RemoveTabItem(tab);
 941                                  }
 942                                }));
 943              } else {
 944                var message = String.Empty;
 945                var obj = new ShellItem(item.LogicalDrive);
 946                switch (veto) {
 947                  case Native.PNP_VETO_TYPE.Ok:
 948                    break;
 949                  case Native.PNP_VETO_TYPE.TypeUnknown:
 950                    break;
 951                  case Native.PNP_VETO_TYPE.LegacyDevice:
 952                    break;
 953                  case Native.PNP_VETO_TYPE.PendingClose:
 954                    break;
 955                  case Native.PNP_VETO_TYPE.WindowsApp:
 956                    break;
 957                  case Native.PNP_VETO_TYPE.WindowsService:
 958                    break;
 959                  case Native.PNP_VETO_TYPE.OutstandingOpen:
 960                    message = $"The device {obj.GetDisplayName(SIGDN.NORMALDISPLAY)} can not be disconnected because is in use!";
 961                    break;
 962                  case Native.PNP_VETO_TYPE.Device:
 963                    break;
 964                  case Native.PNP_VETO_TYPE.Driver:
 965                    break;
 966                  case Native.PNP_VETO_TYPE.IllegalDeviceRequest:
 967                    break;
 968                  case Native.PNP_VETO_TYPE.InsufficientPower:
 969                    break;
 970                  case Native.PNP_VETO_TYPE.NonDisableable:
 971                    message = $"The device {obj.GetDisplayName(SIGDN.NORMALDISPLAY)} does not support disconnecting!";
 972                    break;
 973                  case Native.PNP_VETO_TYPE.LegacyDriver:
 974                    break;
 975                  default:
 976                    break;
 977                }
 978
 979                Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() => this.beNotifyIcon.ShowBalloonTip("Error", message, Hardcodet.Wpf.TaskbarNotification.BalloonIcon.Error)));
 980              }
 981            }
 982            break;
 983          }
 984        }
 985      });
 986      t.SetApartmentState(ApartmentState.STA);
 987      t.Start();
 988    }
 989
 990    private void btnEjectDevice_Click(object sender, RoutedEventArgs e) {
 991      var firstSelectedItem = _ShellListView.GetFirstSelectedItem();
 992      if (firstSelectedItem?.GetDriveInfo().DriveType == DriveType.Removable || firstSelectedItem.GetDriveInfo().DriveType == DriveType.Fixed) {
 993        EjectDisk(GetDriveLetterFromDrivePath(firstSelectedItem.ParsingName));
 994        //USBEject.EjectDrive(GetDriveLetterFromDrivePath(firstSelectedItem.ParsingName));
 995      }
 996    }
 997
 998    // Virtual Disk Tools
 999    private bool CheckImDiskInstalled() {
1000      try {
1001        ImDiskAPI.GetDeviceList();
1002        return true;
1003      } catch (DllNotFoundException) {
1004        return false;
1005      }
1006    }
1007
1008    public void ShowInstallImDiskMessage() {
1009      if (MessageBox.Show("It appears you do not have the ImDisk Virtual Disk Driver installed. This driver is used to power Better Explorer's ISO-mounting features. \n\nWould you like to visit ImDisk's website to install the product? (http://www.ltr-data.se/opencode.html/)", "ImDisk Not Found", MessageBoxButton.YesNo, MessageBoxImage.Error) == MessageBoxResult.Yes) {
1010        Process.Start("http://www.ltr-data.se/opencode.html/#ImDisk");
1011      }
1012    }
1013
1014    private void btnAdvMountIso_Click(object sender, RoutedEventArgs e) {
1015      if (!CheckImDiskInstalled()) {
1016        ShowInstallImDiskMessage();
1017        return;
1018      }
1019
1020      var mi = new MountIso() { Owner = this };
1021      mi.ShowDialog();
1022      if (mi.yep) {
1023        string DriveLetter = String.Format("{0}:", mi.chkPreselect.IsChecked == true ? ImDiskAPI.FindFreeDriveLetter() : (char)mi.cbbLetter.SelectedItem);
1024        long size = mi.chkPresized.IsChecked == true ? 0 : Convert.ToInt64(mi.txtSize.Text);
1025
1026        ImDiskFlags i

Large files files are truncated, but you can click here to view the full file