Skip to content

Commit 0e8e194

Browse files
committed
- more fixes for the theme
- fixes for the treeview - returning the native dark mode scrollbars for the listview since custom one cause alot of troubles Related Work Items: #65
1 parent 60d470c commit 0e8e194

File tree

6 files changed

+434
-157
lines changed

6 files changed

+434
-157
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,4 @@ BExplorer/BetterExplorer/BEHelper.dll.config
278278
/Debug/ImDiskNet.xml
279279
/Debug/ImDiskNet.pdb
280280
/Debug/ImDiskNet.dll
281+
/ShellExplorerControls/SHControls/ShellExplorerControls

BExplorer/BetterExplorer/MainWindow.xaml.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,6 +1655,7 @@ private void Window_Loaded(object sender, RoutedEventArgs e) {
16551655
this.ShellViewHost.Child = this._ShellListView;
16561656

16571657
this.stvTreeView.ShellListView = this._ShellListView;
1658+
this.stvTreeView.NodeClick += (o, args) => { this.tcMain.NewTab(args.Item, false); };
16581659
//this.ctrlConsole.ShellListView = this._ShellListView;
16591660
this.autoUpdater.UpdateAvailable += this.AutoUpdater_UpdateAvailable;
16601661
this.updateCheckTimer.Interval = 10000;//3600000 * 3;

Shell/ShellContextMenu.cs

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,177 @@ public void ShowContextMenu(Control control, Point pos, CMF aditionalFlags = 0,
411411
Marshal.Release(this._Result);
412412
this._Result = IntPtr.Zero;
413413
}
414+
public void ShowContextMenu(Point pos, CMF aditionalFlags, bool IsOnEmpty = false) {
415+
using (ContextMenu mnu = new ContextMenu()) {
416+
this.Populate(mnu, aditionalFlags);
417+
this._Timer.Interval = 2;
418+
this._Timer.Tick += TimerOnTick;
419+
this._Timer.Stop();
420+
421+
var view = new ContextMenu();
422+
var sortMenu = new ContextMenu();
423+
var groupMenu = new ContextMenu();
424+
var count = User32.GetMenuItemCount(mnu.Handle);
425+
426+
var itemInfo = new MENUITEMINFO();
427+
428+
itemInfo.fMask = MIIM.MIIM_FTYPE | MIIM.MIIM_DATA | MIIM.MIIM_STRING | MIIM.MIIM_SUBMENU | MIIM.MIIM_ID;
429+
if (User32.GetMenuItemInfo(mnu.Handle, count - 1, true, ref itemInfo)) {
430+
if ((itemInfo.fType & MFT.MFT_SEPARATOR) != 0) {
431+
User32.DeleteMenu(mnu.Handle, count - 1, MF.MF_BYPOSITION);
432+
}
433+
}
434+
435+
User32.GetMenuItemInfo(mnu.Handle, User32.GetMenuItemCount(mnu.Handle) - 3, true, ref itemInfo);
436+
if (itemInfo.hSubMenu == IntPtr.Zero) {
437+
User32.GetMenuItemInfo(mnu.Handle, User32.GetMenuItemCount(mnu.Handle) - 1, true, ref itemInfo);
438+
}
439+
440+
this._NewMenuPtr = itemInfo.hSubMenu;
441+
442+
if (IsOnEmpty) {
443+
this.GenerateExplorerBackgroundMenuItems(view, mnu, sortMenu, groupMenu);
444+
} else {
445+
if (this._Items.FirstOrDefault()?.IsFolder == true) {
446+
this.GenerateMenuItem(mnu, System.Windows.Application.Current?.FindResource("mnuOpenNewTab")?.ToString(), 301, false, 1);
447+
}
448+
}
449+
450+
this.RemoveDuplicatedSeparators(mnu);
451+
452+
453+
454+
var command = User32.TrackPopupMenuEx(mnu.Handle, TPM.TPM_RETURNCMD, pos.X, pos.Y, m_MessageWindow.Handle, IntPtr.Zero);
455+
if (command > 0 && command < m_CmdFirst) {
456+
switch (command) {
457+
case 245:
458+
this._ShellView.SetGroupOrder(false);
459+
break;
460+
case 246:
461+
this._ShellView.SetGroupOrder();
462+
break;
463+
case 247:
464+
var colasc = this._ShellView.Collumns.FirstOrDefault(w => w.ID == this._ShellView.LastSortedColumnId);
465+
this._ShellView.SetSortCollumn(true, colasc, SortOrder.Ascending);
466+
break;
467+
case 248:
468+
var coldesc = this._ShellView.Collumns.FirstOrDefault(w => w.ID == this._ShellView.LastSortedColumnId);
469+
this._ShellView.SetSortCollumn(true, coldesc, SortOrder.Descending);
470+
break;
471+
case 249:
472+
this._ShellView.PasteAvailableFiles();
473+
break;
474+
case 250:
475+
this._ShellView.RefreshContents();
476+
break;
477+
case 251:
478+
this._ShellView.View = ShellViewStyle.ExtraLargeIcon;
479+
break;
480+
case 252:
481+
this._ShellView.View = ShellViewStyle.LargeIcon;
482+
break;
483+
case 253:
484+
this._ShellView.View = ShellViewStyle.Medium;
485+
break;
486+
case 254:
487+
this._ShellView.View = ShellViewStyle.SmallIcon;
488+
break;
489+
case 255:
490+
this._ShellView.View = ShellViewStyle.List;
491+
break;
492+
case 256:
493+
this._ShellView.View = ShellViewStyle.Details;
494+
break;
495+
case 257:
496+
this._ShellView.View = ShellViewStyle.Tile;
497+
break;
498+
case 258:
499+
this._ShellView.View = ShellViewStyle.Content;
500+
break;
501+
case 259:
502+
this._ShellView.View = ShellViewStyle.Thumbstrip;
503+
break;
504+
case 260:
505+
if (this._ShellView.IsGroupsEnabled) {
506+
this._ShellView.DisableGroups();
507+
}
508+
break;
509+
case 301:
510+
this._ShellView.RaiseMiddleClickOnItem(this._Items.First());
511+
break;
512+
default:
513+
break;
514+
}
515+
516+
if (command >= 262 && command <= 262 + this._ShellView.Collumns.Count) {
517+
this._ShellView.SetSortCollumn(true, this._ShellView.Collumns[command - 262], SortOrder.Ascending);
518+
} else if (command > 260 && command != 301) {
519+
if (!this._ShellView.IsGroupsEnabled)
520+
this._ShellView.EnableGroups();
521+
this._ShellView.GenerateGroupsFromColumn(this._ShellView.Collumns[command - (262 + this._ShellView.Collumns.Count) - 1], false);
522+
}
523+
}
524+
525+
if (command > m_CmdFirst) {
526+
var info = string.Empty;
527+
var bytes = new byte[256];
528+
IntPtr pszName = Marshal.AllocHGlobal(256);
529+
this.m_ComInterface3.GetCommandString(command - (int)m_CmdFirst, 4, 0, pszName, 260);
530+
531+
//var index = 0;
532+
//while (index < bytes.Length - 1 && (bytes[index] != 0 || bytes[index + 1] != 0)) { index += 2; }
533+
534+
//if (index < bytes.Length - 1) { info = Encoding.Unicode.GetString(bytes, 0, index); }
535+
info = Marshal.PtrToStringAuto(pszName);
536+
537+
switch (info) {
538+
case "open":
539+
//(control as ShellView)?.OpenOrNavigateItem();
540+
break;
541+
case "rename":
542+
//(control as ShellView)?.RenameSelectedItem();
543+
break;
544+
case "cut":
545+
//(control as ShellView)?.CutSelectedFiles();
546+
break;
547+
case "copy":
548+
//(control as ShellView)?.CopySelectedFiles();
549+
break;
550+
default:
551+
CMINVOKECOMMANDINFOEX cminvokecommandinfoex = new CMINVOKECOMMANDINFOEX {
552+
lpVerb = (IntPtr)(command - m_CmdFirst),
553+
lpVerbW = (IntPtr)(command - m_CmdFirst)
554+
};
555+
cminvokecommandinfoex.cbSize = Marshal.SizeOf(cminvokecommandinfoex);
556+
557+
//cminvokecommandinfoex.lpDirectory = this._ShellView.CurrentFolder.ParsingName;
558+
//cminvokecommandinfoex.lpDirectoryW = this._ShellView.CurrentFolder.ParsingName;
559+
560+
cminvokecommandinfoex.fMask = ((CMIC.Asyncok | CMIC.PtInvoke | CMIC.Unicode | CMIC.FlagNoUi) | (((Control.ModifierKeys & Keys.Control) > Keys.None) ? CMIC.ControlDown : ((CMIC)0))) | (((Control.ModifierKeys & Keys.Shift) > Keys.None) ? CMIC.ShiftDown : ((CMIC)0));
561+
cminvokecommandinfoex.ptInvoke = pos;
562+
cminvokecommandinfoex.nShow = 1;
563+
//cminvokecommandinfoex.hwnd = this._ShellView.LVHandle;
564+
this.m_ComInterface3.InvokeCommand(ref cminvokecommandinfoex);
565+
//this.InvokeCommand((IntPtr)(command - m_CmdFirst), pos, (IntPtr)(command - m_CmdFirst));
566+
break;
567+
}
568+
}
569+
570+
User32.DestroyMenu(mnu.Handle);
571+
view.Dispose();
572+
User32.DestroyMenu(view.Handle);
573+
sortMenu.Dispose();
574+
User32.DestroyMenu(sortMenu.Handle);
575+
groupMenu.Dispose();
576+
User32.DestroyMenu(groupMenu.Handle);
577+
}
578+
579+
Marshal.ReleaseComObject(this.m_ComInterface);
580+
Marshal.ReleaseComObject(this.m_ComInterface2);
581+
Marshal.ReleaseComObject(this.m_ComInterface3);
582+
Marshal.Release(this._Result);
583+
this._Result = IntPtr.Zero;
584+
}
414585
private void TimerOnTick(Object sender, EventArgs e) {
415586
this._Timer.Stop();
416587
User32.SendMessage(this.m_MessageWindow.Handle, 0x001F, 0, 0);

Shell/ShellTreeView.xaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,12 @@
309309
<Trigger Property="Orientation" Value="Horizontal">
310310
<Setter Property="Width" Value="Auto" />
311311
<Setter Property="Template" Value="{DynamicResource HorizontalScrollBar}" />
312-
<Setter Property="Height" Value="18" />
312+
<Setter Property="Height" Value="16" />
313313
</Trigger>
314314
<Trigger Property="Orientation" Value="Vertical">
315315
<Setter Property="Height" Value="Auto" />
316316
<Setter Property="Template" Value="{DynamicResource VerticalScrollBar}" />
317-
<Setter Property="Width" Value="18" />
317+
<Setter Property="Width" Value="16" />
318318
</Trigger>
319319
</Style.Triggers>
320320
</Style>
@@ -326,12 +326,12 @@
326326
<Trigger Property="Orientation" Value="Horizontal">
327327
<Setter Property="Width" Value="Auto" />
328328
<Setter Property="Template" Value="{DynamicResource HorizontalScrollBar}" />
329-
<Setter Property="Height" Value="17" />
329+
<Setter Property="Height" Value="16" />
330330
</Trigger>
331331
<Trigger Property="Orientation" Value="Vertical">
332332
<Setter Property="Height" Value="Auto" />
333333
<Setter Property="Template" Value="{DynamicResource VerticalScrollBar}" />
334-
<Setter Property="Width" Value="17" />
334+
<Setter Property="Width" Value="16" />
335335
</Trigger>
336336
</Style.Triggers>
337337
</Style>

Shell/ShellTreeView.xaml.cs

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System;
44
using System.Collections.Generic;
55
using System.Collections.ObjectModel;
6+
using System.Drawing;
67
using System.Linq;
78
using System.Threading;
89
using System.Windows;
@@ -13,6 +14,7 @@
1314
using System.Windows.Media;
1415
using System.Windows.Threading;
1516
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
17+
using TabControl = System.Windows.Controls.TabControl;
1618
using UserControl = System.Windows.Controls.UserControl;
1719

1820
namespace BExplorer.Shell {
@@ -52,7 +54,7 @@ private void ShellListViewOnNewItemAvailable(Object sender, ItemUpdatedEventArgs
5254

5355
#region Event Handlers
5456

55-
public event EventHandler<TreeNodeMouseClickEventArgs> NodeClick;
57+
public event EventHandler<TreeViewMiddleClickEventArgs> NodeClick;
5658

5759
public event EventHandler<NavigatedEventArgs> AfterSelect;
5860

@@ -264,41 +266,41 @@ private void TvShellTreeViewInternal_OnExpanded(Object sender, RoutedEventArgs e
264266
//var navThread = new Thread(() => {
265267

266268

267-
this.Dispatcher.BeginInvoke(DispatcherPriority.Render, (ThreadStart)(() => {
268-
var sho = fstItem.FsItem;
269-
fstItem.Items.Clear();
270-
foreach (var item in sho.ParsingName != KnownFolders.Computer.ParsingName
271-
? sho.GetContents(this.IsShowHiddenItems)
272-
.Where(w => (sho != null && !sho.IsFileSystem && System.IO.Path.GetExtension(sho?.ParsingName)?.ToLowerInvariant() != ".library-ms") ||
273-
(w.IsFolder || w.IsLink || w.IsDrive)).OrderBy(o => o.DisplayName)
274-
: sho.GetContents(this.IsShowHiddenItems)
275-
.Where(w => (sho != null && !sho.IsFileSystem && System.IO.Path.GetExtension(sho?.ParsingName)?.ToLowerInvariant() != ".library-ms") || (w.IsFolder || w.IsLink || w.IsDrive))) {
276-
if (item != null && !item.IsFolder && !item.IsLink) {
277-
continue;
278-
}
279-
//System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate { }));
280-
if (item?.IsLink == true) {
281-
try {
282-
var shellLink = new ShellLink(item.ParsingName);
283-
var linkTarget = shellLink.TargetPIDL;
284-
var itemLinkReal = FileSystemListItem.ToFileSystemItem(IntPtr.Zero, linkTarget);
285-
shellLink.Dispose();
286-
if (!itemLinkReal.IsFolder) {
287-
continue;
288-
}
289-
} catch { }
290-
}
291-
fstItem.Items.Add(new FilesystemTreeViewItem(this, item));
269+
this.Dispatcher.BeginInvoke(DispatcherPriority.Render, (ThreadStart)(() => {
270+
var sho = fstItem.FsItem;
271+
fstItem.Items.Clear();
272+
foreach (var item in sho.ParsingName != KnownFolders.Computer.ParsingName
273+
? sho.GetContents(this.IsShowHiddenItems)
274+
.Where(w => (sho != null && !sho.IsFileSystem && System.IO.Path.GetExtension(sho?.ParsingName)?.ToLowerInvariant() != ".library-ms") ||
275+
(w.IsFolder || w.IsLink || w.IsDrive)).OrderBy(o => o.DisplayName)
276+
: sho.GetContents(this.IsShowHiddenItems)
277+
.Where(w => (sho != null && !sho.IsFileSystem && System.IO.Path.GetExtension(sho?.ParsingName)?.ToLowerInvariant() != ".library-ms") || (w.IsFolder || w.IsLink || w.IsDrive))) {
278+
if (item != null && !item.IsFolder && !item.IsLink) {
279+
continue;
292280
}
293-
294-
fstItem.IsLoaded = true;
295-
var lvSho = this.ShellListView?.CurrentFolder?.Clone();
296-
if (lvSho != null) {
297-
this.SelItem(lvSho);
298-
//var item = this.tvShellTreeViewInternal.ItemContainerGenerator.ContainerFromItemRecursive(this.tvShellTreeViewInternal.SelectedItem);
299-
//item?.BringIntoView();
281+
//System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate { }));
282+
if (item?.IsLink == true) {
283+
try {
284+
var shellLink = new ShellLink(item.ParsingName);
285+
var linkTarget = shellLink.TargetPIDL;
286+
var itemLinkReal = FileSystemListItem.ToFileSystemItem(IntPtr.Zero, linkTarget);
287+
shellLink.Dispose();
288+
if (!itemLinkReal.IsFolder) {
289+
continue;
290+
}
291+
} catch { }
300292
}
301-
}));
293+
fstItem.Items.Add(new FilesystemTreeViewItem(this, item));
294+
}
295+
296+
fstItem.IsLoaded = true;
297+
var lvSho = this.ShellListView?.CurrentFolder?.Clone();
298+
if (lvSho != null) {
299+
this.SelItem(lvSho);
300+
//var item = this.tvShellTreeViewInternal.ItemContainerGenerator.ContainerFromItemRecursive(this.tvShellTreeViewInternal.SelectedItem);
301+
//item?.BringIntoView();
302+
}
303+
}));
302304
//});
303305
//navThread.SetApartmentState(ApartmentState.STA);
304306
//navThread.Start();
@@ -372,7 +374,20 @@ private void TvShellTreeViewInternal_OnPreviewMouseUp(Object sender, MouseButton
372374
return;
373375
}
374376
var shItem = ((e.OriginalSource as FrameworkElement)?.DataContext as FilesystemTreeViewItem)?.FsItem;
375-
this.NavigateListView(shItem);
377+
switch (e.ChangedButton) {
378+
case MouseButton.Left:
379+
this.NavigateListView(shItem);
380+
break;
381+
case MouseButton.Middle:
382+
this.NodeClick?.Invoke(this, new TreeViewMiddleClickEventArgs() { Item = shItem });
383+
break;
384+
case MouseButton.Right:
385+
var pt = this.PointToScreen(e.GetPosition(this));
386+
new ShellContextMenu(this.ShellListView, shItem).ShowContextMenu(new System.Drawing.Point((Int32)pt.X, (Int32)pt.Y), CMF.CANRENAME);
387+
break;
388+
default:
389+
throw new ArgumentOutOfRangeException();
390+
}
376391
}
377392

378393
private void EventSetter_OnHandler(Object sender, RoutedEventArgs e) {

0 commit comments

Comments
 (0)