This commit is contained in:
Stephan Maier
2024-08-27 08:10:27 +02:00
parent eb5c2fa502
commit 647f938eee
617 changed files with 73086 additions and 7137 deletions

View File

@@ -0,0 +1,115 @@
// <copyright file="App.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace FSI.BT.Tools.SystemTrayMenu
{
using System;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;
using FSI.BT.Tools.SystemTrayMenu.Business;
using FSI.BT.Tools.SystemTrayMenu.Helper.Updater;
using FSI.BT.Tools.SystemTrayMenu.UserInterface;
using FSI.BT.Tools.SystemTrayMenu.Utilities;
using FSI.BT.Tools.Global.Utilities;
/// <summary>
/// App contains the notifyicon, the taskbarform and the menus.
/// </summary>
internal class App : IDisposable
{
private readonly AppNotifyIcon menuNotifyIcon = new();
private readonly Menus menus = new();
private readonly TaskbarForm taskbarForm = null;
public App()
{
AppRestart.BeforeRestarting += Dispose;
SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
menus.LoadStarted += menuNotifyIcon.LoadingStart;
menus.LoadStopped += menuNotifyIcon.LoadingStop;
menuNotifyIcon.Click += MenuNotifyIcon_Click;
menuNotifyIcon.OpenLog += Log.OpenLogFile;
menus.MainPreload();
if (Global.Vars.SystemTrayMenuSettings.ShowInTaskbar)
{
taskbarForm = new TaskbarForm();
taskbarForm.FormClosed += TaskbarForm_FormClosed;
taskbarForm.Deactivate += SetStateNormal;
taskbarForm.Resize += SetStateNormal;
taskbarForm.Activated += TasbkarItemActivated;
}
BT.Tools.Global.DllImports.NativeMethods.User32ShowInactiveTopmost(taskbarForm);
//if (Global.Vars.SystemTrayMenuSettings.CheckForUpdates)
//{
// new Thread((obj) => GitHubUpdate.ActivateNewVersionFormOrCheckForUpdates(
// showWhenUpToDate: false))
// .Start();
//}
}
public void Dispose()
{
if (taskbarForm?.InvokeRequired == true)
{
taskbarForm.Invoke(Dispose);
}
else
{
AppRestart.BeforeRestarting -= Dispose;
SystemEvents.DisplaySettingsChanged -= SystemEvents_DisplaySettingsChanged;
menus.LoadStarted -= menuNotifyIcon.LoadingStart;
menus.LoadStopped -= menuNotifyIcon.LoadingStop;
menus.Dispose();
menuNotifyIcon.Click -= MenuNotifyIcon_Click;
menuNotifyIcon.OpenLog -= Log.OpenLogFile;
menuNotifyIcon.Dispose();
if (taskbarForm != null)
{
taskbarForm.FormClosed -= TaskbarForm_FormClosed;
taskbarForm.Deactivate -= SetStateNormal;
taskbarForm.Resize -= SetStateNormal;
taskbarForm.Activated -= TasbkarItemActivated;
taskbarForm.Dispose();
}
}
}
private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
menus.ReAdjustSizeAndLocation();
}
private void MenuNotifyIcon_Click()
{
menus.SwitchOpenClose(true);
}
private void TaskbarForm_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Exit();
}
/// <summary>
/// This ensures that next click on taskbaritem works as activate event/click event.
/// </summary>
private void SetStateNormal(object sender, EventArgs e)
{
if (Form.ActiveForm == taskbarForm)
{
taskbarForm.WindowState = FormWindowState.Normal;
}
}
private void TasbkarItemActivated(object sender, EventArgs e)
{
SetStateNormal(sender, e);
taskbarForm.Activate();
taskbarForm.Focus();
menus.SwitchOpenCloseByTaskbarItem();
}
}
}

View File

