mirror of
https://github.com/Hofknecht/SystemTrayMenu.git
synced 2024-06-02 18:44:56 +12:00
Reduce code complexity and refined member variables
Improve null pointer assumptions by relying on nullable value types
This commit is contained in:
parent
5d04cc0abd
commit
aa87100095
|
@ -315,7 +315,7 @@ namespace SystemTrayMenu.Handler
|
|||
{
|
||||
ListViewItemData itemData = (ListViewItemData)dgv.Items[iRowKey];
|
||||
RowData trigger = itemData.data;
|
||||
if (trigger.IsMenuOpen || !trigger.ContainsMenu)
|
||||
if (trigger.IsMenuOpen || !trigger.IsPointingToFolder)
|
||||
{
|
||||
trigger.OpenItem(out bool doCloseAfterOpen);
|
||||
if (doCloseAfterOpen)
|
||||
|
|
|
@ -76,11 +76,11 @@ namespace SystemTrayMenu.Business
|
|||
waitToOpenMenu.StartLoadMenu += StartLoadMenu;
|
||||
void StartLoadMenu(RowData rowData)
|
||||
{
|
||||
if (IsMainUsable && rowData.Path != null &&
|
||||
if (IsMainUsable &&
|
||||
(menus[rowData.Level + 1] == null ||
|
||||
menus[rowData.Level + 1]?.RowDataParent != rowData))
|
||||
{
|
||||
Create(new(rowData.Level + 1, rowData), rowData.Path); // Level 1+ Sub Menu (loading)
|
||||
Create(new(rowData), rowData.Path); // Level 1+ Sub Menu (loading)
|
||||
|
||||
BackgroundWorker? workerSubMenu = workersSubMenu.
|
||||
Where(w => !w.IsBusy).FirstOrDefault();
|
||||
|
@ -315,28 +315,12 @@ namespace SystemTrayMenu.Business
|
|||
{
|
||||
BackgroundWorker? workerSelf = sender as BackgroundWorker;
|
||||
RowData? rowData = eDoWork.Argument as RowData;
|
||||
string? path;
|
||||
int level;
|
||||
if (rowData != null)
|
||||
{
|
||||
path = rowData.ResolvedPath;
|
||||
if (path == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
string path = rowData?.ResolvedPath ?? Config.Path;
|
||||
|
||||
level = rowData.Level + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
path = Config.Path;
|
||||
level = 0;
|
||||
}
|
||||
|
||||
MenuData menuData = new(level, rowData);
|
||||
MenuData menuData = new(rowData);
|
||||
DirectoryHelpers.DiscoverItems(workerSelf, path, ref menuData);
|
||||
if (menuData.DirectoryState != MenuDataDirectoryState.Undefined &&
|
||||
workerSelf != null && level == 0)
|
||||
workerSelf != null && rowData == null)
|
||||
{
|
||||
// After success of MainMenu loading: never run again
|
||||
workerSelf.DoWork -= LoadMenu;
|
||||
|
@ -366,7 +350,6 @@ namespace SystemTrayMenu.Business
|
|||
rowDataToClear.IsMenuOpen = false;
|
||||
rowDataToClear.IsClicking = false;
|
||||
rowDataToClear.IsSelected = false;
|
||||
rowDataToClear.IsContextMenuOpen = false;
|
||||
}
|
||||
|
||||
RefreshSelection(dgvMainMenu);
|
||||
|
@ -470,8 +453,7 @@ namespace SystemTrayMenu.Business
|
|||
{
|
||||
foreach (ListViewItemData item in dgv.Items)
|
||||
{
|
||||
RowData rowData = item.data;
|
||||
if (rowData != null && rowData.IsContextMenuOpen)
|
||||
if (item.data != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -737,10 +719,6 @@ namespace SystemTrayMenu.Business
|
|||
#endif
|
||||
dgv.SelectedItems.Add(itemData);
|
||||
}
|
||||
else if (rowData.IsContextMenuOpen || (rowData.IsMenuOpen && rowData.IsSelected))
|
||||
{
|
||||
dgv.SelectedItems.Add(itemData);
|
||||
}
|
||||
else if (rowData.IsMenuOpen)
|
||||
{
|
||||
dgv.SelectedItems.Add(itemData);
|
||||
|
@ -1070,18 +1048,20 @@ namespace SystemTrayMenu.Business
|
|||
foreach (ListViewItemData item in dgv.Items)
|
||||
{
|
||||
RowData rowData = item.data;
|
||||
if (rowData.Path?.StartsWith($"{e.OldFullPath}") ?? false)
|
||||
if (rowData.Path.StartsWith($"{e.OldFullPath}"))
|
||||
{
|
||||
string? path = rowData.Path.Replace(e.OldFullPath, e.FullPath);
|
||||
string path = rowData.Path.Replace(e.OldFullPath, e.FullPath);
|
||||
FileAttributes attr = File.GetAttributes(path);
|
||||
bool isFolder = (attr & FileAttributes.Directory) == FileAttributes.Directory;
|
||||
if (isFolder)
|
||||
{
|
||||
path = Path.GetDirectoryName(path);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
string? dirpath = Path.GetDirectoryName(path);
|
||||
if (string.IsNullOrEmpty(dirpath))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
path = dirpath;
|
||||
}
|
||||
|
||||
RowData rowDataRenamed = new(isFolder, rowData.IsAdditionalItem, 0, path);
|
||||
|
@ -1127,7 +1107,7 @@ namespace SystemTrayMenu.Business
|
|||
{
|
||||
RowData rowData = item.data;
|
||||
if (rowData.Path == e.FullPath ||
|
||||
(rowData.Path?.StartsWith($"{e.FullPath}\\") ?? false))
|
||||
rowData.Path.StartsWith($"{e.FullPath}\\"))
|
||||
{
|
||||
IconReader.RemoveIconFromCache(rowData.Path);
|
||||
rowsToRemove.Add(item);
|
||||
|
|
|
@ -176,8 +176,7 @@ namespace SystemTrayMenu.Handler
|
|||
|
||||
menu?.FocusTextBox();
|
||||
|
||||
if (!rowData.IsContextMenuOpen &&
|
||||
rowData.ContainsMenu &&
|
||||
if (rowData.IsPointingToFolder &&
|
||||
rowData.Level + 1 < MenuDefines.MenusMax)
|
||||
{
|
||||
StartLoadMenu?.Invoke(rowData);
|
||||
|
|
|
@ -31,15 +31,22 @@ namespace SystemTrayMenu.DataClasses
|
|||
|
||||
internal struct MenuData
|
||||
{
|
||||
public MenuData(int level, RowData? rowDataParent)
|
||||
public MenuData(RowData? rowDataParent)
|
||||
{
|
||||
Level = level;
|
||||
RowDataParent = rowDataParent;
|
||||
if (rowDataParent != null)
|
||||
{
|
||||
Level = rowDataParent.Level + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Level = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal int Level { get; }
|
||||
|
||||
internal RowData? RowDataParent { get; set; }
|
||||
internal RowData? RowDataParent { get; }
|
||||
|
||||
internal List<RowData> RowDatas { get; set; } = new ();
|
||||
|
||||
|
|
|
@ -7,17 +7,13 @@ namespace SystemTrayMenu.DataClasses
|
|||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using SystemTrayMenu.Utilities;
|
||||
using static SystemTrayMenu.Utilities.IconReader;
|
||||
using Menu = SystemTrayMenu.UserInterface.Menu;
|
||||
using Point = System.Windows.Point;
|
||||
|
||||
internal class RowData
|
||||
{
|
||||
private static DateTime contextMenuClosed;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RowData"/> class.
|
||||
/// (Related replace "\x00" see #171.)
|
||||
|
@ -31,87 +27,85 @@ namespace SystemTrayMenu.DataClasses
|
|||
IsFolder = isFolder;
|
||||
IsAdditionalItem = isAdditionalItem;
|
||||
Level = level;
|
||||
FileInfo = new FileInfo(path.Replace("\x00", string.Empty));
|
||||
Path = isFolder ? $@"{FileInfo.FullName}\" : FileInfo.FullName;
|
||||
FileExtension = System.IO.Path.GetExtension(Path) ?? string.Empty;
|
||||
|
||||
try
|
||||
if (FileExtension.Equals(".lnk", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
FileInfo = new FileInfo(path.Replace("\x00", string.Empty));
|
||||
Path = IsFolder ? $@"{FileInfo.FullName}\" : FileInfo.FullName;
|
||||
FileExtension = System.IO.Path.GetExtension(Path);
|
||||
IsLink = FileExtension.Equals(".lnk", StringComparison.InvariantCultureIgnoreCase);
|
||||
if (IsLink)
|
||||
ResolvedPath = FileLnk.GetResolvedFileName(Path, out bool isLinkToFolder);
|
||||
ShowOverlay = Properties.Settings.Default.ShowLinkOverlay;
|
||||
Text = System.IO.Path.GetFileNameWithoutExtension(Path);
|
||||
if (Properties.Settings.Default.ResolveLinksToFolders)
|
||||
{
|
||||
IsPointingToFolder |= isLinkToFolder || FileLnk.IsNetworkRoot(ResolvedPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ResolvedPath = Path;
|
||||
if (string.IsNullOrEmpty(FileInfo.Name))
|
||||
{
|
||||
int nameBegin = FileInfo.FullName.LastIndexOf(@"\", StringComparison.InvariantCulture) + 1;
|
||||
Text = FileInfo.FullName[nameBegin..];
|
||||
}
|
||||
else if (FileExtension.Equals(".url", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
FileExtension.Equals(".appref-ms", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
ResolvedPath = FileLnk.GetResolvedFileName(Path, out bool isLinkToFolder);
|
||||
IsLinkToFolder = isLinkToFolder || FileLnk.IsNetworkRoot(ResolvedPath);
|
||||
ShowOverlay = Properties.Settings.Default.ShowLinkOverlay;
|
||||
Text = System.IO.Path.GetFileNameWithoutExtension(Path);
|
||||
if (string.IsNullOrEmpty(ResolvedPath))
|
||||
{
|
||||
Log.Info($"Resolved path is empty: '{Path}'");
|
||||
ResolvedPath = Path;
|
||||
}
|
||||
Text = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name);
|
||||
}
|
||||
else if (!isFolder && Config.IsHideFileExtension())
|
||||
{
|
||||
Text = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
ResolvedPath = Path;
|
||||
if (string.IsNullOrEmpty(FileInfo.Name))
|
||||
{
|
||||
int nameBegin = FileInfo.FullName.LastIndexOf(@"\", StringComparison.InvariantCulture) + 1;
|
||||
Text = FileInfo.FullName[nameBegin..];
|
||||
}
|
||||
else if (FileExtension.Equals(".url", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
FileExtension.Equals(".appref-ms", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
ShowOverlay = Properties.Settings.Default.ShowLinkOverlay;
|
||||
Text = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name);
|
||||
}
|
||||
else if (!IsFolder && Config.IsHideFileExtension())
|
||||
{
|
||||
Text = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = FileInfo.Name;
|
||||
}
|
||||
Text = FileInfo.Name;
|
||||
}
|
||||
}
|
||||
|
||||
ContainsMenu = IsFolder;
|
||||
if (Properties.Settings.Default.ResolveLinksToFolders)
|
||||
{
|
||||
ContainsMenu |= IsLinkToFolder;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"path:'{path}'", ex);
|
||||
}
|
||||
IsPointingToFolder |= isFolder;
|
||||
}
|
||||
|
||||
internal Icon? Icon { get; private set; }
|
||||
|
||||
internal FileInfo? FileInfo { get; }
|
||||
internal FileInfo FileInfo { get; }
|
||||
|
||||
internal string? Path { get; }
|
||||
/// <summary>
|
||||
/// Gets the original/local path.
|
||||
/// </summary>
|
||||
internal string Path { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the resulting target path after following shortcuts or CLSIDs.
|
||||
/// </summary>
|
||||
internal string ResolvedPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether
|
||||
/// the item is actually a folder and not a file.
|
||||
/// E.g. a shortcut (.lnk) would return false.
|
||||
/// </summary>
|
||||
internal bool IsFolder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether
|
||||
/// the item is actually a folder or at least points to one.
|
||||
/// E.g. a shortcut (.lnk) could return either false or true.
|
||||
/// </summary>
|
||||
internal bool IsPointingToFolder { get; }
|
||||
|
||||
internal bool IsAdditionalItem { get; }
|
||||
|
||||
internal int Level { get; set; }
|
||||
|
||||
internal string? FileExtension { get; }
|
||||
|
||||
internal bool IsLink { get; }
|
||||
|
||||
internal string? ResolvedPath { get; }
|
||||
|
||||
internal bool IsLinkToFolder { get; }
|
||||
internal string FileExtension { get; }
|
||||
|
||||
internal bool ShowOverlay { get; }
|
||||
|
||||
internal string? Text { get; }
|
||||
|
||||
internal bool ContainsMenu { get; }
|
||||
|
||||
internal Menu? SubMenu { get; set; }
|
||||
|
||||
internal bool IsMenuOpen { get; set; }
|
||||
|
@ -120,8 +114,6 @@ namespace SystemTrayMenu.DataClasses
|
|||
|
||||
internal bool IsSelected { get; set; }
|
||||
|
||||
internal bool IsContextMenuOpen { get; set; }
|
||||
|
||||
internal bool HiddenEntry { get; set; }
|
||||
|
||||
internal int RowIndex { get; set; }
|
||||
|
@ -130,17 +122,17 @@ namespace SystemTrayMenu.DataClasses
|
|||
|
||||
internal void ReadIcon(bool updateIconInBackground)
|
||||
{
|
||||
if (IsFolder || IsLinkToFolder)
|
||||
bool loading;
|
||||
if (IsPointingToFolder)
|
||||
{
|
||||
Icon = GetFolderIconWithCache(Path, ShowOverlay, updateIconInBackground, Level == 0, out bool loading);
|
||||
IconLoading = loading;
|
||||
Icon = GetFolderIconWithCache(Path, ShowOverlay, updateIconInBackground, Level == 0, out loading);
|
||||
}
|
||||
else
|
||||
{
|
||||
Icon = GetFileIconWithCache(Path, ResolvedPath, ShowOverlay, updateIconInBackground, Level == 0, out bool loading);
|
||||
IconLoading = loading;
|
||||
Icon = GetFileIconWithCache(Path, ResolvedPath, ShowOverlay, updateIconInBackground, Level == 0, out loading);
|
||||
}
|
||||
|
||||
IconLoading = loading;
|
||||
if (!IconLoading)
|
||||
{
|
||||
if (Icon == null)
|
||||
|
@ -154,57 +146,20 @@ namespace SystemTrayMenu.DataClasses
|
|||
}
|
||||
}
|
||||
|
||||
internal void MouseDown(ListView dgv, MouseButtonEventArgs e)
|
||||
internal void OpenShellContextMenu(Point position)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
ShellContextMenu ctxMnu = new();
|
||||
if (IsPointingToFolder)
|
||||
{
|
||||
IsClicking = true;
|
||||
DirectoryInfo[] dir = new DirectoryInfo[1];
|
||||
dir[0] = new DirectoryInfo(Path);
|
||||
ctxMnu.ShowContextMenu(dir, position);
|
||||
}
|
||||
else if (e.RightButton == MouseButtonState.Pressed &&
|
||||
FileInfo != null && Path != null &&
|
||||
dgv != null && dgv.Items.Count > RowIndex &&
|
||||
(DateTime.Now - contextMenuClosed).TotalMilliseconds > 200)
|
||||
else
|
||||
{
|
||||
IsContextMenuOpen = true;
|
||||
CreateAndShowShellContextMenu();
|
||||
void CreateAndShowShellContextMenu()
|
||||
{
|
||||
ShellContextMenu ctxMnu = new();
|
||||
Window window = dgv.GetParentWindow();
|
||||
var position = Mouse.GetPosition(window);
|
||||
position.Offset(window.Left, window.Top);
|
||||
if (ContainsMenu)
|
||||
{
|
||||
DirectoryInfo[] dir = new DirectoryInfo[1];
|
||||
dir[0] = new DirectoryInfo(Path);
|
||||
ctxMnu.ShowContextMenu(dir, position);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileInfo[] arrFI = new FileInfo[1];
|
||||
arrFI[0] = FileInfo;
|
||||
ctxMnu.ShowContextMenu(arrFI, position);
|
||||
}
|
||||
}
|
||||
|
||||
TriggerFileWatcherChangeWorkaround();
|
||||
void TriggerFileWatcherChangeWorkaround()
|
||||
{
|
||||
try
|
||||
{
|
||||
string? parentFolder = System.IO.Path.GetDirectoryName(Path);
|
||||
|
||||
// Assume folder is not null as failure will be catched any ways
|
||||
Directory.GetFiles(parentFolder!);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"{nameof(TriggerFileWatcherChangeWorkaround)} '{Path}'", ex);
|
||||
}
|
||||
}
|
||||
|
||||
IsContextMenuOpen = false;
|
||||
contextMenuClosed = DateTime.Now;
|
||||
FileInfo[] arrFI = new FileInfo[1];
|
||||
arrFI[0] = FileInfo;
|
||||
ctxMnu.ShowContextMenu(arrFI, position);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,11 +168,11 @@ namespace SystemTrayMenu.DataClasses
|
|||
IsClicking = false;
|
||||
doCloseAfterOpen = false;
|
||||
|
||||
if (clickCount == -1 ||
|
||||
if (!IsPointingToFolder)
|
||||
{
|
||||
if (clickCount == -1 ||
|
||||
(clickCount == 1 && Properties.Settings.Default.OpenItemWithOneClick) ||
|
||||
(clickCount == 2 && !Properties.Settings.Default.OpenItemWithOneClick))
|
||||
{
|
||||
if (!ContainsMenu && Path != null && ResolvedPath != null)
|
||||
{
|
||||
string? workingDirectory = System.IO.Path.GetDirectoryName(ResolvedPath);
|
||||
Log.ProcessStart(Path, string.Empty, false, workingDirectory, true, ResolvedPath);
|
||||
|
@ -227,12 +182,11 @@ namespace SystemTrayMenu.DataClasses
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (clickCount == -1 ||
|
||||
else
|
||||
{
|
||||
if (clickCount == -1 ||
|
||||
(clickCount == 1 && Properties.Settings.Default.OpenDirectoryWithOneClick) ||
|
||||
(clickCount == 2 && !Properties.Settings.Default.OpenDirectoryWithOneClick))
|
||||
{
|
||||
if (Path != null && ContainsMenu)
|
||||
{
|
||||
Log.ProcessStart(Path);
|
||||
if (!Properties.Settings.Default.StaysOpenWhenItemClicked)
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace SystemTrayMenu.Helpers
|
|||
else if (Properties.Settings.Default.SortByTypeAndDate)
|
||||
{
|
||||
rowDatas = rowDatas.OrderByDescending(x => x.IsFolder)
|
||||
.ThenByDescending(x => x.FileInfo?.LastWriteTime).ToList();
|
||||
.ThenByDescending(x => x.FileInfo.LastWriteTime).ToList();
|
||||
}
|
||||
else if (Properties.Settings.Default.SortByFileExtensionAndName)
|
||||
{
|
||||
|
@ -110,7 +110,7 @@ namespace SystemTrayMenu.Helpers
|
|||
}
|
||||
else if (Properties.Settings.Default.SortByDate)
|
||||
{
|
||||
rowDatas = rowDatas.OrderByDescending(x => x.FileInfo?.LastWriteTime).ToList();
|
||||
rowDatas = rowDatas.OrderByDescending(x => x.FileInfo.LastWriteTime).ToList();
|
||||
}
|
||||
|
||||
return rowDatas;
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace SystemTrayMenu.Helpers
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using SystemTrayMenu.DataClasses;
|
||||
using SystemTrayMenu.UserInterface;
|
||||
using SystemTrayMenu.Utilities;
|
||||
|
||||
|
@ -32,33 +31,9 @@ namespace SystemTrayMenu.Helpers
|
|||
}
|
||||
}
|
||||
|
||||
public static void DragDrop(object sender, DragEventArgs e)
|
||||
public static void DragDrop(object? sender, DragEventArgs e)
|
||||
{
|
||||
Menu menu = (Menu)sender;
|
||||
string path;
|
||||
if (menu != null)
|
||||
{
|
||||
RowData? rowData = menu.RowDataParent;
|
||||
if (rowData != null)
|
||||
{
|
||||
string? resolvedPath = rowData.ResolvedPath;
|
||||
if (string.IsNullOrEmpty(resolvedPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
path = resolvedPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
path = Config.Path;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
path = Config.Path;
|
||||
}
|
||||
|
||||
string path = ((Menu?)sender)?.RowDataParent?.ResolvedPath ?? Config.Path;
|
||||
object data = e.Data.GetData("UniformResourceLocator");
|
||||
if (data is not MemoryStream ms)
|
||||
{
|
||||
|
|
|
@ -93,19 +93,19 @@ namespace SystemTrayMenu.UserInterface
|
|||
|
||||
folderPath = path;
|
||||
RowDataParent = menuData.RowDataParent;
|
||||
Level = menuData.Level;
|
||||
if (Level == 0)
|
||||
if (RowDataParent == null)
|
||||
{
|
||||
// This will be a main menu
|
||||
Level = 0;
|
||||
|
||||
// Use Main Menu DPI for all further calculations
|
||||
Scaling.CalculateFactorByDpi(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This will be a submenu
|
||||
if (RowDataParent != null)
|
||||
{
|
||||
RowDataParent.SubMenu = this;
|
||||
}
|
||||
// This will be a sub menu
|
||||
Level = RowDataParent.Level + 1;
|
||||
RowDataParent.SubMenu = this;
|
||||
|
||||
buttonOpenFolder.Visibility = Visibility.Collapsed;
|
||||
buttonSettings.Visibility = Visibility.Collapsed;
|
||||
|
@ -450,7 +450,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
if (!(rowData.IsAdditionalItem && Settings.Default.ShowOnlyAsSearchResult))
|
||||
{
|
||||
if (rowData.ContainsMenu)
|
||||
if (rowData.IsPointingToFolder)
|
||||
{
|
||||
foldersCount++;
|
||||
}
|
||||
|
@ -1262,7 +1262,17 @@ namespace SystemTrayMenu.UserInterface
|
|||
|
||||
CellMouseDown?.Invoke(dgv, itemData, e);
|
||||
|
||||
itemData.data.MouseDown(dgv, e);
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
itemData.data.IsClicking = true;
|
||||
}
|
||||
|
||||
if (e.RightButton == MouseButtonState.Pressed)
|
||||
{
|
||||
var position = Mouse.GetPosition(this);
|
||||
position.Offset(Left, Top);
|
||||
itemData.data.OpenShellContextMenu(position);
|
||||
}
|
||||
}
|
||||
|
||||
private void ListViewItem_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
|
|
|
@ -1,98 +1,106 @@
|
|||
// <copyright file="FileLnk.cs" company="PlaceholderCompany">
|
||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace SystemTrayMenu.Utilities
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Shell32;
|
||||
|
||||
internal class FileLnk
|
||||
{
|
||||
public static string GetResolvedFileName(string shortcutFilename, out bool isFolder)
|
||||
{
|
||||
bool isFolderByShell = false;
|
||||
string resolvedFilename = string.Empty;
|
||||
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
|
||||
{
|
||||
resolvedFilename = GetShortcutFileNamePath(shortcutFilename, out isFolderByShell);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread staThread = new(new ParameterizedThreadStart(StaThreadMethod));
|
||||
void StaThreadMethod(object? obj)
|
||||
{
|
||||
resolvedFilename = GetShortcutFileNamePath(shortcutFilename, out isFolderByShell);
|
||||
}
|
||||
|
||||
staThread.SetApartmentState(ApartmentState.STA);
|
||||
staThread.Start(shortcutFilename);
|
||||
staThread.Join();
|
||||
}
|
||||
|
||||
isFolder = isFolderByShell;
|
||||
return resolvedFilename;
|
||||
}
|
||||
|
||||
public static bool IsNetworkRoot(string path)
|
||||
{
|
||||
return path.StartsWith(@"\\", StringComparison.InvariantCulture) &&
|
||||
!path[2..].Contains('\\', StringComparison.InvariantCulture);
|
||||
}
|
||||
|
||||
private static string GetShortcutFileNamePath(object shortcutFilename, out bool isFolder)
|
||||
{
|
||||
string resolvedFilename = string.Empty;
|
||||
isFolder = false;
|
||||
try
|
||||
{
|
||||
string? pathOnly = Path.GetDirectoryName((string)shortcutFilename);
|
||||
string? filenameOnly = Path.GetFileName((string)shortcutFilename);
|
||||
|
||||
Shell shell = new();
|
||||
Folder folder = shell.NameSpace(pathOnly);
|
||||
if (folder == null)
|
||||
{
|
||||
Log.Info($"{nameof(GetShortcutFileNamePath)} folder == null for path:'{shortcutFilename}'");
|
||||
return resolvedFilename;
|
||||
}
|
||||
|
||||
FolderItem folderItem = folder.ParseName(filenameOnly);
|
||||
if (folderItem == null)
|
||||
{
|
||||
Log.Info($"{nameof(GetShortcutFileNamePath)} folderItem == null for path:'{shortcutFilename}'");
|
||||
return resolvedFilename;
|
||||
}
|
||||
|
||||
ShellLinkObject link = (ShellLinkObject)folderItem.GetLink;
|
||||
isFolder = link.Target.IsFolder;
|
||||
if (string.IsNullOrEmpty(link.Path))
|
||||
{
|
||||
// https://github.com/Hofknecht/SystemTrayMenu/issues/242
|
||||
// do not set CLSID key (GUID) shortcuts as resolvedFilename
|
||||
if (!link.Target.Path.Contains("::{"))
|
||||
{
|
||||
resolvedFilename = link.Target.Path;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedFilename = link.Path;
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
// https://stackoverflow.com/questions/2934420/why-do-i-get-e-accessdenied-when-reading-public-shortcuts-through-shell32
|
||||
// e.g. Administrative Tools\Component Services.lnk which can not be resolved, do not spam the logfile in this case
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"shortcutFilename:'{shortcutFilename}'", ex);
|
||||
}
|
||||
|
||||
return resolvedFilename;
|
||||
}
|
||||
}
|
||||
// <copyright file="FileLnk.cs" company="PlaceholderCompany">
|
||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace SystemTrayMenu.Utilities
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Shell32;
|
||||
|
||||
internal class FileLnk
|
||||
{
|
||||
public static string GetResolvedFileName(string shortcutFilename, out bool isFolder)
|
||||
{
|
||||
bool isFolderByShell = false;
|
||||
string resolvedFilename = string.Empty;
|
||||
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
|
||||
{
|
||||
resolvedFilename = GetShortcutFileNamePath(shortcutFilename, out isFolderByShell);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread staThread = new(new ParameterizedThreadStart(StaThreadMethod));
|
||||
void StaThreadMethod(object? obj)
|
||||
{
|
||||
resolvedFilename = GetShortcutFileNamePath(shortcutFilename, out isFolderByShell);
|
||||
}
|
||||
|
||||
staThread.SetApartmentState(ApartmentState.STA);
|
||||
staThread.Start(shortcutFilename);
|
||||
staThread.Join();
|
||||
}
|
||||
|
||||
// If path cannot be resolved, write log message and give back original path
|
||||
if (string.IsNullOrEmpty(resolvedFilename))
|
||||
{
|
||||
Log.Info($"Resolved path is empty: '{shortcutFilename}'");
|
||||
resolvedFilename = shortcutFilename;
|
||||
}
|
||||
|
||||
isFolder = isFolderByShell;
|
||||
|
||||
return resolvedFilename;
|
||||
}
|
||||
|
||||
public static bool IsNetworkRoot(string path)
|
||||
{
|
||||
return path.StartsWith(@"\\", StringComparison.InvariantCulture) &&
|
||||
!path[2..].Contains('\\', StringComparison.InvariantCulture);
|
||||
}
|
||||
|
||||
private static string GetShortcutFileNamePath(object shortcutFilename, out bool isFolder)
|
||||
{
|
||||
string resolvedFilename = string.Empty;
|
||||
isFolder = false;
|
||||
try
|
||||
{
|
||||
string? pathOnly = Path.GetDirectoryName((string)shortcutFilename);
|
||||
string? filenameOnly = Path.GetFileName((string)shortcutFilename);
|
||||
|
||||
Shell shell = new();
|
||||
Folder folder = shell.NameSpace(pathOnly);
|
||||
if (folder == null)
|
||||
{
|
||||
Log.Info($"{nameof(GetShortcutFileNamePath)} folder == null for path:'{shortcutFilename}'");
|
||||
return resolvedFilename;
|
||||
}
|
||||
|
||||
FolderItem folderItem = folder.ParseName(filenameOnly);
|
||||
if (folderItem == null)
|
||||
{
|
||||
Log.Info($"{nameof(GetShortcutFileNamePath)} folderItem == null for path:'{shortcutFilename}'");
|
||||
return resolvedFilename;
|
||||
}
|
||||
|
||||
ShellLinkObject link = (ShellLinkObject)folderItem.GetLink;
|
||||
isFolder = link.Target.IsFolder;
|
||||
if (string.IsNullOrEmpty(link.Path))
|
||||
{
|
||||
// https://github.com/Hofknecht/SystemTrayMenu/issues/242
|
||||
// do not set CLSID key (GUID) shortcuts as resolvedFilename
|
||||
if (!link.Target.Path.Contains("::{"))
|
||||
{
|
||||
resolvedFilename = link.Target.Path;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedFilename = link.Path;
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
// https://stackoverflow.com/questions/2934420/why-do-i-get-e-accessdenied-when-reading-public-shortcuts-through-shell32
|
||||
// e.g. Administrative Tools\Component Services.lnk which can not be resolved, do not spam the logfile in this case
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"shortcutFilename:'{shortcutFilename}'", ex);
|
||||
}
|
||||
|
||||
return resolvedFilename;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -55,60 +55,8 @@ namespace SystemTrayMenu.Utilities
|
|||
}
|
||||
|
||||
public static Icon? GetFileIconWithCache(
|
||||
string? path,
|
||||
string? resolvedPath,
|
||||
bool linkOverlay,
|
||||
bool updateIconInBackground,
|
||||
bool checkPersistentFirst,
|
||||
out bool loading,
|
||||
string keyPath = "")
|
||||
{
|
||||
loading = false;
|
||||
|
||||
Icon? icon = null;
|
||||
if (path != null)
|
||||
{
|
||||
string extension = Path.GetExtension(path);
|
||||
IconSize size = IconSize.Small;
|
||||
if (Scaling.Factor >= 1.25f ||
|
||||
Scaling.FactorByDpi >= 1.25f ||
|
||||
Properties.Settings.Default.IconSizeInPercent / 100f >= 1.25f)
|
||||
{
|
||||
size = IconSize.Large;
|
||||
}
|
||||
|
||||
string key = path;
|
||||
if (!string.IsNullOrEmpty(keyPath))
|
||||
{
|
||||
key = keyPath;
|
||||
}
|
||||
|
||||
if (IsExtensionWithSameIcon(extension))
|
||||
{
|
||||
key = extension + linkOverlay;
|
||||
}
|
||||
|
||||
if (!DictIconCache(checkPersistentFirst).TryGetValue(key, out icon) &&
|
||||
!DictIconCache(!checkPersistentFirst).TryGetValue(key, out icon))
|
||||
{
|
||||
icon = Resources.StaticResources.LoadingIcon;
|
||||
loading = true;
|
||||
if (updateIconInBackground)
|
||||
{
|
||||
new Thread(UpdateIconInBackground).Start();
|
||||
void UpdateIconInBackground()
|
||||
{
|
||||
DictIconCache(checkPersistentFirst).GetOrAdd(key, GetIconSTA(path, resolvedPath, linkOverlay, size, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
public static Icon? GetFolderIconWithCache(
|
||||
string? path,
|
||||
string path,
|
||||
string resolvedPath,
|
||||
bool linkOverlay,
|
||||
bool updateIconInBackground,
|
||||
bool checkPersistentFirst,
|
||||
|
@ -117,43 +65,36 @@ namespace SystemTrayMenu.Utilities
|
|||
loading = false;
|
||||
|
||||
Icon? icon = null;
|
||||
if (path != null)
|
||||
string key;
|
||||
string extension = Path.GetExtension(path);
|
||||
if (IsExtensionWithSameIcon(extension))
|
||||
{
|
||||
IconSize size = IconSize.Small;
|
||||
if (Scaling.Factor >= 1.25f ||
|
||||
Scaling.FactorByDpi >= 1.25f ||
|
||||
Properties.Settings.Default.IconSizeInPercent / 100f >= 1.25f)
|
||||
{
|
||||
// IconSize.Large returns another folder icon than windows explorer
|
||||
size = IconSize.Large;
|
||||
}
|
||||
key = extension + linkOverlay;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = path;
|
||||
}
|
||||
|
||||
string key = path;
|
||||
if (!DictIconCache(checkPersistentFirst).TryGetValue(key, out icon) &&
|
||||
!DictIconCache(!checkPersistentFirst).TryGetValue(key, out icon))
|
||||
if (!DictIconCache(checkPersistentFirst).TryGetValue(key, out icon) &&
|
||||
!DictIconCache(!checkPersistentFirst).TryGetValue(key, out icon))
|
||||
{
|
||||
icon = Resources.StaticResources.LoadingIcon;
|
||||
loading = true;
|
||||
if (updateIconInBackground)
|
||||
{
|
||||
icon = Resources.StaticResources.LoadingIcon;
|
||||
loading = true;
|
||||
|
||||
if (updateIconInBackground)
|
||||
IconSize size = IconSize.Small;
|
||||
if (Scaling.Factor >= 1.25f ||
|
||||
Scaling.FactorByDpi >= 1.25f ||
|
||||
Properties.Settings.Default.IconSizeInPercent / 100f >= 1.25f)
|
||||
{
|
||||
if (IsPreloading)
|
||||
{
|
||||
DictIconCache(checkPersistentFirst).GetOrAdd(key, GetFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
new Thread(UpdateIconInBackground).Start();
|
||||
void UpdateIconInBackground()
|
||||
{
|
||||
DictIconCache(checkPersistentFirst).GetOrAdd(key, GetFolder);
|
||||
}
|
||||
}
|
||||
size = IconSize.Large;
|
||||
}
|
||||
|
||||
Icon? GetFolder(string keyExtension)
|
||||
{
|
||||
return GetIconSTA(path, path, linkOverlay, size, true);
|
||||
}
|
||||
new Thread(UpdateIconInBackground).Start();
|
||||
void UpdateIconInBackground()
|
||||
{
|
||||
DictIconCache(checkPersistentFirst).GetOrAdd(key, GetIconSTA(path, resolvedPath, linkOverlay, size, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +102,58 @@ namespace SystemTrayMenu.Utilities
|
|||
return icon;
|
||||
}
|
||||
|
||||
public static Icon? GetIconSTA(string path, string? resolvedPath, bool linkOverlay, IconSize size, bool isFolder)
|
||||
public static Icon? GetFolderIconWithCache(
|
||||
string path,
|
||||
bool linkOverlay,
|
||||
bool updateIconInBackground,
|
||||
bool checkPersistentFirst,
|
||||
out bool loading)
|
||||
{
|
||||
loading = false;
|
||||
|
||||
Icon? icon = null;
|
||||
string key = path;
|
||||
if (!DictIconCache(checkPersistentFirst).TryGetValue(key, out icon) &&
|
||||
!DictIconCache(!checkPersistentFirst).TryGetValue(key, out icon))
|
||||
{
|
||||
icon = Resources.StaticResources.LoadingIcon;
|
||||
loading = true;
|
||||
|
||||
if (updateIconInBackground)
|
||||
{
|
||||
IconSize size = IconSize.Small;
|
||||
if (Scaling.Factor >= 1.25f ||
|
||||
Scaling.FactorByDpi >= 1.25f ||
|
||||
Properties.Settings.Default.IconSizeInPercent / 100f >= 1.25f)
|
||||
{
|
||||
// IconSize.Large returns another folder icon than windows explorer
|
||||
size = IconSize.Large;
|
||||
}
|
||||
|
||||
if (IsPreloading)
|
||||
{
|
||||
DictIconCache(checkPersistentFirst).GetOrAdd(key, GetFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
new Thread(UpdateIconInBackground).Start();
|
||||
void UpdateIconInBackground()
|
||||
{
|
||||
DictIconCache(checkPersistentFirst).GetOrAdd(key, GetFolder);
|
||||
}
|
||||
}
|
||||
|
||||
Icon? GetFolder(string keyExtension)
|
||||
{
|
||||
return GetIconSTA(path, path, linkOverlay, size, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
public static Icon? GetIconSTA(string path, string resolvedPath, bool linkOverlay, IconSize size, bool isFolder)
|
||||
{
|
||||
Icon? icon = null;
|
||||
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
|
||||
|
@ -217,7 +209,7 @@ namespace SystemTrayMenu.Utilities
|
|||
return isExtensionWithSameIcon;
|
||||
}
|
||||
|
||||
private static Icon? GetIcon(string path, string? resolvedPath, bool linkOverlay, IconSize size, bool isFolder)
|
||||
private static Icon? GetIcon(string path, string resolvedPath, bool linkOverlay, IconSize size, bool isFolder)
|
||||
{
|
||||
Icon? icon;
|
||||
if (Path.GetExtension(path).Equals(".ico", StringComparison.InvariantCultureIgnoreCase))
|
||||
|
|
|
@ -53,11 +53,11 @@ namespace SystemTrayMenu.Utilities
|
|||
}
|
||||
}
|
||||
|
||||
internal static void ReadHiddenAttributes(string? path, out bool hasHiddenFlag, out bool isDirectoryToHide)
|
||||
internal static void ReadHiddenAttributes(string path, out bool hasHiddenFlag, out bool isDirectoryToHide)
|
||||
{
|
||||
isDirectoryToHide = false;
|
||||
hasHiddenFlag = false;
|
||||
if (path == null || path.Length >= 260)
|
||||
if (path.Length >= 260)
|
||||
{
|
||||
Log.Info($"path too long (>=260):'{path}'");
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue