mirror of
https://github.com/Hofknecht/SystemTrayMenu.git
synced 2024-05-02 11:32:24 +12:00
This commit is contained in:
parent
bcb537d1ee
commit
7c253fa28a
|
@ -30,6 +30,8 @@ namespace SystemTrayMenu.Business
|
|||
private readonly DgvMouseRow dgvMouseRow = new();
|
||||
private readonly WaitToLoadMenu waitToOpenMenu = new();
|
||||
private readonly KeyboardInput keyboardInput;
|
||||
private readonly List<FileSystemWatcher> watchers = new();
|
||||
private readonly List<FileSystemEventArgs> watcherHistory = new();
|
||||
private readonly Timer timerShowProcessStartedAsLoadingIcon = new();
|
||||
private readonly Timer timerStillActiveCheck = new();
|
||||
private readonly WaitLeave waitLeave = new(Properties.Settings.Default.TimeUntilCloses);
|
||||
|
@ -43,12 +45,12 @@ namespace SystemTrayMenu.Business
|
|||
private int dragSwipeScrollingStartRowIndex = -1;
|
||||
private bool isDraggingSwipeScrolling;
|
||||
private bool isDragSwipeScrolled;
|
||||
private bool hideSubmenuDuringRefreshSearch;
|
||||
|
||||
public Menus()
|
||||
{
|
||||
workerMainMenu.WorkerSupportsCancellation = true;
|
||||
workerMainMenu.DoWork += LoadMenu;
|
||||
|
||||
workerMainMenu.RunWorkerCompleted += LoadMainMenuCompleted;
|
||||
void LoadMainMenuCompleted(object sender, RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
|
@ -90,8 +92,8 @@ namespace SystemTrayMenu.Business
|
|||
{
|
||||
workerMainMenu.DoWork -= LoadMenu;
|
||||
menus[0] = Create(menuData, Path.GetFileName(Config.Path));
|
||||
menus[0].HandleCreated += (s, e) => ExecuteWatcherHistory();
|
||||
IconReader.MainPreload = false;
|
||||
|
||||
if (showMenuAfterMainPreload)
|
||||
{
|
||||
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
|
||||
|
@ -135,8 +137,8 @@ namespace SystemTrayMenu.Business
|
|||
Config.SetFolderByUser();
|
||||
AppRestart.ByConfigChange();
|
||||
break;
|
||||
case MenuDataValidity.AbortedOrUnknown:
|
||||
Log.Info("MenuDataValidity.AbortedOrUnknown");
|
||||
case MenuDataValidity.Undefined:
|
||||
Log.Info($"{nameof(MenuDataValidity)}.{nameof(MenuDataValidity.Undefined)}");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -162,23 +164,21 @@ namespace SystemTrayMenu.Business
|
|||
void StartLoadMenu(RowData rowData)
|
||||
{
|
||||
if (menus[0].IsUsable &&
|
||||
(menus[rowData.MenuLevel + 1] == null ||
|
||||
menus[rowData.MenuLevel + 1].Tag as RowData != rowData))
|
||||
(menus[rowData.Level + 1] == null ||
|
||||
menus[rowData.Level + 1].Tag as RowData != rowData))
|
||||
{
|
||||
CreateAndShowLoadingMenu(rowData);
|
||||
void CreateAndShowLoadingMenu(RowData rowData)
|
||||
{
|
||||
MenuData menuDataLoading = new()
|
||||
MenuData menuDataLoading = new(rowData.Level + 1)
|
||||
{
|
||||
RowDatas = new List<RowData>(),
|
||||
Validity = MenuDataValidity.Valid,
|
||||
Level = rowData.MenuLevel + 1,
|
||||
};
|
||||
|
||||
Menu menuLoading = Create(menuDataLoading, Path.GetFileName(rowData.TargetFilePathOrig));
|
||||
Menu menuLoading = Create(menuDataLoading, Path.GetFileName(rowData.Path));
|
||||
menuLoading.IsLoadingMenu = true;
|
||||
AdjustMenusSizeAndLocation();
|
||||
menus[rowData.MenuLevel + 1] = menuLoading;
|
||||
menus[rowData.Level + 1] = menuLoading;
|
||||
menuLoading.Tag = menuDataLoading.RowDataParent = rowData;
|
||||
menuDataLoading.RowDataParent.SubMenu = menuLoading;
|
||||
menuLoading.SetTypeLoading();
|
||||
|
@ -216,7 +216,7 @@ namespace SystemTrayMenu.Business
|
|||
closedLoadingMenu = true;
|
||||
}
|
||||
|
||||
if (menuData.Validity != MenuDataValidity.AbortedOrUnknown &&
|
||||
if (menuData.Validity != MenuDataValidity.Undefined &&
|
||||
menus[0].IsUsable)
|
||||
{
|
||||
Menu menu = Create(menuData);
|
||||
|
@ -270,20 +270,6 @@ namespace SystemTrayMenu.Business
|
|||
}
|
||||
|
||||
waitToOpenMenu.MouseEnterOk += MouseEnterOk;
|
||||
void MouseEnterOk(DataGridView dgv, int rowIndex)
|
||||
{
|
||||
if (menus[0].IsUsable)
|
||||
{
|
||||
if (keyboardInput.InUse)
|
||||
{
|
||||
keyboardInput.ClearIsSelectedByKey();
|
||||
keyboardInput.InUse = false;
|
||||
}
|
||||
|
||||
keyboardInput.Select(dgv, rowIndex, false);
|
||||
}
|
||||
}
|
||||
|
||||
dgvMouseRow.RowMouseEnter += waitToOpenMenu.MouseEnter;
|
||||
dgvMouseRow.RowMouseLeave += waitToOpenMenu.MouseLeave;
|
||||
dgvMouseRow.RowMouseLeave += Dgv_RowMouseLeave;
|
||||
|
@ -316,6 +302,37 @@ namespace SystemTrayMenu.Business
|
|||
}
|
||||
|
||||
waitLeave.LeaveTriggered += FadeHalfOrOutIfNeeded;
|
||||
|
||||
CreateWatcher(Config.Path, false);
|
||||
foreach (var pathAndFlags in MenusHelpers.GetAddionalPathsForMainMenu())
|
||||
{
|
||||
CreateWatcher(pathAndFlags.Path, pathAndFlags.Recursive);
|
||||
}
|
||||
|
||||
void CreateWatcher(string path, bool recursiv)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileSystemWatcher watcher = new FileSystemWatcher();
|
||||
watcher.Path = path;
|
||||
watcher.NotifyFilter = NotifyFilters.Attributes |
|
||||
NotifyFilters.DirectoryName |
|
||||
NotifyFilters.FileName |
|
||||
NotifyFilters.LastWrite;
|
||||
watcher.Filter = "*.*";
|
||||
watcher.Created += WatcherProcessItem;
|
||||
watcher.Deleted += WatcherProcessItem;
|
||||
watcher.Renamed += WatcherRenamed;
|
||||
watcher.Changed += WatcherChanged;
|
||||
watcher.IncludeSubdirectories = recursiv;
|
||||
watcher.EnableRaisingEvents = true;
|
||||
watchers.Add(watcher);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"Failed to {nameof(CreateWatcher)}: {path}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal event EventHandlerEmpty LoadStarted;
|
||||
|
@ -349,237 +366,44 @@ namespace SystemTrayMenu.Business
|
|||
IconReader.Dispose();
|
||||
DisposeMenu(menus[0]);
|
||||
dgvMouseRow.Dispose();
|
||||
foreach (FileSystemWatcher watcher in watchers)
|
||||
{
|
||||
watcher.Created -= WatcherProcessItem;
|
||||
watcher.Deleted -= WatcherProcessItem;
|
||||
watcher.Renamed -= WatcherRenamed;
|
||||
watcher.Changed -= WatcherChanged;
|
||||
watcher.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
internal static MenuData GetData(BackgroundWorker worker, string path, int level)
|
||||
{
|
||||
MenuData menuData = new()
|
||||
MenuData menuData = new(level);
|
||||
if (worker?.CancellationPending == true || string.IsNullOrEmpty(path))
|
||||
{
|
||||
RowDatas = new List<RowData>(),
|
||||
Validity = MenuDataValidity.AbortedOrUnknown,
|
||||
Level = level,
|
||||
};
|
||||
|
||||
string[] directoriesToAddToMainMenu = Array.Empty<string>();
|
||||
string[] filesToAddToMainMenu = Array.Empty<string>();
|
||||
if (level == 0)
|
||||
{
|
||||
AddFoldersToMainMenu(ref directoriesToAddToMainMenu, ref filesToAddToMainMenu);
|
||||
return menuData;
|
||||
}
|
||||
|
||||
if (!worker.CancellationPending)
|
||||
MenusHelpers.GetItemsForMainMenu(worker, path, ref menuData);
|
||||
if (worker?.CancellationPending == true)
|
||||
{
|
||||
string[] directories = Array.Empty<string>();
|
||||
bool isSharedDirectory = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
Log.Info($"path is null or empty");
|
||||
}
|
||||
else if (FileLnk.IsNetworkRoot(path))
|
||||
{
|
||||
isSharedDirectory = true;
|
||||
directories = GetDirectoriesInNetworkLocation(path);
|
||||
static string[] GetDirectoriesInNetworkLocation(string networkLocationRootPath)
|
||||
{
|
||||
List<string> directories = new();
|
||||
Process cmd = new();
|
||||
cmd.StartInfo.FileName = "cmd.exe";
|
||||
cmd.StartInfo.RedirectStandardInput = true;
|
||||
cmd.StartInfo.RedirectStandardOutput = true;
|
||||
cmd.StartInfo.CreateNoWindow = true;
|
||||
cmd.StartInfo.UseShellExecute = false;
|
||||
cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
cmd.Start();
|
||||
cmd.StandardInput.WriteLine($"net view {networkLocationRootPath}");
|
||||
cmd.StandardInput.Flush();
|
||||
cmd.StandardInput.Close();
|
||||
|
||||
string output = cmd.StandardOutput.ReadToEnd();
|
||||
|
||||
cmd.WaitForExit();
|
||||
cmd.Close();
|
||||
|
||||
bool resolvedSomething = false;
|
||||
|
||||
List<string> lines = output
|
||||
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
if (lines.Count > 8)
|
||||
{
|
||||
foreach (string line in lines.Skip(6).SkipLast(2))
|
||||
{
|
||||
int indexOfFirstSpace = line.IndexOf(" ", StringComparison.InvariantCulture);
|
||||
if (indexOfFirstSpace > 0)
|
||||
{
|
||||
string directory = Path.Combine(
|
||||
networkLocationRootPath,
|
||||
line[..indexOfFirstSpace]);
|
||||
|
||||
directories.Add(directory);
|
||||
resolvedSomething = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!resolvedSomething)
|
||||
{
|
||||
Log.Info($"Could not resolve network root folder: {networkLocationRootPath} , output:{output}");
|
||||
}
|
||||
|
||||
return directories.ToArray();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
directories = Directory.GetDirectories(path);
|
||||
directories = directories.Concat(directoriesToAddToMainMenu).ToArray();
|
||||
}
|
||||
|
||||
if (Properties.Settings.Default.SortByTypeAndNameWindowsExplorerSort)
|
||||
{
|
||||
Array.Sort(directories, new WindowsExplorerSort());
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
Log.Warn($"path:'{path}'", ex);
|
||||
menuData.Validity = MenuDataValidity.NoAccess;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"path:'{path}'", ex);
|
||||
}
|
||||
|
||||
foreach (string directoryWithIllegalCharacters in directories)
|
||||
{
|
||||
if (worker != null && worker.CancellationPending)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// https://github.com/Hofknecht/SystemTrayMenu/issues/171
|
||||
string directory = directoryWithIllegalCharacters.Replace("\x00", string.Empty);
|
||||
|
||||
bool hiddenEntry = false;
|
||||
if (!isSharedDirectory &&
|
||||
FolderOptions.IsHidden(directory, ref hiddenEntry))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RowData rowData = ReadRowData(directory, false, true);
|
||||
rowData.HiddenEntry = hiddenEntry;
|
||||
string resolvedLnkPath = string.Empty;
|
||||
rowData.ReadIconOrResolveLinkAndReadIcon(true, ref resolvedLnkPath, level);
|
||||
rowData.MenuLevel = level;
|
||||
menuData.RowDatas.Add(rowData);
|
||||
}
|
||||
|
||||
if (Properties.Settings.Default.SortByTypeAndDate)
|
||||
{
|
||||
menuData.RowDatas = menuData.RowDatas.OrderBy(x => x.FileInfo.LastWriteTime).Reverse().ToList();
|
||||
}
|
||||
return menuData;
|
||||
}
|
||||
|
||||
if (!worker.CancellationPending)
|
||||
MenusHelpers.GetAddionalItemsForMainMenu(ref menuData);
|
||||
if (worker?.CancellationPending == true)
|
||||
{
|
||||
string[] files = Array.Empty<string>();
|
||||
List<RowData> rowDatasFiles = new List<RowData>();
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
Log.Info($"path is null or empty");
|
||||
}
|
||||
else if (!FileLnk.IsNetworkRoot(path))
|
||||
{
|
||||
files = DirectoryBySearchPattern.GetFiles(path, Config.SearchPattern);
|
||||
files = files.Concat(filesToAddToMainMenu).ToArray();
|
||||
}
|
||||
|
||||
if (Properties.Settings.Default.SortByTypeAndNameWindowsExplorerSort)
|
||||
{
|
||||
Array.Sort(files, new WindowsExplorerSort());
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
Log.Warn($"path:'{path}'", ex);
|
||||
menuData.Validity = MenuDataValidity.NoAccess;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"path:'{path}'", ex);
|
||||
}
|
||||
|
||||
foreach (string fileWithIllegalCharacters in files)
|
||||
{
|
||||
if (worker != null && worker.CancellationPending)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// https://github.com/Hofknecht/SystemTrayMenu/issues/171
|
||||
string file = fileWithIllegalCharacters.Replace("\x00", string.Empty);
|
||||
|
||||
bool hiddenEntry = false;
|
||||
if (FolderOptions.IsHidden(file, ref hiddenEntry))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RowData rowData = ReadRowData(file, false, false);
|
||||
rowData.HiddenEntry = hiddenEntry;
|
||||
if (Properties.Settings.Default.ShowOnlyAsSearchResult)
|
||||
{
|
||||
rowData.ShowOnlyWhenSearch = filesToAddToMainMenu.Contains(fileWithIllegalCharacters);
|
||||
}
|
||||
|
||||
string resolvedLnkPath = string.Empty;
|
||||
if (rowData.ReadIconOrResolveLinkAndReadIcon(false, ref resolvedLnkPath, level))
|
||||
{
|
||||
rowData = ReadRowData(resolvedLnkPath, true, true, rowData);
|
||||
rowData.HiddenEntry = hiddenEntry;
|
||||
}
|
||||
|
||||
rowDatasFiles.Add(rowData);
|
||||
}
|
||||
|
||||
if (Properties.Settings.Default.SortByTypeAndDate)
|
||||
{
|
||||
rowDatasFiles = rowDatasFiles.OrderBy(x => x.FileInfo.LastWriteTime).Reverse().ToList();
|
||||
}
|
||||
|
||||
menuData.RowDatas = menuData.RowDatas.Concat(rowDatasFiles).ToList();
|
||||
return menuData;
|
||||
}
|
||||
|
||||
if (!worker.CancellationPending)
|
||||
MenusHelpers.ReadHiddenAndReadIcons(worker, ref menuData);
|
||||
if (worker?.CancellationPending == true)
|
||||
{
|
||||
if (menuData.Validity == MenuDataValidity.AbortedOrUnknown)
|
||||
{
|
||||
if (menuData.RowDatas.Count == 0)
|
||||
{
|
||||
menuData.Validity = MenuDataValidity.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Properties.Settings.Default.SortByName)
|
||||
{
|
||||
menuData.RowDatas = menuData.RowDatas.OrderBy(x => x.Text).ToList();
|
||||
}
|
||||
else if (Properties.Settings.Default.SortByDate)
|
||||
{
|
||||
menuData.RowDatas = menuData.RowDatas.OrderBy(x => x.FileInfo.LastWriteTime).Reverse().ToList();
|
||||
}
|
||||
|
||||
menuData.Validity = MenuDataValidity.Valid;
|
||||
}
|
||||
}
|
||||
return menuData;
|
||||
}
|
||||
|
||||
MenusHelpers.CheckIfValid(ref menuData);
|
||||
MenusHelpers.SortItemsWhenValid(ref menuData);
|
||||
return menuData;
|
||||
}
|
||||
|
||||
|
@ -726,8 +550,8 @@ namespace SystemTrayMenu.Business
|
|||
RowData rowData = eDoWork.Argument as RowData;
|
||||
if (rowData != null)
|
||||
{
|
||||
path = rowData.TargetFilePath;
|
||||
level = rowData.MenuLevel + 1;
|
||||
path = rowData.ResolvedPath;
|
||||
level = rowData.Level + 1;
|
||||
}
|
||||
|
||||
if (Properties.Settings.Default.GenerateShortcutsToDrives)
|
||||
|
@ -740,120 +564,6 @@ namespace SystemTrayMenu.Business
|
|||
eDoWork.Result = menuData;
|
||||
}
|
||||
|
||||
private static void AddFoldersToMainMenu(ref string[] directoriesToAddToMainMenu, ref string[] filesToAddToMainMenu)
|
||||
{
|
||||
string pathAddToMainMenu = string.Empty;
|
||||
bool recursive = false;
|
||||
try
|
||||
{
|
||||
foreach (string pathAndRecursivString in Properties.Settings.Default.PathsAddToMainMenu.Split(@"|"))
|
||||
{
|
||||
if (string.IsNullOrEmpty(pathAndRecursivString))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pathAddToMainMenu = pathAndRecursivString.Split("recursiv:")[0].Trim();
|
||||
recursive = pathAndRecursivString.Split("recursiv:")[1].StartsWith("True");
|
||||
bool onlyFiles = pathAndRecursivString.Split("onlyFiles:")[1].StartsWith("True");
|
||||
|
||||
string[] directoriesToConcat = Array.Empty<string>();
|
||||
string[] filesToAddToConcat = Array.Empty<string>();
|
||||
if (recursive)
|
||||
{
|
||||
GetDirectoriesAndFilesRecursive(ref directoriesToConcat, ref filesToAddToConcat, pathAddToMainMenu);
|
||||
}
|
||||
else
|
||||
{
|
||||
directoriesToConcat = Directory.GetDirectories(pathAddToMainMenu);
|
||||
filesToAddToConcat = DirectoryBySearchPattern.GetFiles(pathAddToMainMenu, Config.SearchPattern);
|
||||
}
|
||||
|
||||
if (!onlyFiles)
|
||||
{
|
||||
directoriesToAddToMainMenu = directoriesToAddToMainMenu.Concat(directoriesToConcat).ToArray();
|
||||
}
|
||||
|
||||
filesToAddToMainMenu = filesToAddToMainMenu.Concat(filesToAddToConcat).ToArray();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"path:'{pathAddToMainMenu}' recursiv:{recursive}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetDirectoriesAndFilesRecursive(ref string[] directoriesToConcat, ref string[] filesToAddToConcat, string pathAddToMainMenu)
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] directories = Directory.GetDirectories(pathAddToMainMenu);
|
||||
|
||||
try
|
||||
{
|
||||
filesToAddToConcat = filesToAddToConcat.Concat(DirectoryBySearchPattern.GetFiles(pathAddToMainMenu, Config.SearchPattern)).ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"GetDirectoriesAndFilesRecursive path:'{pathAddToMainMenu}'", ex);
|
||||
}
|
||||
|
||||
foreach (string directory in directories)
|
||||
{
|
||||
GetDirectoriesAndFilesRecursive(ref directoriesToConcat, ref filesToAddToConcat, directory);
|
||||
}
|
||||
|
||||
directoriesToConcat = directoriesToConcat.Concat(directories).ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"GetDirectoriesAndFilesRecursive path:'{pathAddToMainMenu}'", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static RowData ReadRowData(string fileName, bool isResolvedLnk, bool containsMenu, RowData rowData = null)
|
||||
{
|
||||
if (rowData == null)
|
||||
{
|
||||
rowData = new RowData();
|
||||
}
|
||||
|
||||
rowData.ContainsMenu = containsMenu;
|
||||
rowData.IsResolvedLnk = isResolvedLnk;
|
||||
|
||||
try
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(fileName);
|
||||
rowData.TargetFilePath = fileInfo.FullName;
|
||||
if (!isResolvedLnk)
|
||||
{
|
||||
rowData.FileInfo = fileInfo;
|
||||
if (string.IsNullOrEmpty(fileInfo.Name))
|
||||
{
|
||||
string path = fileInfo.FullName;
|
||||
int directoryNameBegin = path.LastIndexOf(@"\", StringComparison.InvariantCulture) + 1;
|
||||
rowData.SetText(path[directoryNameBegin..]);
|
||||
}
|
||||
else if (!rowData.ContainsMenu && Config.IsHideFileExtension())
|
||||
{
|
||||
rowData.SetText(Path.GetFileNameWithoutExtension(fileInfo.Name));
|
||||
}
|
||||
else
|
||||
{
|
||||
rowData.SetText(fileInfo.Name);
|
||||
}
|
||||
|
||||
rowData.TargetFilePathOrig = fileInfo.FullName;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"fileName:'{fileName}'", ex);
|
||||
}
|
||||
|
||||
return rowData;
|
||||
}
|
||||
|
||||
private static void OpenFolder(string pathToFolder = "")
|
||||
{
|
||||
string path = pathToFolder;
|
||||
|
@ -879,6 +589,52 @@ namespace SystemTrayMenu.Business
|
|||
}
|
||||
}
|
||||
|
||||
private static void AddItemsToMenu(List<RowData> data, Menu menu, out int foldersCount, out int filesCount)
|
||||
{
|
||||
foldersCount = 0;
|
||||
filesCount = 0;
|
||||
DataGridView dgv = menu.GetDataGridView();
|
||||
DataTable dataTable = new();
|
||||
dataTable.Columns.Add(dgv.Columns[0].Name, typeof(Icon));
|
||||
dataTable.Columns.Add(dgv.Columns[1].Name, typeof(string));
|
||||
dataTable.Columns.Add("data", typeof(RowData));
|
||||
dataTable.Columns.Add("SortIndex");
|
||||
foreach (RowData rowData in data)
|
||||
{
|
||||
if (!(rowData.IsAddionalItem && Properties.Settings.Default.ShowOnlyAsSearchResult))
|
||||
{
|
||||
if (rowData.ContainsMenu)
|
||||
{
|
||||
foldersCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
filesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
rowData.SetData(rowData, dataTable);
|
||||
}
|
||||
|
||||
dgv.DataSource = dataTable;
|
||||
dgv.Columns["data"].Visible = false;
|
||||
dgv.Columns["SortIndex"].Visible = false;
|
||||
|
||||
string columnSortIndex = "SortIndex";
|
||||
foreach (DataRow row in dataTable.Rows)
|
||||
{
|
||||
RowData rowData = (RowData)row[2];
|
||||
if (rowData.IsAddionalItem && Properties.Settings.Default.ShowOnlyAsSearchResult)
|
||||
{
|
||||
row[columnSortIndex] = 99;
|
||||
}
|
||||
else
|
||||
{
|
||||
row[columnSortIndex] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsActive()
|
||||
{
|
||||
bool IsShellContextMenuOpen()
|
||||
|
@ -916,8 +672,8 @@ namespace SystemTrayMenu.Business
|
|||
string path = Config.Path;
|
||||
if (title == null)
|
||||
{
|
||||
title = Path.GetFileName(menuData.RowDataParent.TargetFilePath);
|
||||
path = menuData.RowDataParent.TargetFilePath;
|
||||
title = Path.GetFileName(menuData.RowDataParent.ResolvedPath);
|
||||
path = menuData.RowDataParent.ResolvedPath;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(title))
|
||||
|
@ -975,51 +731,6 @@ namespace SystemTrayMenu.Business
|
|||
|
||||
menu.VisibleChanged += MenuVisibleChanged;
|
||||
AddItemsToMenu(menuData.RowDatas, menu, out int foldersCount, out int filesCount);
|
||||
static void AddItemsToMenu(List<RowData> data, Menu menu, out int foldersCount, out int filesCount)
|
||||
{
|
||||
foldersCount = 0;
|
||||
filesCount = 0;
|
||||
DataGridView dgv = menu.GetDataGridView();
|
||||
DataTable dataTable = new();
|
||||
dataTable.Columns.Add(dgv.Columns[0].Name, typeof(Icon));
|
||||
dataTable.Columns.Add(dgv.Columns[1].Name, typeof(string));
|
||||
dataTable.Columns.Add("data", typeof(RowData));
|
||||
dataTable.Columns.Add("SortIndex");
|
||||
foreach (RowData rowData in data)
|
||||
{
|
||||
if (!rowData.ShowOnlyWhenSearch)
|
||||
{
|
||||
if (rowData.ContainsMenu)
|
||||
{
|
||||
foldersCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
filesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
rowData.SetData(rowData, dataTable);
|
||||
}
|
||||
|
||||
dgv.DataSource = dataTable;
|
||||
dgv.Columns["data"].Visible = false;
|
||||
dgv.Columns["SortIndex"].Visible = false;
|
||||
|
||||
string columnSortIndex = "SortIndex";
|
||||
foreach (DataRow row in dataTable.Rows)
|
||||
{
|
||||
RowData rowData = (RowData)row[2];
|
||||
if (rowData.ShowOnlyWhenSearch)
|
||||
{
|
||||
row[columnSortIndex] = 99;
|
||||
}
|
||||
else
|
||||
{
|
||||
row[columnSortIndex] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataGridView dgv = menu.GetDataGridView();
|
||||
dgv.CellMouseEnter += dgvMouseRow.CellMouseEnter;
|
||||
|
@ -1137,6 +848,7 @@ namespace SystemTrayMenu.Business
|
|||
if (hitTestInfo.RowIndex > -1 &&
|
||||
hitTestInfo.RowIndex < dgv.Rows.Count)
|
||||
{
|
||||
MouseEnterOk(dgv, hitTestInfo.RowIndex, true);
|
||||
RowData rowData = (RowData)dgv.Rows[hitTestInfo.RowIndex].Cells[2].Value;
|
||||
rowData.MouseDown(dgv, e);
|
||||
InvalidateRowIfIndexInRange(dgv, hitTestInfo.RowIndex);
|
||||
|
@ -1178,6 +890,25 @@ namespace SystemTrayMenu.Business
|
|||
isDragSwipeScrolled = false;
|
||||
}
|
||||
|
||||
private void MouseEnterOk(DataGridView dgv, int rowIndex)
|
||||
{
|
||||
MouseEnterOk(dgv, rowIndex, false);
|
||||
}
|
||||
|
||||
private void MouseEnterOk(DataGridView dgv, int rowIndex, bool refreshView)
|
||||
{
|
||||
if (menus[0].IsUsable)
|
||||
{
|
||||
if (keyboardInput.InUse)
|
||||
{
|
||||
keyboardInput.ClearIsSelectedByKey();
|
||||
keyboardInput.InUse = false;
|
||||
}
|
||||
|
||||
keyboardInput.Select(dgv, rowIndex, refreshView);
|
||||
}
|
||||
}
|
||||
|
||||
private void Dgv_RowMouseLeave(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
DataGridView dgv = (DataGridView)sender;
|
||||
|
@ -1189,7 +920,7 @@ namespace SystemTrayMenu.Business
|
|||
{
|
||||
lastMouseDownRowIndex = -1;
|
||||
RowData rowData = (RowData)dgv.Rows[e.RowIndex].Cells[2].Value;
|
||||
string[] files = new string[] { rowData.TargetFilePathOrig };
|
||||
string[] files = new string[] { rowData.Path };
|
||||
|
||||
// Update position raises move event which prevent DoDragDrop blocking UI when mouse not moved
|
||||
Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y);
|
||||
|
@ -1332,7 +1063,7 @@ namespace SystemTrayMenu.Business
|
|||
{
|
||||
timerShowProcessStartedAsLoadingIcon.Tick -= Tick;
|
||||
timerShowProcessStartedAsLoadingIcon.Stop();
|
||||
row.Cells[0].Value = rowData.ReadLoadedIcon();
|
||||
row.Cells[0].Value = rowData.ReadIcon(false);
|
||||
waitingForReactivate = false;
|
||||
}
|
||||
|
||||
|
@ -1538,6 +1269,7 @@ namespace SystemTrayMenu.Business
|
|||
{
|
||||
searchTextChanging = true;
|
||||
keyboardInput.SearchTextChanging();
|
||||
waitToOpenMenu.MouseActive = false;
|
||||
}
|
||||
|
||||
private void Menu_SearchTextChanged(object sender, bool isSearchStringEmpty)
|
||||
|
@ -1551,11 +1283,126 @@ namespace SystemTrayMenu.Business
|
|||
if (menu.Level + 1 < menus.Length)
|
||||
{
|
||||
Menu menuToClose = menus[menu.Level + 1];
|
||||
if (menuToClose != null)
|
||||
if (menuToClose != null && hideSubmenuDuringRefreshSearch)
|
||||
{
|
||||
HideOldMenu(menuToClose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteWatcherHistory()
|
||||
{
|
||||
foreach (var fileSystemEventArgs in watcherHistory)
|
||||
{
|
||||
WatcherProcessItem(watchers, fileSystemEventArgs);
|
||||
}
|
||||
|
||||
watcherHistory.Clear();
|
||||
}
|
||||
|
||||
private void WatcherRenamed(object sender, RenamedEventArgs e)
|
||||
{
|
||||
WatcherProcessItem(sender, new FileSystemEventArgs(WatcherChangeTypes.Deleted, Path.GetDirectoryName(e.OldFullPath), e.OldName));
|
||||
WatcherProcessItem(sender, new FileSystemEventArgs(WatcherChangeTypes.Created, Path.GetDirectoryName(e.FullPath), e.Name));
|
||||
}
|
||||
|
||||
private void WatcherChanged(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
WatcherProcessItem(sender, new FileSystemEventArgs(WatcherChangeTypes.Deleted, Path.GetDirectoryName(e.FullPath), e.Name));
|
||||
WatcherProcessItem(sender, new FileSystemEventArgs(WatcherChangeTypes.Created, Path.GetDirectoryName(e.FullPath), e.Name));
|
||||
}
|
||||
|
||||
private void WatcherProcessItem(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
if (menus[0] == null || !menus[0].IsHandleCreated)
|
||||
{
|
||||
watcherHistory.Add(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.ChangeType == WatcherChangeTypes.Deleted)
|
||||
{
|
||||
menus[0].Invoke(() => DeleteItem(e));
|
||||
}
|
||||
else if (e.ChangeType == WatcherChangeTypes.Created)
|
||||
{
|
||||
menus[0].Invoke(() => CreateItem(e));
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteItem(FileSystemEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
DataRow rowToRemove = null;
|
||||
DataGridView dgv = menus[0].GetDataGridView();
|
||||
DataTable dataTable = (DataTable)dgv.DataSource;
|
||||
foreach (DataRow row in dataTable.Rows)
|
||||
{
|
||||
RowData rowData = (RowData)row[2];
|
||||
if (rowData.Path == e.FullPath)
|
||||
{
|
||||
IconReader.RemoveIconFromCache(rowData.Path);
|
||||
rowToRemove = row;
|
||||
}
|
||||
}
|
||||
|
||||
if (rowToRemove != null)
|
||||
{
|
||||
dataTable.Rows.Remove(rowToRemove);
|
||||
}
|
||||
|
||||
keyboardInput.ClearIsSelectedByKey();
|
||||
dgv.DataSource = dataTable;
|
||||
|
||||
hideSubmenuDuringRefreshSearch = false;
|
||||
menus[0].RefreshSearchText();
|
||||
hideSubmenuDuringRefreshSearch = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"Failed to {nameof(DeleteItem)}: {e.FullPath}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateItem(FileSystemEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileAttributes attr = File.GetAttributes(e.FullPath);
|
||||
bool isFolder = (attr & FileAttributes.Directory) == FileAttributes.Directory;
|
||||
bool isAddionalItem = Path.GetDirectoryName(e.FullPath) != Config.Path;
|
||||
RowData rowData = new(isFolder, isAddionalItem, false, 0, e.FullPath);
|
||||
if (FolderOptions.IsHidden(rowData))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rowData.ReadIcon(true);
|
||||
|
||||
List<RowData> rowDatas = new();
|
||||
rowDatas.Add(rowData);
|
||||
|
||||
DataTable dataTable = (DataTable)menus[0].GetDataGridView().DataSource;
|
||||
foreach (DataRow row in dataTable.Rows)
|
||||
{
|
||||
rowDatas.Add((RowData)row[2]);
|
||||
}
|
||||
|
||||
rowDatas = MenusHelpers.SortItems(rowDatas);
|
||||
keyboardInput.ClearIsSelectedByKey();
|
||||
AddItemsToMenu(rowDatas, menus[0], out _, out _);
|
||||
|
||||
hideSubmenuDuringRefreshSearch = false;
|
||||
menus[0].RefreshSearchText();
|
||||
hideSubmenuDuringRefreshSearch = true;
|
||||
|
||||
menus[0].TimerUpdateIconsStart();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"Failed to {nameof(CreateItem)}: {e.FullPath}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
265
Business/MenusHelpers.cs
Normal file
265
Business/MenusHelpers.cs
Normal file
|
@ -0,0 +1,265 @@
|
|||
// <copyright file="MenusHelpers.cs" company="PlaceholderCompany">
|
||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace SystemTrayMenu.Business
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SystemTrayMenu.DataClasses;
|
||||
using SystemTrayMenu.Helper;
|
||||
using SystemTrayMenu.Utilities;
|
||||
|
||||
internal static class MenusHelpers
|
||||
{
|
||||
internal static void GetItemsForMainMenu(BackgroundWorker worker, string path, ref MenuData menuData)
|
||||
{
|
||||
menuData.IsNetworkRoot = FileLnk.IsNetworkRoot(path);
|
||||
if (menuData.IsNetworkRoot)
|
||||
{
|
||||
GetNetworkRootDirectories(path, ref menuData);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetDirectories(worker, path, ref menuData);
|
||||
GetFiles(worker, path, ref menuData);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void GetAddionalItemsForMainMenu(ref MenuData menuData)
|
||||
{
|
||||
if (menuData.Level != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var path in GetAddionalPathsForMainMenu())
|
||||
{
|
||||
GetDirectoriesAndFilesRecursive(ref menuData, path.Path, path.OnlyFiles, path.Recursive);
|
||||
}
|
||||
}
|
||||
|
||||
internal static IEnumerable<(string Path, bool Recursive, bool OnlyFiles)> GetAddionalPathsForMainMenu()
|
||||
{
|
||||
foreach (string pathAndRecursivString in Properties.Settings.Default.PathsAddToMainMenu.Split(@"|"))
|
||||
{
|
||||
if (string.IsNullOrEmpty(pathAndRecursivString))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string pathAddForMainMenu = pathAndRecursivString.Split("recursiv:")[0].Trim();
|
||||
bool recursive = pathAndRecursivString.Split("recursiv:")[1].StartsWith("True");
|
||||
bool onlyFiles = pathAndRecursivString.Split("onlyFiles:")[1].StartsWith("True");
|
||||
yield return (Path: pathAddForMainMenu, Recursive: recursive, OnlyFiles: onlyFiles);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ReadHiddenAndReadIcons(BackgroundWorker worker, ref MenuData menuData)
|
||||
{
|
||||
List<RowData> rowDatasToRemove = new();
|
||||
foreach (RowData rowData in menuData.RowDatas)
|
||||
{
|
||||
if (worker?.CancellationPending == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!menuData.IsNetworkRoot && FolderOptions.IsHidden(rowData))
|
||||
{
|
||||
rowDatasToRemove.Add(rowData);
|
||||
continue;
|
||||
}
|
||||
|
||||
rowData.ReadIcon(true);
|
||||
}
|
||||
|
||||
menuData.RowDatas = menuData.RowDatas.Except(rowDatasToRemove).ToList();
|
||||
}
|
||||
|
||||
internal static void CheckIfValid(ref MenuData menuData)
|
||||
{
|
||||
if (menuData.Validity == MenuDataValidity.Undefined)
|
||||
{
|
||||
if (menuData.RowDatas.Count == 0)
|
||||
{
|
||||
menuData.Validity = MenuDataValidity.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
menuData.Validity = MenuDataValidity.Valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SortItemsWhenValid(ref MenuData menuData)
|
||||
{
|
||||
if (menuData.Validity != MenuDataValidity.Valid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
menuData.RowDatas = SortItems(menuData.RowDatas);
|
||||
}
|
||||
|
||||
internal static List<RowData> SortItems(List<RowData> rowDatas)
|
||||
{
|
||||
if (Properties.Settings.Default.SortByTypeAndNameWindowsExplorerSort)
|
||||
{
|
||||
rowDatas = rowDatas.OrderByDescending(x => x.IsFolder)
|
||||
.ThenBy(x => x.Text, new WindowsExplorerSort()).ToList();
|
||||
}
|
||||
else if (Properties.Settings.Default.SortByTypeAndDate)
|
||||
{
|
||||
rowDatas = rowDatas.OrderByDescending(x => x.IsFolder)
|
||||
.ThenByDescending(x => x.FileInfo.LastWriteTime).ToList();
|
||||
}
|
||||
else if (Properties.Settings.Default.SortByName)
|
||||
{
|
||||
rowDatas = rowDatas.OrderBy(x => x.Text).ToList();
|
||||
}
|
||||
else if (Properties.Settings.Default.SortByDate)
|
||||
{
|
||||
rowDatas = rowDatas.OrderByDescending(x => x.FileInfo.LastWriteTime).ToList();
|
||||
}
|
||||
|
||||
return rowDatas;
|
||||
}
|
||||
|
||||
private static void GetNetworkRootDirectories(string path, ref MenuData menuData)
|
||||
{
|
||||
Process cmd = new();
|
||||
cmd.StartInfo.FileName = "cmd.exe";
|
||||
cmd.StartInfo.RedirectStandardInput = true;
|
||||
cmd.StartInfo.RedirectStandardOutput = true;
|
||||
cmd.StartInfo.CreateNoWindow = true;
|
||||
cmd.StartInfo.UseShellExecute = false;
|
||||
cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
|
||||
try
|
||||
{
|
||||
bool resolvedSomething = false;
|
||||
cmd.Start();
|
||||
cmd.StandardInput.WriteLine($"net view {path}");
|
||||
cmd.StandardInput.Flush();
|
||||
cmd.StandardInput.Close();
|
||||
string output = cmd.StandardOutput.ReadToEnd();
|
||||
cmd.WaitForExit();
|
||||
cmd.Close();
|
||||
List<string> lines = output
|
||||
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
if (lines.Count > 8)
|
||||
{
|
||||
foreach (string line in lines.Skip(6).SkipLast(2))
|
||||
{
|
||||
int indexOfFirstSpace = line.IndexOf(" ", StringComparison.InvariantCulture);
|
||||
if (indexOfFirstSpace > 0)
|
||||
{
|
||||
string directory = Path.Combine(path, line[..indexOfFirstSpace]);
|
||||
menuData.RowDatas.Add(new RowData(true, false, true, menuData.Level, directory));
|
||||
resolvedSomething = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!resolvedSomething)
|
||||
{
|
||||
Log.Info($"Could not resolve network root folder: {path} , output:{output}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"path:'{path}'", ex);
|
||||
if (ex is UnauthorizedAccessException)
|
||||
{
|
||||
menuData.Validity = MenuDataValidity.NoAccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetDirectories(BackgroundWorker worker, string path, ref MenuData menuData)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var directory in Directory.GetDirectories(path))
|
||||
{
|
||||
if (worker?.CancellationPending == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
menuData.RowDatas.Add(new RowData(true, false, false, menuData.Level, directory));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"path:'{path}'", ex);
|
||||
if (ex is UnauthorizedAccessException)
|
||||
{
|
||||
menuData.Validity = MenuDataValidity.NoAccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetFiles(BackgroundWorker worker, string path, ref MenuData menuData)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (string file in DirectoryBySearchPattern.GetFiles(path, Config.SearchPattern))
|
||||
{
|
||||
if (worker?.CancellationPending == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
menuData.RowDatas.Add(new RowData(false, false, false, menuData.Level, file));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"path:'{path}'", ex);
|
||||
if (ex is UnauthorizedAccessException)
|
||||
{
|
||||
menuData.Validity = MenuDataValidity.NoAccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetDirectoriesAndFilesRecursive(
|
||||
ref MenuData menuData,
|
||||
string path,
|
||||
bool onlyFiles,
|
||||
bool recursiv)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (string file in DirectoryBySearchPattern.GetFiles(path, Config.SearchPattern))
|
||||
{
|
||||
menuData.RowDatas.Add(new RowData(false, true, false, menuData.Level, file));
|
||||
}
|
||||
|
||||
foreach (string directory in Directory.GetDirectories(path))
|
||||
{
|
||||
if (!onlyFiles)
|
||||
{
|
||||
menuData.RowDatas.Add(new RowData(true, true, false, menuData.Level, directory));
|
||||
}
|
||||
|
||||
if (recursiv)
|
||||
{
|
||||
GetDirectoriesAndFilesRecursive(ref menuData, directory, onlyFiles, recursiv);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"GetDirectoriesAndFilesRecursive path:'{path}'", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -168,17 +168,17 @@ namespace SystemTrayMenu.Handler
|
|||
{
|
||||
RowData rowData = (RowData)dgv.Rows[rowIndex].Cells[2].Value;
|
||||
Menu menu = (Menu)dgv.FindForm();
|
||||
rowData.MenuLevel = menu.Level;
|
||||
rowData.Level = menu.Level;
|
||||
if (rowData.ContainsMenu)
|
||||
{
|
||||
CloseMenu.Invoke(rowData.MenuLevel + 2);
|
||||
CloseMenu.Invoke(rowData.Level + 2);
|
||||
}
|
||||
|
||||
CloseMenu.Invoke(rowData.MenuLevel + 1);
|
||||
CloseMenu.Invoke(rowData.Level + 1);
|
||||
|
||||
if (!rowData.IsContextMenuOpen &&
|
||||
rowData.ContainsMenu &&
|
||||
rowData.MenuLevel + 1 < MenuDefines.MenusMax)
|
||||
rowData.Level + 1 < MenuDefines.MenusMax)
|
||||
{
|
||||
StartLoadMenu.Invoke(rowData);
|
||||
}
|
||||
|
|
|
@ -14,12 +14,12 @@ namespace SystemTrayMenu
|
|||
using SystemTrayMenu.Properties;
|
||||
using SystemTrayMenu.UserInterface.FolderBrowseDialog;
|
||||
using SystemTrayMenu.Utilities;
|
||||
using static SystemTrayMenu.Utilities.IconReader;
|
||||
|
||||
public static class Config
|
||||
{
|
||||
private static readonly Icon SystemTrayMenu = Properties.Resources.SystemTrayMenu;
|
||||
private static readonly Icon IconFromRootFolder = IconReader.GetIconSTA(
|
||||
Path, Path, false, IconReader.IconSize.Small, IconReader.FolderType.Closed);
|
||||
private static readonly Icon IconRootFolder = GetIconSTA(Path, Path, false, IconSize.Small, true);
|
||||
|
||||
private static bool readDarkModeDone;
|
||||
private static bool isDarkMode;
|
||||
|
@ -71,7 +71,7 @@ namespace SystemTrayMenu
|
|||
{
|
||||
if (Settings.Default.UseIconFromRootFolder)
|
||||
{
|
||||
return IconFromRootFolder;
|
||||
return IconRootFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -174,7 +174,7 @@ namespace SystemTrayMenu
|
|||
/// <summary>
|
||||
/// Read the OS setting whether HideFileExt enabled.
|
||||
/// </summary>
|
||||
/// <returns>true = Dark mode; false = Light mode.</returns>
|
||||
/// <returns>isHideFileExtension.</returns>
|
||||
internal static bool IsHideFileExtension()
|
||||
{
|
||||
if (!readHideFileExtdone)
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace SystemTrayMenu.DataClasses
|
|||
|
||||
internal enum MenuDataValidity
|
||||
{
|
||||
AbortedOrUnknown,
|
||||
Undefined,
|
||||
Valid,
|
||||
Empty,
|
||||
NoAccess,
|
||||
|
@ -16,9 +16,23 @@ namespace SystemTrayMenu.DataClasses
|
|||
|
||||
internal struct MenuData
|
||||
{
|
||||
internal List<RowData> RowDatas;
|
||||
internal MenuDataValidity Validity;
|
||||
internal int Level;
|
||||
internal RowData RowDataParent;
|
||||
public MenuData(int level)
|
||||
{
|
||||
RowDatas = new List<RowData>();
|
||||
Validity = MenuDataValidity.Undefined;
|
||||
Level = level;
|
||||
RowDataParent = null;
|
||||
IsNetworkRoot = false;
|
||||
}
|
||||
|
||||
internal List<RowData> RowDatas { get; set; }
|
||||
|
||||
internal MenuDataValidity Validity { get; set; }
|
||||
|
||||
internal int Level { get; }
|
||||
|
||||
internal RowData RowDataParent { get; set; }
|
||||
|
||||
internal bool IsNetworkRoot { get; set; }
|
||||
}
|
||||
}
|
|
@ -10,22 +10,116 @@ namespace SystemTrayMenu.DataClasses
|
|||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using SystemTrayMenu.Utilities;
|
||||
using static SystemTrayMenu.Utilities.IconReader;
|
||||
using Menu = SystemTrayMenu.UserInterface.Menu;
|
||||
|
||||
internal class RowData
|
||||
{
|
||||
private static readonly Icon White50PercentageIcon = Properties.Resources.White50Percentage;
|
||||
private static readonly Icon NotFoundIcon = Properties.Resources.NotFound;
|
||||
private static DateTime contextMenuClosed;
|
||||
private Icon icon;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RowData"/> class.
|
||||
/// empty dummy.
|
||||
/// </summary>
|
||||
internal RowData()
|
||||
{
|
||||
}
|
||||
|
||||
internal string Text { get; set; }
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RowData"/> class.
|
||||
/// (Related replace "\x00" see #171.)
|
||||
/// </summary>
|
||||
/// <param name="isFolder">Flag if file or folder.</param>
|
||||
/// <param name="isAddionalItem">Flag if addional item, from other folder than root folder.</param>
|
||||
/// <param name="isNetworkRoot">Flag if resolved from network root folder.</param>
|
||||
/// <param name="level">The number of the menu level.</param>
|
||||
/// <param name="path">Path to item.</param>
|
||||
internal RowData(bool isFolder, bool isAddionalItem, bool isNetworkRoot, int level, string path)
|
||||
{
|
||||
IsFolder = isFolder;
|
||||
IsAddionalItem = isAddionalItem;
|
||||
IsNetworkRoot = isNetworkRoot;
|
||||
Level = level;
|
||||
|
||||
internal FileInfo FileInfo { get; set; }
|
||||
try
|
||||
{
|
||||
FileInfo = new FileInfo(path.Replace("\x00", string.Empty));
|
||||
Path = FileInfo.FullName;
|
||||
FileExtension = System.IO.Path.GetExtension(Path);
|
||||
IsLink = FileExtension.Equals(".lnk", StringComparison.InvariantCultureIgnoreCase);
|
||||
if (IsLink)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
ContainsMenu = IsFolder || IsLinkToFolder;
|
||||
IsMainMenu = Level == 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn($"path:'{path}'", ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal FileInfo FileInfo { get; }
|
||||
|
||||
internal string Path { get; }
|
||||
|
||||
internal bool IsFolder { get; }
|
||||
|
||||
internal bool IsAddionalItem { get; }
|
||||
|
||||
internal bool IsNetworkRoot { get; }
|
||||
|
||||
internal int Level { get; set; }
|
||||
|
||||
internal string FileExtension { get; }
|
||||
|
||||
internal bool IsLink { get; }
|
||||
|
||||
internal string ResolvedPath { get; }
|
||||
|
||||
internal bool IsLinkToFolder { get; }
|
||||
|
||||
internal bool ShowOverlay { get; }
|
||||
|
||||
internal string Text { get; }
|
||||
|
||||
internal bool ContainsMenu { get; }
|
||||
|
||||
internal bool IsMainMenu { get; }
|
||||
|
||||
internal Menu SubMenu { get; set; }
|
||||
|
||||
|
@ -35,35 +129,16 @@ namespace SystemTrayMenu.DataClasses
|
|||
|
||||
internal bool IsSelected { get; set; }
|
||||
|
||||
internal bool ContainsMenu { get; set; }
|
||||
|
||||
internal bool IsContextMenuOpen { get; set; }
|
||||
|
||||
internal bool IsResolvedLnk { get; set; }
|
||||
|
||||
internal bool HiddenEntry { get; set; }
|
||||
|
||||
internal bool ShowOnlyWhenSearch { get; set; }
|
||||
|
||||
internal string TargetFilePath { get; set; }
|
||||
|
||||
internal string TargetFilePathOrig { get; set; }
|
||||
|
||||
internal int RowIndex { get; set; }
|
||||
|
||||
internal int MenuLevel { get; set; }
|
||||
|
||||
internal bool IconLoading { get; set; }
|
||||
|
||||
internal string FilePathIcon { get; set; }
|
||||
|
||||
internal bool ProcessStarted { get; set; }
|
||||
|
||||
internal void SetText(string text)
|
||||
{
|
||||
this.Text = text;
|
||||
}
|
||||
|
||||
internal void SetData(RowData data, DataTable dataTable)
|
||||
{
|
||||
DataRow row = dataTable.Rows.Add();
|
||||
|
@ -71,7 +146,7 @@ namespace SystemTrayMenu.DataClasses
|
|||
|
||||
if (HiddenEntry)
|
||||
{
|
||||
row[0] = IconReader.AddIconOverlay(data.icon, White50PercentageIcon);
|
||||
row[0] = AddIconOverlay(data.icon, Properties.Resources.White50Percentage);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -82,65 +157,32 @@ namespace SystemTrayMenu.DataClasses
|
|||
row[2] = data;
|
||||
}
|
||||
|
||||
internal bool ReadIconOrResolveLinkAndReadIcon(bool isDirectory, ref string resolvedLnkPath, int level)
|
||||
internal Icon ReadIcon(bool updateIconInBackground)
|
||||
{
|
||||
bool isLnkDirectory = false;
|
||||
|
||||
if (string.IsNullOrEmpty(TargetFilePath))
|
||||
if (IsFolder || IsLinkToFolder)
|
||||
{
|
||||
Log.Info($"TargetFilePath from {resolvedLnkPath} empty");
|
||||
}
|
||||
else if (isDirectory)
|
||||
{
|
||||
icon = IconReader.GetFolderIconWithCache(
|
||||
TargetFilePathOrig,
|
||||
IconReader.FolderType.Closed,
|
||||
false,
|
||||
true,
|
||||
level == 0,
|
||||
out bool loading);
|
||||
icon = GetFolderIconWithCache(Path, ShowOverlay, updateIconInBackground, IsMainMenu, out bool loading);
|
||||
IconLoading = loading;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool handled = false;
|
||||
bool showOverlay = false;
|
||||
string fileExtension = Path.GetExtension(TargetFilePath);
|
||||
|
||||
if (fileExtension.Equals(".lnk", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
handled = ResolveLinkAndReadIcon(level, ref isLnkDirectory, ref resolvedLnkPath);
|
||||
showOverlay = Properties.Settings.Default.ShowLinkOverlay;
|
||||
}
|
||||
else if (fileExtension.Equals(".url", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
SetText($"{Text[0..^4]}");
|
||||
showOverlay = Properties.Settings.Default.ShowLinkOverlay;
|
||||
}
|
||||
else if (fileExtension.Equals(".appref-ms", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
showOverlay = Properties.Settings.Default.ShowLinkOverlay;
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
icon = IconReader.GetFileIconWithCache(
|
||||
TargetFilePathOrig,
|
||||
TargetFilePath,
|
||||
showOverlay,
|
||||
true,
|
||||
level == 0,
|
||||
out bool loading);
|
||||
IconLoading = loading;
|
||||
}
|
||||
icon = GetFileIconWithCache(Path, ResolvedPath, ShowOverlay, updateIconInBackground, IsMainMenu, out bool loading);
|
||||
IconLoading = loading;
|
||||
}
|
||||
|
||||
if (icon == null)
|
||||
if (!IconLoading)
|
||||
{
|
||||
icon = NotFoundIcon;
|
||||
if (icon == null)
|
||||
{
|
||||
icon = Properties.Resources.NotFound;
|
||||
}
|
||||
else if (HiddenEntry)
|
||||
{
|
||||
icon = AddIconOverlay(icon, Properties.Resources.White50Percentage);
|
||||
}
|
||||
}
|
||||
|
||||
return isLnkDirectory;
|
||||
return icon;
|
||||
}
|
||||
|
||||
internal void MouseDown(DataGridView dgv, MouseEventArgs e)
|
||||
|
@ -167,14 +209,22 @@ namespace SystemTrayMenu.DataClasses
|
|||
if (ContainsMenu)
|
||||
{
|
||||
DirectoryInfo[] dir = new DirectoryInfo[1];
|
||||
dir[0] = new DirectoryInfo(TargetFilePathOrig);
|
||||
dir[0] = new DirectoryInfo(Path);
|
||||
ctxMnu.ShowContextMenu(dir, point);
|
||||
|
||||
// Triggers filewatcher change event
|
||||
string parentFolder = System.IO.Path.GetDirectoryName(Path);
|
||||
Directory.GetFiles(parentFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileInfo[] arrFI = new FileInfo[1];
|
||||
arrFI[0] = new FileInfo(TargetFilePathOrig);
|
||||
arrFI[0] = FileInfo;
|
||||
ctxMnu.ShowContextMenu(arrFI, point);
|
||||
|
||||
// Triggers filewatcher change event
|
||||
string parentFolder = System.IO.Path.GetDirectoryName(Path);
|
||||
Directory.GetFiles(parentFolder);
|
||||
}
|
||||
|
||||
IsContextMenuOpen = false;
|
||||
|
@ -195,7 +245,7 @@ namespace SystemTrayMenu.DataClasses
|
|||
if (Properties.Settings.Default.OpenDirectoryWithOneClick &&
|
||||
ContainsMenu && (e == null || e.Button == MouseButtons.Left))
|
||||
{
|
||||
Log.ProcessStart(TargetFilePath);
|
||||
Log.ProcessStart(Path);
|
||||
if (!Properties.Settings.Default.StaysOpenWhenItemClicked)
|
||||
{
|
||||
toCloseByDoubleClick = true;
|
||||
|
@ -216,7 +266,7 @@ namespace SystemTrayMenu.DataClasses
|
|||
if (!Properties.Settings.Default.OpenDirectoryWithOneClick &&
|
||||
ContainsMenu && (e == null || e.Button == MouseButtons.Left))
|
||||
{
|
||||
Log.ProcessStart(TargetFilePath);
|
||||
Log.ProcessStart(Path);
|
||||
if (!Properties.Settings.Default.StaysOpenWhenItemClicked)
|
||||
{
|
||||
toCloseByDoubleClick = true;
|
||||
|
@ -224,100 +274,19 @@ namespace SystemTrayMenu.DataClasses
|
|||
}
|
||||
}
|
||||
|
||||
internal Icon ReadLoadedIcon()
|
||||
{
|
||||
if (ContainsMenu)
|
||||
{
|
||||
icon = IconReader.GetFolderIconWithCache(
|
||||
TargetFilePathOrig,
|
||||
IconReader.FolderType.Closed,
|
||||
false,
|
||||
false,
|
||||
MenuLevel == 0,
|
||||
out bool loading);
|
||||
IconLoading = loading;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool showOverlay = false;
|
||||
string fileExtension = Path.GetExtension(TargetFilePathOrig);
|
||||
if (fileExtension == ".lnk" || fileExtension == ".url" || fileExtension == ".appref-ms")
|
||||
{
|
||||
showOverlay = Properties.Settings.Default.ShowLinkOverlay;
|
||||
}
|
||||
|
||||
icon = IconReader.GetFileIconWithCache(
|
||||
TargetFilePathOrig,
|
||||
TargetFilePath,
|
||||
showOverlay,
|
||||
false,
|
||||
MenuLevel == 0,
|
||||
out bool loading);
|
||||
IconLoading = loading;
|
||||
}
|
||||
|
||||
if (!IconLoading && icon == null)
|
||||
{
|
||||
icon = NotFoundIcon;
|
||||
}
|
||||
|
||||
if (HiddenEntry)
|
||||
{
|
||||
icon = IconReader.AddIconOverlay(icon, White50PercentageIcon);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private void OpenItem(MouseEventArgs e, ref bool toCloseByOpenItem)
|
||||
{
|
||||
if (!ContainsMenu &&
|
||||
(e == null || e.Button == MouseButtons.Left))
|
||||
{
|
||||
ProcessStarted = true;
|
||||
string workingDirectory = Path.GetDirectoryName(TargetFilePath);
|
||||
Log.ProcessStart(TargetFilePathOrig, string.Empty, false, workingDirectory, true);
|
||||
string workingDirectory = System.IO.Path.GetDirectoryName(ResolvedPath);
|
||||
Log.ProcessStart(Path, string.Empty, false, workingDirectory, true);
|
||||
if (!Properties.Settings.Default.StaysOpenWhenItemClicked)
|
||||
{
|
||||
toCloseByOpenItem = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ResolveLinkAndReadIcon(int level, ref bool isLnkDirectory, ref string resolvedLnkPath)
|
||||
{
|
||||
bool handled = false;
|
||||
resolvedLnkPath = FileLnk.GetResolvedFileName(TargetFilePath, out bool isFolder);
|
||||
|
||||
if (string.IsNullOrEmpty(resolvedLnkPath))
|
||||
{
|
||||
// Log.Info($"Could not resolve *.LNK '{TargetFilePath}'");
|
||||
}
|
||||
else if (isFolder)
|
||||
{
|
||||
icon = IconReader.GetFolderIconWithCache(
|
||||
TargetFilePathOrig,
|
||||
IconReader.FolderType.Open,
|
||||
Properties.Settings.Default.ShowLinkOverlay,
|
||||
true,
|
||||
level == 0,
|
||||
out bool loading);
|
||||
IconLoading = loading;
|
||||
handled = true;
|
||||
isLnkDirectory = true;
|
||||
}
|
||||
else if (FileLnk.IsNetworkRoot(resolvedLnkPath))
|
||||
{
|
||||
isLnkDirectory = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
TargetFilePath = resolvedLnkPath;
|
||||
}
|
||||
|
||||
SetText(Path.GetFileNameWithoutExtension(TargetFilePathOrig));
|
||||
|
||||
return handled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace SystemTrayMenu.Helper
|
|||
RowData rowData = (RowData)menu.Tag;
|
||||
if (rowData != null)
|
||||
{
|
||||
path = rowData.TargetFilePath;
|
||||
path = rowData.ResolvedPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -39,5 +39,5 @@ using System.Runtime.InteropServices;
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.2.9.19")]
|
||||
[assembly: AssemblyFileVersion("1.2.9.19")]
|
||||
[assembly: AssemblyVersion("1.2.9.20")]
|
||||
[assembly: AssemblyFileVersion("1.2.9.20")]
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
internal partial class Menu : Form
|
||||
{
|
||||
private const int CornerRadius = 20;
|
||||
private const string RowFilterShowAll = "[SortIndex] LIKE '%0%'";
|
||||
private readonly Fading fading = new();
|
||||
private bool isShowing;
|
||||
private bool directionToRight;
|
||||
|
@ -234,7 +235,22 @@ namespace SystemTrayMenu.UserInterface
|
|||
internal void ResetSearchText()
|
||||
{
|
||||
textBoxSearch.Text = string.Empty;
|
||||
dgv.FirstDisplayedScrollingRowIndex = 0;
|
||||
if (dgv.Rows.Count > 0)
|
||||
{
|
||||
dgv.FirstDisplayedScrollingRowIndex = 0;
|
||||
}
|
||||
|
||||
AdjustScrollbar();
|
||||
}
|
||||
|
||||
internal void RefreshSearchText()
|
||||
{
|
||||
TextBoxSearch_TextChanged(textBoxSearch, null);
|
||||
if (dgv.Rows.Count > 0)
|
||||
{
|
||||
dgv.FirstDisplayedScrollingRowIndex = 0;
|
||||
}
|
||||
|
||||
AdjustScrollbar();
|
||||
}
|
||||
|
||||
|
@ -421,6 +437,11 @@ namespace SystemTrayMenu.UserInterface
|
|||
}
|
||||
}
|
||||
|
||||
internal void TimerUpdateIconsStart()
|
||||
{
|
||||
timerUpdateIcons.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the position and size of the menu.
|
||||
/// </summary>
|
||||
|
@ -757,7 +778,8 @@ namespace SystemTrayMenu.UserInterface
|
|||
ScrollbarVisible = false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(data.DefaultView.RowFilter))
|
||||
if (string.IsNullOrEmpty(textBoxSearch.Text) &&
|
||||
dgv.Height != dgvHeightNew)
|
||||
{
|
||||
dgv.Height = dgvHeightNew;
|
||||
}
|
||||
|
@ -765,13 +787,13 @@ namespace SystemTrayMenu.UserInterface
|
|||
|
||||
private void AdjustDataGridViewWidth()
|
||||
{
|
||||
DataGridViewExtensions.FastAutoSizeColumns(dgv);
|
||||
|
||||
if (dgv.Columns[1].Width < 60)
|
||||
if (!string.IsNullOrEmpty(textBoxSearch.Text))
|
||||
{
|
||||
dgv.Columns[1].Width = 60;
|
||||
return;
|
||||
}
|
||||
|
||||
DataGridViewExtensions.FastAutoSizeColumns(dgv);
|
||||
|
||||
int widthIcon = dgv.Columns[0].Width;
|
||||
int widthText = dgv.Columns[1].Width;
|
||||
int widthScrollbar = 0;
|
||||
|
@ -780,14 +802,23 @@ namespace SystemTrayMenu.UserInterface
|
|||
widthScrollbar = customScrollbar.Width;
|
||||
}
|
||||
|
||||
if (tableLayoutPanelBottom.Width > (widthIcon + widthText + widthScrollbar))
|
||||
using Graphics gfx = labelTitle.CreateGraphics();
|
||||
gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
|
||||
int withTitle = (int)(gfx.MeasureString(
|
||||
labelTitle.Text + "___",
|
||||
dgv.RowTemplate.DefaultCellStyle.Font).Width + 0.5);
|
||||
|
||||
if (withTitle > (widthIcon + widthText + widthScrollbar))
|
||||
{
|
||||
dgv.Width = tableLayoutPanelBottom.Width - widthScrollbar;
|
||||
dgv.Columns[1].Width = tableLayoutPanelBottom.Width - widthIcon - widthScrollbar;
|
||||
tableLayoutPanelDgvAndScrollbar.MinimumSize = new Size(withTitle, 0);
|
||||
dgv.Width = withTitle - widthScrollbar;
|
||||
dgv.Columns[1].Width = dgv.Width - widthIcon;
|
||||
}
|
||||
else
|
||||
{
|
||||
tableLayoutPanelDgvAndScrollbar.MinimumSize = new Size(widthIcon + widthText + widthScrollbar, 0);
|
||||
dgv.Width = widthIcon + widthText;
|
||||
dgv.Columns[1].Width = dgv.Width - widthIcon;
|
||||
}
|
||||
|
||||
tableLayoutPanelSearch.MinimumSize = new Size(dgv.Width + widthScrollbar, 0);
|
||||
|
@ -867,7 +898,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
if (Properties.Settings.Default.ShowOnlyAsSearchResult &&
|
||||
isSearchStringEmpty)
|
||||
{
|
||||
data.DefaultView.RowFilter = "[SortIndex] LIKE '%0%'";
|
||||
data.DefaultView.RowFilter = RowFilterShowAll;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -893,8 +924,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
RowData rowData = (RowData)row[2];
|
||||
if (Properties.Settings.Default.ShowOnlyAsSearchResult &&
|
||||
rowData.ShowOnlyWhenSearch)
|
||||
if (rowData.IsAddionalItem && Properties.Settings.Default.ShowOnlyAsSearchResult)
|
||||
{
|
||||
row[columnSortIndex] = 99;
|
||||
}
|
||||
|
@ -934,7 +964,8 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
RowData rowData = (RowData)row.Cells[2].Value;
|
||||
|
||||
if (!isSearchStringEmpty || !rowData.ShowOnlyWhenSearch)
|
||||
if (!isSearchStringEmpty ||
|
||||
!(rowData.IsAddionalItem && Properties.Settings.Default.ShowOnlyAsSearchResult))
|
||||
{
|
||||
rowData.RowIndex = row.Index;
|
||||
|
||||
|
@ -1113,7 +1144,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
if (rowData.IconLoading)
|
||||
{
|
||||
iconsToUpdate++;
|
||||
row.Cells[0].Value = rowData.ReadLoadedIcon();
|
||||
row.Cells[0].Value = rowData.ReadIcon(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ namespace SystemTrayMenu.Utilities
|
|||
|
||||
internal static class DataGridViewExtensions
|
||||
{
|
||||
private const float WidthMin = 100f;
|
||||
|
||||
/// <summary>
|
||||
/// dgv.AutoResizeColumns() was too slow ~45ms.
|
||||
/// </summary>
|
||||
|
@ -22,13 +24,12 @@ namespace SystemTrayMenu.Utilities
|
|||
using Graphics gfx = dgv.CreateGraphics();
|
||||
int i = 1;
|
||||
gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
|
||||
float widthMax = dgv.Columns[i].HeaderCell.Size.Width;
|
||||
float widthMax = WidthMin;
|
||||
foreach (DataGridViewRow row in rows)
|
||||
{
|
||||
float checkWidth = gfx.MeasureString(
|
||||
row.Cells[i].Value.ToString() + "___",
|
||||
dgv.RowTemplate.DefaultCellStyle.Font)
|
||||
.Width;
|
||||
dgv.RowTemplate.DefaultCellStyle.Font).Width;
|
||||
if (checkWidth > widthMax)
|
||||
{
|
||||
widthMax = checkWidth;
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace SystemTrayMenu.Utilities
|
|||
|
||||
public static class DirectoryBySearchPattern
|
||||
{
|
||||
public static string[] GetFiles(string path, string searchPatternCombined)
|
||||
public static List<string> GetFiles(string path, string searchPatternCombined)
|
||||
{
|
||||
string[] searchPatterns = searchPatternCombined.Split('|');
|
||||
List<string> files = new();
|
||||
|
@ -18,8 +18,7 @@ namespace SystemTrayMenu.Utilities
|
|||
files.AddRange(System.IO.Directory.GetFiles(path, searchPattern));
|
||||
}
|
||||
|
||||
files.Sort();
|
||||
return files.ToArray();
|
||||
return files;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,9 +69,17 @@ namespace SystemTrayMenu.Utilities
|
|||
return cleared;
|
||||
}
|
||||
|
||||
public static void RemoveIconFromCache(string path)
|
||||
{
|
||||
if (DictIconCacheMainMenu.Remove(path, out Icon iconToRemove))
|
||||
{
|
||||
iconToRemove?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static Icon GetFileIconWithCache(
|
||||
string pathOrig,
|
||||
string path,
|
||||
string resolvedPath,
|
||||
bool linkOverlay,
|
||||
bool updateIconInBackground,
|
||||
bool isMainMenu,
|
||||
|
@ -79,10 +87,10 @@ namespace SystemTrayMenu.Utilities
|
|||
string keyPath = "")
|
||||
{
|
||||
loading = false;
|
||||
string extension = Path.GetExtension(pathOrig);
|
||||
string extension = Path.GetExtension(path);
|
||||
IconSize size = IconSize.Large;
|
||||
|
||||
string key = pathOrig;
|
||||
string key = path;
|
||||
if (!string.IsNullOrEmpty(keyPath))
|
||||
{
|
||||
key = keyPath;
|
||||
|
@ -103,7 +111,7 @@ namespace SystemTrayMenu.Utilities
|
|||
new Thread(UpdateIconInBackground).Start();
|
||||
void UpdateIconInBackground()
|
||||
{
|
||||
DictIconCache(isMainMenu).GetOrAdd(key, GetIconSTA(pathOrig, path, linkOverlay, size, null));
|
||||
DictIconCache(isMainMenu).GetOrAdd(key, GetIconSTA(path, resolvedPath, linkOverlay, size, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +121,6 @@ namespace SystemTrayMenu.Utilities
|
|||
|
||||
public static Icon GetFolderIconWithCache(
|
||||
string path,
|
||||
FolderType folderType,
|
||||
bool linkOverlay,
|
||||
bool updateIconInBackground,
|
||||
bool isMainMenu,
|
||||
|
@ -156,25 +163,25 @@ namespace SystemTrayMenu.Utilities
|
|||
|
||||
Icon GetFolder(string keyExtension)
|
||||
{
|
||||
return GetIconSTA(path, path, linkOverlay, size, folderType);
|
||||
return GetIconSTA(path, path, linkOverlay, size, true);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
public static Icon GetIconSTA(string pathOrig, string path, bool linkOverlay, IconSize size, FolderType? folderType)
|
||||
public static Icon GetIconSTA(string path, string resolvedPath, bool linkOverlay, IconSize size, bool isFolder)
|
||||
{
|
||||
Icon icon = null;
|
||||
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
|
||||
{
|
||||
icon = GetIcon(pathOrig, path, linkOverlay, size, folderType);
|
||||
icon = GetIcon(path, resolvedPath, linkOverlay, size, isFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread staThread = new(new ParameterizedThreadStart(StaThreadMethod));
|
||||
void StaThreadMethod(object obj)
|
||||
{
|
||||
icon = GetIcon(pathOrig, path, linkOverlay, size, folderType);
|
||||
icon = GetIcon(path, resolvedPath, linkOverlay, size, isFolder);
|
||||
}
|
||||
|
||||
staThread.SetApartmentState(ApartmentState.STA);
|
||||
|
@ -227,17 +234,17 @@ namespace SystemTrayMenu.Utilities
|
|||
return isExtensionWithSameIcon;
|
||||
}
|
||||
|
||||
private static Icon GetIcon(string path, string pathOrig, bool linkOverlay, IconSize size, FolderType? type)
|
||||
private static Icon GetIcon(string path, string resolvedPath, bool linkOverlay, IconSize size, bool isFolder)
|
||||
{
|
||||
Icon icon;
|
||||
if (Path.GetExtension(path).Equals(".ico", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
icon = Icon.ExtractAssociatedIcon(path);
|
||||
}
|
||||
else if (Path.GetExtension(pathOrig).Equals(".ico", StringComparison.InvariantCultureIgnoreCase) &&
|
||||
File.Exists(pathOrig))
|
||||
else if (Path.GetExtension(resolvedPath).Equals(".ico", StringComparison.InvariantCultureIgnoreCase) &&
|
||||
File.Exists(resolvedPath))
|
||||
{
|
||||
icon = Icon.ExtractAssociatedIcon(pathOrig);
|
||||
icon = Icon.ExtractAssociatedIcon(resolvedPath);
|
||||
if (linkOverlay)
|
||||
{
|
||||
icon = AddIconOverlay(icon, Properties.Resources.LinkArrow);
|
||||
|
@ -246,9 +253,8 @@ namespace SystemTrayMenu.Utilities
|
|||
else
|
||||
{
|
||||
NativeMethods.SHFILEINFO shFileInfo = default;
|
||||
uint flags = GetFlags(linkOverlay, size, type);
|
||||
uint attribute = type == null ? NativeMethods.FileAttributeNormal :
|
||||
NativeMethods.FileAttributeDirectory;
|
||||
uint flags = GetFlags(linkOverlay, size);
|
||||
uint attribute = isFolder ? NativeMethods.FileAttributeDirectory : NativeMethods.FileAttributeNormal;
|
||||
IntPtr imageList = NativeMethods.Shell32SHGetFileInfo(
|
||||
path, attribute, ref shFileInfo, (uint)Marshal.SizeOf(shFileInfo), flags);
|
||||
icon = GetIcon(path, linkOverlay, shFileInfo, imageList);
|
||||
|
@ -257,7 +263,7 @@ namespace SystemTrayMenu.Utilities
|
|||
return icon;
|
||||
}
|
||||
|
||||
private static uint GetFlags(bool linkOverlay, IconSize size, FolderType? folderType)
|
||||
private static uint GetFlags(bool linkOverlay, IconSize size)
|
||||
{
|
||||
uint flags = NativeMethods.ShgfiIcon | NativeMethods.ShgfiSYSICONINDEX;
|
||||
if (linkOverlay)
|
||||
|
@ -265,11 +271,6 @@ namespace SystemTrayMenu.Utilities
|
|||
flags += NativeMethods.ShgfiLINKOVERLAY;
|
||||
}
|
||||
|
||||
if (folderType == FolderType.Open)
|
||||
{
|
||||
flags += NativeMethods.ShgfiOPENICON;
|
||||
}
|
||||
|
||||
if (size == IconSize.Small)
|
||||
{
|
||||
flags += NativeMethods.ShgfiSMALLICON;
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace SystemTrayMenu.Utilities
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Shell32;
|
||||
using SystemTrayMenu.DataClasses;
|
||||
|
||||
internal static class FolderOptions
|
||||
{
|
||||
|
@ -55,38 +56,37 @@ namespace SystemTrayMenu.Utilities
|
|||
}
|
||||
}
|
||||
|
||||
internal static bool IsHidden(string path, ref bool hiddenEntry)
|
||||
internal static bool IsHidden(RowData rowData)
|
||||
{
|
||||
bool isDirectoryToHide = false;
|
||||
if (path.Length < 260)
|
||||
if (rowData.Path.Length >= 260)
|
||||
{
|
||||
try
|
||||
Log.Info($"path too long (>=260):'{rowData.Path}'");
|
||||
return isDirectoryToHide;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
FileAttributes attributes = File.GetAttributes(rowData.Path);
|
||||
rowData.HiddenEntry = attributes.HasFlag(FileAttributes.Hidden);
|
||||
bool systemEntry = attributes.HasFlag(
|
||||
FileAttributes.Hidden | FileAttributes.System);
|
||||
if (Properties.Settings.Default.SystemSettingsShowHiddenFiles)
|
||||
{
|
||||
FileAttributes attributes = File.GetAttributes(path);
|
||||
hiddenEntry = attributes.HasFlag(FileAttributes.Hidden);
|
||||
bool systemEntry = attributes.HasFlag(
|
||||
FileAttributes.Hidden | FileAttributes.System);
|
||||
if (Properties.Settings.Default.SystemSettingsShowHiddenFiles)
|
||||
{
|
||||
if ((hideHiddenEntries && hiddenEntry) ||
|
||||
(hideSystemEntries && systemEntry))
|
||||
{
|
||||
isDirectoryToHide = true;
|
||||
}
|
||||
}
|
||||
else if (hiddenEntry && Properties.Settings.Default.NeverShowHiddenFiles)
|
||||
if ((hideHiddenEntries && rowData.HiddenEntry) ||
|
||||
(hideSystemEntries && systemEntry))
|
||||
{
|
||||
isDirectoryToHide = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else if (rowData.HiddenEntry && Properties.Settings.Default.NeverShowHiddenFiles)
|
||||
{
|
||||
Log.Warn($"path:'{path}'", ex);
|
||||
isDirectoryToHide = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Info($"path too long (>=260):'{path}'");
|
||||
Log.Warn($"path:'{rowData.Path}'", ex);
|
||||
}
|
||||
|
||||
return isDirectoryToHide;
|
||||
|
|
Loading…
Reference in a new issue