@@ -0,0 +1,592 @@
// <copyright file="KeyboardInput.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace FSI.BT.Tools.SystemTrayMenu.Handler
{
using System;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;
using FSI.BT.Tools.Global.Utilities;
using FSI.BT.Tools.SystemTrayMenu.DataClasses;
using FSI.BT.Tools.SystemTrayMenu.Helper;
using FSI.BT.Tools.SystemTrayMenu.Utilities;
using Menu = SystemTrayMenu.UserInterface.Menu;
internal class KeyboardInput : IDisposable
{
private readonly Menu[] menus;
private readonly KeyboardHook hook = new();
private int iRowKey = -1;
private int iMenuKey;
public KeyboardInput(Menu[] menus)
{
this.menus = menus;
}
public event Action HotKeyPressed;
public event Action ClosePressed;
public event Action<DataGridView, int> RowSelected;
public event Action<DataGridView, int> RowDeselected;
public event Action<DataGridView, int> EnterPressed;
public event Action Cleared;
public bool InUse { get; set; }
public void Dispose()
{
hook.KeyPressed -= Hook_KeyPressed;
hook.Dispose();
}
public void RegisterHotKey()
{
if (!string.IsNullOrEmpty(Global.Vars.SystemTrayMenuSettings.HotKey))
{
try
{
hook.RegisterHotKey();
hook.KeyPressed += Hook_KeyPressed;
}
catch (InvalidOperationException ex)
{
Log.Warn($"key:'{Global.Vars.SystemTrayMenuSettings.HotKey}'", ex);
Global.Vars.SystemTrayMenuSettings.HotKey = string.Empty;
//Global.Vars.SystemTrayMenuSettings.Save();
}
}
}
public void ResetSelectedByKey()
{
iRowKey = -1;
iMenuKey = 0;
}
public void CmdKeyProcessed(object sender, Keys keys)
{
sender ??= menus[iMenuKey];
switch (keys)
{
case Keys.Enter:
SelectByKey(keys);
menus[iMenuKey]?.FocusTextBox();
break;
case Keys.Left:
SelectByKey(keys);
break;
case Keys.Right:
SelectByKey(keys);
break;
case Keys.Home:
case Keys.End:
case Keys.Up:
case Keys.Down:
case Keys.Escape:
case Keys.Alt | Keys.F4:
SelectByKey(keys);
break;
case Keys.Control | Keys.F:
menus[iMenuKey]?.FocusTextBox();
break;
case Keys.Tab:
{
Menu currentMenu = (Menu)sender;
int indexOfTheCurrentMenu = GetMenuIndex(currentMenu);
int indexMax = menus.Where(m => m != null).Count() - 1;
int indexNew = 0;
if (indexOfTheCurrentMenu > 0)
{
indexNew = indexOfTheCurrentMenu - 1;
}
else
{
indexNew = indexMax;
}
menus[indexNew]?.FocusTextBox();
}
break;
case Keys.Tab | Keys.Shift:
{
Menu currentMenu = (Menu)sender;
int indexOfTheCurrentMenu = GetMenuIndex(currentMenu);
int indexMax = menus.Where(m => m != null).Count() - 1;
int indexNew = 0;
if (indexOfTheCurrentMenu < indexMax)
{
indexNew = indexOfTheCurrentMenu + 1;
}
else
{
indexNew = 0;
}
menus[indexNew]?.FocusTextBox();
}
break;
case Keys.Apps:
{
DataGridView dgv = menus[iMenuKey]?.GetDataGridView();
if (iRowKey > -1 &&
dgv.Rows.Count > iRowKey)
{
Point point = dgv.GetCellDisplayRectangle(2, iRowKey, false).Location;
RowData trigger = (RowData)dgv.Rows[iRowKey].Cells[2].Value;
MouseEventArgs mouseEventArgs = new(MouseButtons.Right, 1, point.X, point.Y, 0);
trigger.MouseDown(dgv, mouseEventArgs);
}
}
break;
default:
break;
}
int GetMenuIndex(in Menu currentMenu)
{
int index = 0;
foreach (Menu menuFindIndex in menus.Where(m => m != null))
{
if (currentMenu == menuFindIndex)
{
break;
}
index++;
}
return index;
}
}
public void SearchTextChanging()
{
ClearIsSelectedByKey();
}
public void SearchTextChanged(Menu menu, bool isSearchStringEmpty)
{
DataGridView dgv = menu.GetDataGridView();
if (isSearchStringEmpty)
{
ClearIsSelectedByKey();
}
else if (dgv.Rows.Count > 0)
{
Select(dgv, 0, true);
}
}
public void ClearIsSelectedByKey()
{
ClearIsSelectedByKey(iMenuKey, iRowKey);
}
public void Select(DataGridView dgv, int i, bool refreshview)
{
int newiMenuKey = ((Menu)dgv.TopLevelControl).Level;
if (i != iRowKey || newiMenuKey != iMenuKey)
{
ClearIsSelectedByKey();
}
iRowKey = i;
iMenuKey = newiMenuKey;
if (dgv.Rows.Count > i)
{
DataGridViewRow row = dgv.Rows[i];
RowData rowData = (RowData)row.Cells[2].Value;
if (rowData != null)
{
rowData.IsSelected = true;
}
if (refreshview)
{
row.Selected = false;
row.Selected = true;
}
}
}
private void Hook_KeyPressed(object sender, KeyPressedEventArgs e)
{
HotKeyPressed?.Invoke();
}
private bool IsAnyMenuSelectedByKey(
ref DataGridView dgv,
ref Menu menuFromSelected,
ref string textselected)
{
Menu menu = menus[iMenuKey];
bool isStillSelected = false;
if (menu != null &&
iRowKey > -1)
{
dgv = menu.GetDataGridView();
if (dgv.Rows.Count > iRowKey)
{
RowData rowData = (RowData)dgv.
Rows[iRowKey].Cells[2].Value;
if (rowData.IsSelected)
{
isStillSelected = true;
menuFromSelected = rowData.SubMenu;
textselected = dgv.Rows[iRowKey].
Cells[1].Value.ToString();
}
}
}
return isStillSelected;
}
private void SelectByKey(Keys keys, string keyInput = "", bool keepSelection = false)
{
int iRowBefore = iRowKey;
int iMenuBefore = iMenuKey;
Menu menu = menus[iMenuKey];
DataGridView dgv = null;
DataGridView dgvBefore = null;
Menu menuFromSelected = null;
string textselected = string.Empty;
bool isStillSelected = IsAnyMenuSelectedByKey(ref dgv, ref menuFromSelected, ref textselected);
if (isStillSelected)
{
if (keepSelection)
{
// If current selection is still valid for this search then skip selecting different item
if (textselected.StartsWith(keyInput, true, CultureInfo.InvariantCulture))
{
return;
}
}
dgvBefore = dgv;
}
else
{
ResetSelectedByKey();
menu = menus[iMenuKey];
dgv = menu.GetDataGridView();
}
bool toClear = false;
switch (keys)
{
case Keys.Enter:
if (iRowKey > -1 && dgv.Rows.Count > iRowKey)
{
RowData trigger = (RowData)dgv.Rows[iRowKey].Cells[2].Value;
if (trigger.IsMenuOpen || !trigger.ContainsMenu)
{
trigger.MouseClick(null, out bool toCloseByMouseClick);
trigger.DoubleClick(
new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0),
out bool toCloseByDoubleClick);
if (toCloseByMouseClick || toCloseByDoubleClick)
{
ClosePressed?.Invoke();
}
if (iRowKey > -1 && dgv.Rows.Count > iRowKey)
{
// Raise Dgv_RowPostPaint to show ProcessStarted
dgv.InvalidateRow(iRowKey);
}
}
else
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
EnterPressed.Invoke(dgv, iRowKey);
}
}
break;
case Keys.Up:
if (SelectMatchedReverse(dgv, iRowKey) ||
SelectMatchedReverse(dgv, dgv.Rows.Count - 1))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
break;
case Keys.Down:
if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
break;
case Keys.Home:
if (SelectMatched(dgv, 0))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
break;
case Keys.End:
if (SelectMatchedReverse(dgv, dgv.Rows.Count - 1))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
break;
case Keys.Left:
bool nextMenuLocationIsLeft = menus[iMenuKey + 1] != null && menus[iMenuKey + 1].Location.X < menus[iMenuKey].Location.X;
bool previousMenuLocationIsRight = iMenuKey > 0 && menus[iMenuKey]?.Location.X < menus[iMenuKey - 1]?.Location.X;
if (nextMenuLocationIsLeft || previousMenuLocationIsRight)
{
SelectNextMenu(iRowBefore, ref dgv, dgvBefore, menuFromSelected, isStillSelected, ref toClear);
}
else if (iMenuKey > 0)
{
SelectPreviousMenu(iRowBefore, ref menu, ref dgv, dgvBefore, ref toClear);
}
break;
case Keys.Right:
bool nextMenuLocationIsRight = menus[iMenuKey + 1]?.Location.X > menus[iMenuKey]?.Location.X;
bool previousMenuLocationIsLeft = iMenuKey > 0 && menus[iMenuKey]?.Location.X > menus[iMenuKey - 1]?.Location.X;
if (nextMenuLocationIsRight || previousMenuLocationIsLeft)
{
SelectNextMenu(iRowBefore, ref dgv, dgvBefore, menuFromSelected, isStillSelected, ref toClear);
}
else if (iMenuKey > 0)
{
SelectPreviousMenu(iRowBefore, ref menu, ref dgv, dgvBefore, ref toClear);
}
break;
case Keys.Escape:
case Keys.Alt | Keys.F4:
RowDeselected(dgvBefore, iRowBefore);
iMenuKey = 0;
iRowKey = -1;
toClear = true;
ClosePressed?.Invoke();
break;
default:
if (!string.IsNullOrEmpty(keyInput))
{
if (SelectMatched(dgv, iRowKey, keyInput) ||
SelectMatched(dgv, 0, keyInput))
{
RowDeselected(null, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
else if (isStillSelected)
{
iRowKey = iRowBefore - 1;
if (SelectMatched(dgv, iRowKey, keyInput) ||
SelectMatched(dgv, 0, keyInput))
{
RowDeselected(null, iRowBefore);
SelectRow(dgv, iRowKey);
}
else
{
iRowKey = iRowBefore;
}
}
}
break;
}
if (isStillSelected && toClear)
{
ClearIsSelectedByKey(iMenuBefore, iRowBefore);
}
}
private void SelectPreviousMenu(int iRowBefore, ref Menu menu, ref DataGridView dgv, DataGridView dgvBefore, ref bool toClear)
{
if (iMenuKey > 0)
{
if (menus[iMenuKey - 1] != null)
{
iMenuKey -= 1;
iRowKey = -1;
menu = menus[iMenuKey];
dgv = menu.GetDataGridView();
if (SelectMatched(dgv, dgv.SelectedRows[0].Index) ||
SelectMatched(dgv, 0))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
}
}
else
{
RowDeselected(dgvBefore, iRowBefore);
iMenuKey = 0;
iRowKey = -1;
toClear = true;
Cleared?.Invoke();
}
}
private void SelectNextMenu(int iRowBefore, ref DataGridView dgv, DataGridView dgvBefore, Menu menuFromSelected, bool isStillSelected, ref bool toClear)
{
int iMenuKeyNext = iMenuKey + 1;
if (isStillSelected)
{
if (menuFromSelected != null &&
menuFromSelected == menus[iMenuKeyNext])
{
dgv = menuFromSelected.GetDataGridView();
if (dgv.Rows.Count > 0)
{
iMenuKey += 1;
iRowKey = -1;
if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
}
}
}
else
{
iRowKey = -1;
iMenuKey = menus.Where(m => m != null).Count() - 1;
if (menus[iMenuKey] != null)
{
dgv = menus[iMenuKey].GetDataGridView();
if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0))
{
RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey);
toClear = true;
}
}
}
}
private void SelectRow(DataGridView dgv, int iRowKey)
{
InUse = true;
RowSelected(dgv, iRowKey);
}
private bool SelectMatched(DataGridView dgv, int indexStart, string keyInput = "")
{
bool found = false;
for (int i = indexStart; i < dgv.Rows.Count; i++)
{
if (Select(dgv, i, keyInput))
{
found = true;
break;
}
}
return found;
}
private bool SelectMatchedReverse(DataGridView dgv, int indexStart, string keyInput = "")
{
bool found = false;
for (int i = indexStart; i > -1; i--)
{
if (Select(dgv, i, keyInput))
{
found = true;
break;
}
}
return found;
}
private bool Select(DataGridView dgv, int i, string keyInput = "")
{
bool found = false;
if (i > -1 &&
i != iRowKey &&
dgv.Rows.Count > i)
{
DataGridViewRow row = dgv.Rows[i];
RowData rowData = (RowData)row.Cells[2].Value;
string text = row.Cells[1].Value.ToString();
if (text.StartsWith(keyInput, true, CultureInfo.InvariantCulture))
{
iRowKey = rowData.RowIndex;
rowData.IsSelected = true;
row.Selected = false;
row.Selected = true;
if (row.Index < dgv.FirstDisplayedScrollingRowIndex)
{
dgv.FirstDisplayedScrollingRowIndex = row.Index;
}
else if (row.Index >=
dgv.FirstDisplayedScrollingRowIndex +
dgv.DisplayedRowCount(false))
{
dgv.FirstDisplayedScrollingRowIndex = row.Index -
dgv.DisplayedRowCount(false) + 1;
}
found = true;
}
}
return found;
}
private void ClearIsSelectedByKey(int menuIndex, int rowIndex)
{
Menu menu = menus[menuIndex];
if (menu != null && rowIndex > -1)
{
DataGridView dgv = menu.GetDataGridView();
if (dgv.Rows.Count > rowIndex)
{
DataGridViewRow row = dgv.Rows[rowIndex];
row.Selected = false;
RowData rowData = (RowData)row.Cells[2].Value;
if (rowData != null)
{
rowData.IsSelected = false;
rowData.IsClicking = false;
}
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,270 @@
// <copyright file="MenusHelpers.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace FSI.BT.Tools.SystemTrayMenu.Business
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using FSI.BT.Tools.Global.Utilities;
using FSI.BT.Tools.SystemTrayMenu.DataClasses;
using FSI.BT.Tools.SystemTrayMenu.Helper;
using FSI.BT.Tools.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 Global.Vars.SystemTrayMenuSettings.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 (Global.Vars.SystemTrayMenuSettings.SortByTypeAndNameWindowsExplorerSort)
{
rowDatas = rowDatas.OrderByDescending(x => x.IsFolder)
.ThenBy(x => x.Text, new WindowsExplorerSort()).ToList();
}
else if (Global.Vars.SystemTrayMenuSettings.SortByTypeAndDate)
{
rowDatas = rowDatas.OrderByDescending(x => x.IsFolder)
.ThenByDescending(x => x.FileInfo.LastWriteTime).ToList();
}
else if (Global.Vars.SystemTrayMenuSettings.SortByFileExtensionAndName)
{
rowDatas = rowDatas.OrderBy(x => x.FileExtension).ThenBy(x => x.Text).ToList();
}
else if (Global.Vars.SystemTrayMenuSettings.SortByName)
{
rowDatas = rowDatas.OrderBy(x => x.Text).ToList();
}
else if (Global.Vars.SystemTrayMenuSettings.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);
}
}
}
}

View File

@@ -0,0 +1,46 @@
// <copyright file="WaitLeave.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace FSI.BT.Tools.SystemTrayMenu.Handler
{
using System;
using FSI.BT.Tools.SystemTrayMenu.Utilities;
using Timer = System.Windows.Forms.Timer;
internal class WaitLeave : IDisposable
{
private readonly Timer timerLeaveCheck = new();
public WaitLeave(int timeUntilTriggered)
{
timerLeaveCheck.Interval = timeUntilTriggered;
timerLeaveCheck.Tick += TimerLeaveCheckTick;
}
public event Action LeaveTriggered;
public void Dispose()
{
timerLeaveCheck.Tick -= TimerLeaveCheckTick;
timerLeaveCheck.Dispose();
}
internal void Start()
{
timerLeaveCheck.Stop();
timerLeaveCheck.Start();
}
internal void Stop()
{
timerLeaveCheck.Stop();
}
internal void TimerLeaveCheckTick(object sender, EventArgs e)
{
timerLeaveCheck.Stop();
LeaveTriggered?.Invoke();
}
}
}

View File

@@ -0,0 +1,220 @@
// <copyright file="WaitToLoadMenu.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace FSI.BT.Tools.SystemTrayMenu.Handler
{
using System;
using System.Windows.Forms;
using FSI.BT.Tools.SystemTrayMenu.DataClasses;
using FSI.BT.Tools.SystemTrayMenu.UserInterface;
using FSI.BT.Tools.SystemTrayMenu.Utilities;
using Timer = System.Windows.Forms.Timer;
internal class WaitToLoadMenu : IDisposable
{
private readonly Timer timerStartLoad = new();
private DataGridView dgv;
private int rowIndex;
private DataGridView dgvTmp;
private int rowIndexTmp;
private int mouseMoveEvents;
private DateTime dateTimeLastMouseMoveEvent = DateTime.Now;
private bool checkForMouseActive = true;
internal WaitToLoadMenu()
{
timerStartLoad.Interval = Global.Vars.SystemTrayMenuSettings.TimeUntilOpens;
timerStartLoad.Tick += WaitStartLoad_Tick;
}
internal event Action<RowData> StartLoadMenu;
internal event Action<int> CloseMenu;
internal event Action StopLoadMenu;
internal event Action<DataGridView, int> MouseEnterOk;
internal bool MouseActive { get; set; }
public void Dispose()
{
timerStartLoad.Tick -= WaitStartLoad_Tick;
timerStartLoad.Stop();
timerStartLoad.Dispose();
dgv?.Dispose();
dgvTmp?.Dispose();
}
internal void MouseEnter(object sender, DataGridViewCellEventArgs e)
{
if (MouseActive)
{
DataGridView dgv = (DataGridView)sender;
if (dgv.Rows.Count > e.RowIndex)
{
MouseEnterOk(dgv, e.RowIndex);
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
checkForMouseActive = true;
SetData(dgv, e.RowIndex);
timerStartLoad.Start();
}
}
else
{
dgvTmp = (DataGridView)sender;
rowIndexTmp = e.RowIndex;
}
}
internal void RowSelected(DataGridView dgv, int rowIndex)
{
if (dgv.Rows.Count > rowIndex)
{
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
SetData(dgv, rowIndex);
MouseActive = false;
checkForMouseActive = false;
timerStartLoad.Start();
}
}
internal void MouseLeave(object sender, DataGridViewCellEventArgs e)
{
if (MouseActive)
{
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
ResetData((DataGridView)sender, e.RowIndex);
}
}
internal void RowDeselected(DataGridView dgv, int rowIndex)
{
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
ResetData(dgv, rowIndex);
MouseActive = false;
}
internal void ClickOpensInstantly(DataGridView dgv, int rowIndex)
{
if (dgv.Rows.Count > rowIndex)
{
timerStartLoad.Stop();
SetData(dgv, rowIndex);
MouseActive = true;
checkForMouseActive = false;
CallOpenMenuNow();
}
}
internal void EnterOpensInstantly(DataGridView dgv, int rowIndex)
{
if (dgv.Rows.Count > rowIndex)
{
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
SetData(dgv, rowIndex);
MouseActive = false;
checkForMouseActive = false;
CallOpenMenuNow();
}
}
internal void MouseMove(object sender, MouseEventArgs e)
{
if (!MouseActive)
{
if (mouseMoveEvents > 6)
{
MouseActive = true;
if (dgvTmp != null && !dgvTmp.IsDisposed)
{
MouseEnter(dgvTmp, new DataGridViewCellEventArgs(
0, rowIndexTmp));
}
mouseMoveEvents = 0;
}
else if (DateTime.Now - dateTimeLastMouseMoveEvent <
new TimeSpan(0, 0, 0, 0, 200))
{
mouseMoveEvents++;
}
else
{
dateTimeLastMouseMoveEvent = DateTime.Now;
mouseMoveEvents = 0;
}
}
}
private void WaitStartLoad_Tick(object sender, EventArgs e)
{
timerStartLoad.Stop();
if (!checkForMouseActive || MouseActive)
{
CallOpenMenuNow();
}
}
private void CallOpenMenuNow()
{
if (dgv.Rows.Count > rowIndex)
{
RowData rowData = (RowData)dgv.Rows[rowIndex].Cells[2].Value;
Menu menu = (Menu)dgv.FindForm();
rowData.Level = menu.Level;
if (rowData.ContainsMenu)
{
CloseMenu.Invoke(rowData.Level + 2);
}
CloseMenu.Invoke(rowData.Level + 1);
if (!rowData.IsContextMenuOpen &&
rowData.ContainsMenu &&
rowData.Level + 1 < MenuDefines.MenusMax)
{
StartLoadMenu.Invoke(rowData);
}
}
}
private void SetData(DataGridView dgv, int rowIndex)
{
dgvTmp = null;
this.dgv = dgv;
this.rowIndex = rowIndex;
RowData rowData = (RowData)dgv.Rows[rowIndex].Cells[2].Value;
if (rowData != null)
{
rowData.IsSelected = true;
}
dgv.Rows[rowIndex].Selected = false;
dgv.Rows[rowIndex].Selected = true;
}
private void ResetData(DataGridView dgv, int rowIndex)
{
if (dgv != null && dgv.Rows.Count > rowIndex)
{
RowData rowData = (RowData)dgv.Rows[rowIndex].Cells[2].Value;
if (rowData != null)
{
rowData.IsSelected = false;
rowData.IsClicking = false;
dgv.Rows[rowIndex].Selected = false;
this.dgv = null;
this.rowIndex = 0;
}
}
}
}
}