Not enough memory resources are available to process this command. (#442), version 1.3.1.9

This commit is contained in:
Markus Hofknecht 2022-10-20 17:55:54 +02:00
parent 87dbd64c73
commit 1d4820c946
19 changed files with 735 additions and 569 deletions

View file

@ -24,27 +24,20 @@ namespace SystemTrayMenu
public App() public App()
{ {
AppRestart.BeforeRestarting += Dispose; AppRestart.BeforeRestarting += Dispose;
SystemEvents.DisplaySettingsChanged += (s, e) => SystemEvents_DisplaySettingsChanged(); SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
menus.LoadStarted += menuNotifyIcon.LoadingStart; menus.LoadStarted += menuNotifyIcon.LoadingStart;
menus.LoadStopped += menuNotifyIcon.LoadingStop; menus.LoadStopped += menuNotifyIcon.LoadingStop;
menuNotifyIcon.Click += () => menus.SwitchOpenClose(true); menuNotifyIcon.Click += MenuNotifyIcon_Click;
menuNotifyIcon.OpenLog += Log.OpenLogFile; menuNotifyIcon.OpenLog += Log.OpenLogFile;
menus.MainPreload(); menus.MainPreload();
if (Properties.Settings.Default.ShowInTaskbar) if (Properties.Settings.Default.ShowInTaskbar)
{ {
taskbarForm = new TaskbarForm(); taskbarForm = new TaskbarForm();
taskbarForm.FormClosed += (s, e) => Application.Exit(); taskbarForm.FormClosed += TaskbarForm_FormClosed;
taskbarForm.Deactivate += (s, e) => SetStateNormal(); taskbarForm.Deactivate += SetStateNormal;
taskbarForm.Resize += (s, e) => SetStateNormal(); taskbarForm.Resize += SetStateNormal;
taskbarForm.Activated += TasbkarItemActivated; taskbarForm.Activated += TasbkarItemActivated;
void TasbkarItemActivated(object sender, EventArgs e)
{
SetStateNormal();
taskbarForm.Activate();
taskbarForm.Focus();
menus.SwitchOpenCloseByTaskbarItem();
}
} }
DllImports.NativeMethods.User32ShowInactiveTopmost(taskbarForm); DllImports.NativeMethods.User32ShowInactiveTopmost(taskbarForm);
@ -65,27 +58,57 @@ namespace SystemTrayMenu
} }
else else
{ {
taskbarForm?.Dispose(); AppRestart.BeforeRestarting -= Dispose;
SystemEvents.DisplaySettingsChanged -= (s, e) => SystemEvents_DisplaySettingsChanged(); SystemEvents.DisplaySettingsChanged -= SystemEvents_DisplaySettingsChanged;
menus.LoadStarted -= menuNotifyIcon.LoadingStart;
menus.LoadStopped -= menuNotifyIcon.LoadingStop;
menus.Dispose(); menus.Dispose();
menuNotifyIcon.Click -= MenuNotifyIcon_Click;
menuNotifyIcon.OpenLog -= Log.OpenLogFile;
menuNotifyIcon.Dispose(); menuNotifyIcon.Dispose();
if (taskbarForm != null)
{
taskbarForm.FormClosed -= TaskbarForm_FormClosed;
taskbarForm.Deactivate -= SetStateNormal;
taskbarForm.Resize -= SetStateNormal;
taskbarForm.Activated -= TasbkarItemActivated;
taskbarForm.Dispose();
}
} }
} }
private void SystemEvents_DisplaySettingsChanged() private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{ {
menus.ReAdjustSizeAndLocation(); menus.ReAdjustSizeAndLocation();
} }
private void MenuNotifyIcon_Click()
{
menus.SwitchOpenClose(true);
}
private void TaskbarForm_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Exit();
}
/// <summary> /// <summary>
/// This ensures that next click on taskbaritem works as activate event/click event. /// This ensures that next click on taskbaritem works as activate event/click event.
/// </summary> /// </summary>
private void SetStateNormal() private void SetStateNormal(object sender, EventArgs e)
{ {
if (Form.ActiveForm == taskbarForm) if (Form.ActiveForm == taskbarForm)
{ {
taskbarForm.WindowState = FormWindowState.Normal; taskbarForm.WindowState = FormWindowState.Normal;
} }
} }
private void TasbkarItemActivated(object sender, EventArgs e)
{
SetStateNormal(sender, e);
taskbarForm.Activate();
taskbarForm.Focus();
menus.SwitchOpenCloseByTaskbarItem();
}
} }
} }

View file

@ -27,33 +27,34 @@ namespace SystemTrayMenu.Handler
this.menus = menus; this.menus = menus;
} }
internal event EventHandlerEmpty HotKeyPressed; public event Action HotKeyPressed;
internal event EventHandlerEmpty ClosePressed; public event Action ClosePressed;
internal event Action<DataGridView, int> RowSelected; public event Action<DataGridView, int> RowSelected;
internal event Action<int, DataGridView> RowDeselected; public event Action<DataGridView, int> RowDeselected;
internal event Action<DataGridView, int> EnterPressed; public event Action<DataGridView, int> EnterPressed;
internal event EventHandlerEmpty Cleared; public event Action Cleared;
internal bool InUse { get; set; } public bool InUse { get; set; }
public void Dispose() public void Dispose()
{ {
hook.KeyPressed -= Hook_KeyPressed;
hook.Dispose(); hook.Dispose();
} }
internal void RegisterHotKey() public void RegisterHotKey()
{ {
if (!string.IsNullOrEmpty(Properties.Settings.Default.HotKey)) if (!string.IsNullOrEmpty(Properties.Settings.Default.HotKey))
{ {
try try
{ {
hook.RegisterHotKey(); hook.RegisterHotKey();
hook.KeyPressed += (sender, e) => HotKeyPressed?.Invoke(); hook.KeyPressed += Hook_KeyPressed;
} }
catch (InvalidOperationException ex) catch (InvalidOperationException ex)
{ {
@ -64,13 +65,13 @@ namespace SystemTrayMenu.Handler
} }
} }
internal void ResetSelectedByKey() public void ResetSelectedByKey()
{ {
iRowKey = -1; iRowKey = -1;
iMenuKey = 0; iMenuKey = 0;
} }
internal void CmdKeyProcessed(object sender, Keys keys) public void CmdKeyProcessed(object sender, Keys keys)
{ {
sender ??= menus[iMenuKey]; sender ??= menus[iMenuKey];
@ -171,12 +172,12 @@ namespace SystemTrayMenu.Handler
} }
} }
internal void SearchTextChanging() public void SearchTextChanging()
{ {
ClearIsSelectedByKey(); ClearIsSelectedByKey();
} }
internal void SearchTextChanged(Menu menu, bool isSearchStringEmpty) public void SearchTextChanged(Menu menu, bool isSearchStringEmpty)
{ {
DataGridView dgv = menu.GetDataGridView(); DataGridView dgv = menu.GetDataGridView();
if (isSearchStringEmpty) if (isSearchStringEmpty)
@ -189,12 +190,12 @@ namespace SystemTrayMenu.Handler
} }
} }
internal void ClearIsSelectedByKey() public void ClearIsSelectedByKey()
{ {
ClearIsSelectedByKey(iMenuKey, iRowKey); ClearIsSelectedByKey(iMenuKey, iRowKey);
} }
internal void Select(DataGridView dgv, int i, bool refreshview) public void Select(DataGridView dgv, int i, bool refreshview)
{ {
int newiMenuKey = ((Menu)dgv.TopLevelControl).Level; int newiMenuKey = ((Menu)dgv.TopLevelControl).Level;
if (i != iRowKey || newiMenuKey != iMenuKey) if (i != iRowKey || newiMenuKey != iMenuKey)
@ -222,6 +223,11 @@ namespace SystemTrayMenu.Handler
} }
} }
private void Hook_KeyPressed(object sender, KeyPressedEventArgs e)
{
HotKeyPressed?.Invoke();
}
private bool IsAnyMenuSelectedByKey( private bool IsAnyMenuSelectedByKey(
ref DataGridView dgv, ref DataGridView dgv,
ref Menu menuFromSelected, ref Menu menuFromSelected,
@ -307,7 +313,7 @@ namespace SystemTrayMenu.Handler
} }
else else
{ {
RowDeselected(iRowBefore, dgvBefore); RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey); SelectRow(dgv, iRowKey);
EnterPressed.Invoke(dgv, iRowKey); EnterPressed.Invoke(dgv, iRowKey);
} }
@ -318,7 +324,7 @@ namespace SystemTrayMenu.Handler
if (SelectMatchedReverse(dgv, iRowKey) || if (SelectMatchedReverse(dgv, iRowKey) ||
SelectMatchedReverse(dgv, dgv.Rows.Count - 1)) SelectMatchedReverse(dgv, dgv.Rows.Count - 1))
{ {
RowDeselected(iRowBefore, dgvBefore); RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey); SelectRow(dgv, iRowKey);
toClear = true; toClear = true;
} }
@ -328,7 +334,7 @@ namespace SystemTrayMenu.Handler
if (SelectMatched(dgv, iRowKey) || if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0)) SelectMatched(dgv, 0))
{ {
RowDeselected(iRowBefore, dgvBefore); RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey); SelectRow(dgv, iRowKey);
toClear = true; toClear = true;
} }
@ -337,7 +343,7 @@ namespace SystemTrayMenu.Handler
case Keys.Home: case Keys.Home:
if (SelectMatched(dgv, 0)) if (SelectMatched(dgv, 0))
{ {
RowDeselected(iRowBefore, dgvBefore); RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey); SelectRow(dgv, iRowKey);
toClear = true; toClear = true;
} }
@ -346,7 +352,7 @@ namespace SystemTrayMenu.Handler
case Keys.End: case Keys.End:
if (SelectMatchedReverse(dgv, dgv.Rows.Count - 1)) if (SelectMatchedReverse(dgv, dgv.Rows.Count - 1))
{ {
RowDeselected(iRowBefore, dgvBefore); RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey); SelectRow(dgv, iRowKey);
toClear = true; toClear = true;
} }
@ -380,7 +386,7 @@ namespace SystemTrayMenu.Handler
break; break;
case Keys.Escape: case Keys.Escape:
case Keys.Alt | Keys.F4: case Keys.Alt | Keys.F4:
RowDeselected(iRowBefore, dgvBefore); RowDeselected(dgvBefore, iRowBefore);
iMenuKey = 0; iMenuKey = 0;
iRowKey = -1; iRowKey = -1;
toClear = true; toClear = true;
@ -392,7 +398,7 @@ namespace SystemTrayMenu.Handler
if (SelectMatched(dgv, iRowKey, keyInput) || if (SelectMatched(dgv, iRowKey, keyInput) ||
SelectMatched(dgv, 0, keyInput)) SelectMatched(dgv, 0, keyInput))
{ {
RowDeselected(iRowBefore, null); RowDeselected(null, iRowBefore);
SelectRow(dgv, iRowKey); SelectRow(dgv, iRowKey);
toClear = true; toClear = true;
} }
@ -402,7 +408,7 @@ namespace SystemTrayMenu.Handler
if (SelectMatched(dgv, iRowKey, keyInput) || if (SelectMatched(dgv, iRowKey, keyInput) ||
SelectMatched(dgv, 0, keyInput)) SelectMatched(dgv, 0, keyInput))
{ {
RowDeselected(iRowBefore, null); RowDeselected(null, iRowBefore);
SelectRow(dgv, iRowKey); SelectRow(dgv, iRowKey);
} }
else else
@ -434,7 +440,7 @@ namespace SystemTrayMenu.Handler
if (SelectMatched(dgv, dgv.SelectedRows[0].Index) || if (SelectMatched(dgv, dgv.SelectedRows[0].Index) ||
SelectMatched(dgv, 0)) SelectMatched(dgv, 0))
{ {
RowDeselected(iRowBefore, dgvBefore); RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey); SelectRow(dgv, iRowKey);
toClear = true; toClear = true;
} }
@ -442,7 +448,7 @@ namespace SystemTrayMenu.Handler
} }
else else
{ {
RowDeselected(iRowBefore, dgvBefore); RowDeselected(dgvBefore, iRowBefore);
iMenuKey = 0; iMenuKey = 0;
iRowKey = -1; iRowKey = -1;
toClear = true; toClear = true;
@ -466,7 +472,7 @@ namespace SystemTrayMenu.Handler
if (SelectMatched(dgv, iRowKey) || if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0)) SelectMatched(dgv, 0))
{ {
RowDeselected(iRowBefore, dgvBefore); RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey); SelectRow(dgv, iRowKey);
toClear = true; toClear = true;
} }
@ -483,7 +489,7 @@ namespace SystemTrayMenu.Handler
if (SelectMatched(dgv, iRowKey) || if (SelectMatched(dgv, iRowKey) ||
SelectMatched(dgv, 0)) SelectMatched(dgv, 0))
{ {
RowDeselected(iRowBefore, dgvBefore); RowDeselected(dgvBefore, iRowBefore);
SelectRow(dgv, iRowKey); SelectRow(dgv, iRowKey);
toClear = true; toClear = true;
} }

View file

@ -12,6 +12,7 @@ namespace SystemTrayMenu.Business
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using SharpDX.DirectInput;
using SystemTrayMenu.DataClasses; using SystemTrayMenu.DataClasses;
using SystemTrayMenu.DllImports; using SystemTrayMenu.DllImports;
using SystemTrayMenu.Handler; using SystemTrayMenu.Handler;
@ -19,6 +20,7 @@ namespace SystemTrayMenu.Business
using SystemTrayMenu.Helpers; using SystemTrayMenu.Helpers;
using SystemTrayMenu.UserInterface; using SystemTrayMenu.UserInterface;
using SystemTrayMenu.Utilities; using SystemTrayMenu.Utilities;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using Menu = SystemTrayMenu.UserInterface.Menu; using Menu = SystemTrayMenu.UserInterface.Menu;
using Timer = System.Windows.Forms.Timer; using Timer = System.Windows.Forms.Timer;
@ -53,275 +55,33 @@ namespace SystemTrayMenu.Business
workerMainMenu.WorkerSupportsCancellation = true; workerMainMenu.WorkerSupportsCancellation = true;
workerMainMenu.DoWork += LoadMenu; workerMainMenu.DoWork += LoadMenu;
workerMainMenu.RunWorkerCompleted += LoadMainMenuCompleted; workerMainMenu.RunWorkerCompleted += LoadMainMenuCompleted;
void LoadMainMenuCompleted(object sender, RunWorkerCompletedEventArgs e)
{
keyboardInput.ResetSelectedByKey();
LoadStopped();
if (e.Result == null)
{
// Clean up menu status IsMenuOpen for previous one
DataGridView dgvMainMenu = menus[0].GetDataGridView();
foreach (DataRow row in ((DataTable)dgvMainMenu.DataSource).Rows)
{
RowData rowDataToClear = (RowData)row[2];
rowDataToClear.IsMenuOpen = false;
rowDataToClear.IsClicking = false;
rowDataToClear.IsSelected = false;
rowDataToClear.IsContextMenuOpen = false;
}
RefreshSelection(dgvMainMenu);
if (Properties.Settings.Default.AppearAtMouseLocation)
{
menus[0].Tag = null;
}
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
}
else
{
MenuData menuData = (MenuData)e.Result;
switch (menuData.Validity)
{
case MenuDataValidity.Valid:
if (IconReader.MainPreload)
{
workerMainMenu.DoWork -= LoadMenu;
menus[0] = Create(menuData, new DirectoryInfo(Config.Path).Name);
menus[0].HandleCreated += (s, e) => ExecuteWatcherHistory();
Scaling.CalculateFactorByDpi(menus[0].GetDataGridView().CreateGraphics());
IconReader.MainPreload = false;
if (showMenuAfterMainPreload)
{
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
}
}
else
{
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
}
break;
case MenuDataValidity.Empty:
MessageBox.Show(Translator.GetText("Your root directory for the app does not exist or is empty! Change the root directory or put some files, directories or shortcuts into the root directory."));
OpenFolder();
Config.SetFolderByUser();
AppRestart.ByConfigChange();
break;
case MenuDataValidity.NoAccess:
MessageBox.Show(Translator.GetText("You have no access to the root directory of the app. Grant access to the directory or change the root directory."));
OpenFolder();
Config.SetFolderByUser();
AppRestart.ByConfigChange();
break;
case MenuDataValidity.Undefined:
Log.Info($"{nameof(MenuDataValidity)}.{nameof(MenuDataValidity.Undefined)}");
break;
default:
break;
}
}
openCloseState = OpenCloseState.Default;
}
waitToOpenMenu.StopLoadMenu += WaitToOpenMenu_StopLoadMenu; waitToOpenMenu.StopLoadMenu += WaitToOpenMenu_StopLoadMenu;
void WaitToOpenMenu_StopLoadMenu()
{
foreach (BackgroundWorker workerSubMenu in workersSubMenu.
Where(w => w.IsBusy))
{
workerSubMenu.CancelAsync();
}
LoadStopped();
}
waitToOpenMenu.StartLoadMenu += StartLoadMenu; waitToOpenMenu.StartLoadMenu += StartLoadMenu;
void StartLoadMenu(RowData rowData)
{
if (menus[0].IsUsable &&
(menus[rowData.Level + 1] == null ||
menus[rowData.Level + 1].Tag as RowData != rowData))
{
CreateAndShowLoadingMenu(rowData);
void CreateAndShowLoadingMenu(RowData rowData)
{
MenuData menuDataLoading = new(rowData.Level + 1)
{
Validity = MenuDataValidity.Valid,
};
Menu menuLoading = Create(menuDataLoading, new DirectoryInfo(rowData.Path).Name);
menuLoading.IsLoadingMenu = true;
AdjustMenusSizeAndLocation();
menus[rowData.Level + 1] = menuLoading;
menuLoading.Tag = menuDataLoading.RowDataParent = rowData;
menuDataLoading.RowDataParent.SubMenu = menuLoading;
menuLoading.SetTypeLoading();
ShowSubMenu(menuLoading);
}
BackgroundWorker workerSubMenu = workersSubMenu.
Where(w => !w.IsBusy).FirstOrDefault();
if (workerSubMenu == null)
{
workerSubMenu = new BackgroundWorker
{
WorkerSupportsCancellation = true,
};
workerSubMenu.DoWork += LoadMenu;
workerSubMenu.RunWorkerCompleted += LoadSubMenuCompleted;
workersSubMenu.Add(workerSubMenu);
}
workerSubMenu.RunWorkerAsync(rowData);
}
void LoadSubMenuCompleted(object senderCompleted, RunWorkerCompletedEventArgs e)
{
MenuData menuData = (MenuData)e.Result;
Menu menuLoading = menus[menuData.Level];
string userSearchText = string.Empty;
bool closedLoadingMenu = false;
if (menuLoading != null && menuLoading.IsLoadingMenu)
{
menuLoading.HideWithFade();
userSearchText = menuLoading.GetSearchText();
menus[menuLoading.Level] = null;
closedLoadingMenu = true;
}
if (menuData.Validity != MenuDataValidity.Undefined &&
menus[0].IsUsable)
{
Menu menu = Create(menuData);
switch (menuData.Validity)
{
case MenuDataValidity.Valid:
menu.SetTypeSub();
break;
case MenuDataValidity.Empty:
menu.SetTypeEmpty();
break;
case MenuDataValidity.NoAccess:
menu.SetTypeNoAccess();
break;
}
menu.Tag = menuData.RowDataParent;
menuData.RowDataParent.SubMenu = menu;
if (menus[0].IsUsable)
{
ShowSubMenu(menu);
menu.SetSearchText(userSearchText);
}
}
else if (closedLoadingMenu && menus[0].IsUsable)
{
menuData.RowDataParent.IsMenuOpen = false;
menuData.RowDataParent.IsClicking = false;
menuData.RowDataParent.IsSelected = false;
Menu menuPrevious = menus[menuData.Level - 1];
if (menuPrevious != null)
{
RefreshSelection(menuPrevious.GetDataGridView());
}
}
}
}
waitToOpenMenu.CloseMenu += CloseMenu; waitToOpenMenu.CloseMenu += CloseMenu;
void CloseMenu(int level)
{
if (level < menus.Length && menus[level] != null)
{
HideOldMenu(menus[level]);
}
if (level - 1 < menus.Length && menus[level - 1] != null)
{
menus[level - 1].FocusTextBox();
}
}
waitToOpenMenu.MouseEnterOk += MouseEnterOk; waitToOpenMenu.MouseEnterOk += MouseEnterOk;
dgvMouseRow.RowMouseEnter += waitToOpenMenu.MouseEnter; dgvMouseRow.RowMouseEnter += waitToOpenMenu.MouseEnter;
dgvMouseRow.RowMouseLeave += waitToOpenMenu.MouseLeave; dgvMouseRow.RowMouseLeave += waitToOpenMenu.MouseLeave;
dgvMouseRow.RowMouseLeave += Dgv_RowMouseLeave; dgvMouseRow.RowMouseLeave += Dgv_RowMouseLeave;
keyboardInput = new(menus); keyboardInput = new(menus);
keyboardInput.RegisterHotKey(); keyboardInput.RegisterHotKey();
keyboardInput.HotKeyPressed += () => SwitchOpenClose(false); keyboardInput.HotKeyPressed += KeyboardInput_HotKeyPressed;
keyboardInput.ClosePressed += MenusFadeOut; keyboardInput.ClosePressed += MenusFadeOut;
keyboardInput.RowDeselected += waitToOpenMenu.RowDeselected; keyboardInput.RowDeselected += waitToOpenMenu.RowDeselected;
keyboardInput.EnterPressed += waitToOpenMenu.EnterOpensInstantly; keyboardInput.EnterPressed += waitToOpenMenu.EnterOpensInstantly;
keyboardInput.RowSelected += waitToOpenMenu.RowSelected; keyboardInput.RowSelected += waitToOpenMenu.RowSelected;
keyboardInput.RowSelected += AdjustScrollbarToDisplayedRow; keyboardInput.RowSelected += AdjustScrollbarToDisplayedRow;
void AdjustScrollbarToDisplayedRow(DataGridView dgv, int index)
{
Menu menu = (Menu)dgv.FindForm();
menu.AdjustScrollbar();
}
joystickHelper = new(); joystickHelper = new();
joystickHelper.KeyPressed += (key) => menus[0].Invoke(keyboardInput.CmdKeyProcessed, null, key); joystickHelper.KeyPressed += JoystickHelper_KeyPressed;
timerShowProcessStartedAsLoadingIcon.Interval = Properties.Settings.Default.TimeUntilClosesAfterEnterPressed; timerShowProcessStartedAsLoadingIcon.Interval = Properties.Settings.Default.TimeUntilClosesAfterEnterPressed;
timerStillActiveCheck.Interval = Properties.Settings.Default.TimeUntilClosesAfterEnterPressed + 20; timerStillActiveCheck.Interval = Properties.Settings.Default.TimeUntilClosesAfterEnterPressed + 20;
timerStillActiveCheck.Tick += (sender, e) => StillActiveTick(); timerStillActiveCheck.Tick += TimerStillActiveCheck_Tick;
void StillActiveTick()
{
if (!IsActive())
{
FadeHalfOrOutIfNeeded();
}
timerStillActiveCheck.Stop();
}
waitLeave.LeaveTriggered += FadeHalfOrOutIfNeeded; waitLeave.LeaveTriggered += FadeHalfOrOutIfNeeded;
CreateWatchers();
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()
{
Path = path,
NotifyFilter = NotifyFilters.Attributes |
NotifyFilters.DirectoryName |
NotifyFilters.FileName |
NotifyFilters.LastWrite,
Filter = "*.*",
};
watcher.Created += WatcherProcessItem;
watcher.Deleted += WatcherProcessItem;
watcher.Renamed += WatcherProcessItem;
watcher.Changed += WatcherProcessItem;
watcher.IncludeSubdirectories = recursiv;
watcher.EnableRaisingEvents = true;
watchers.Add(watcher);
}
catch (Exception ex)
{
Log.Warn($"Failed to {nameof(CreateWatcher)}: {path}", ex);
}
}
} }
internal event EventHandlerEmpty LoadStarted; public event Action LoadStarted;
internal event EventHandlerEmpty LoadStopped; public event Action LoadStopped;
private enum OpenCloseState private enum OpenCloseState
{ {
@ -334,34 +94,7 @@ namespace SystemTrayMenu.Business
private List<Menu> AsList => AsEnumerable.ToList(); private List<Menu> AsList => AsEnumerable.ToList();
public void Dispose() public static MenuData GetData(BackgroundWorker worker, string path, int level)
{
workerMainMenu.Dispose();
foreach (BackgroundWorker worker in workersSubMenu)
{
worker.Dispose();
}
waitToOpenMenu.Dispose();
keyboardInput.Dispose();
joystickHelper.Dispose();
timerShowProcessStartedAsLoadingIcon.Dispose();
timerStillActiveCheck.Dispose();
waitLeave.Dispose();
IconReader.Dispose();
DisposeMenu(menus[0]);
dgvMouseRow.Dispose();
foreach (FileSystemWatcher watcher in watchers)
{
watcher.Created -= WatcherProcessItem;
watcher.Deleted -= WatcherProcessItem;
watcher.Renamed -= WatcherProcessItem;
watcher.Changed -= WatcherProcessItem;
watcher.Dispose();
}
}
internal static MenuData GetData(BackgroundWorker worker, string path, int level)
{ {
MenuData menuData = new(level); MenuData menuData = new(level);
if (worker?.CancellationPending == true || string.IsNullOrEmpty(path)) if (worker?.CancellationPending == true || string.IsNullOrEmpty(path))
@ -392,18 +125,65 @@ namespace SystemTrayMenu.Business
return menuData; return menuData;
} }
internal void SwitchOpenCloseByTaskbarItem() public void Dispose()
{
workerMainMenu.DoWork -= LoadMenu;
workerMainMenu.RunWorkerCompleted -= LoadMainMenuCompleted;
workerMainMenu.Dispose();
dgvMouseRow.RowMouseEnter -= waitToOpenMenu.MouseEnter;
dgvMouseRow.RowMouseLeave -= waitToOpenMenu.MouseLeave;
dgvMouseRow.RowMouseLeave -= Dgv_RowMouseLeave;
keyboardInput.HotKeyPressed -= KeyboardInput_HotKeyPressed;
keyboardInput.ClosePressed -= MenusFadeOut;
keyboardInput.RowDeselected -= waitToOpenMenu.RowDeselected;
keyboardInput.EnterPressed -= waitToOpenMenu.EnterOpensInstantly;
keyboardInput.RowSelected -= waitToOpenMenu.RowSelected;
keyboardInput.RowSelected -= AdjustScrollbarToDisplayedRow;
keyboardInput.Dispose();
waitToOpenMenu.StopLoadMenu -= WaitToOpenMenu_StopLoadMenu;
waitToOpenMenu.StartLoadMenu -= StartLoadMenu;
waitToOpenMenu.CloseMenu -= CloseMenu;
waitToOpenMenu.MouseEnterOk -= MouseEnterOk;
waitToOpenMenu.Dispose();
joystickHelper.KeyPressed -= JoystickHelper_KeyPressed;
joystickHelper.Dispose();
timerShowProcessStartedAsLoadingIcon.Dispose();
timerStillActiveCheck.Tick -= TimerStillActiveCheck_Tick;
timerStillActiveCheck.Dispose();
waitLeave.LeaveTriggered -= FadeHalfOrOutIfNeeded;
waitLeave.Dispose();
foreach (BackgroundWorker workerSubMenu in workersSubMenu)
{
workerSubMenu.DoWork -= LoadMenu;
workerSubMenu.RunWorkerCompleted -= LoadSubMenuCompleted;
workerSubMenu.Dispose();
}
IconReader.Dispose();
dgvMouseRow.Dispose();
DisposeMenu(menus[0]);
foreach (FileSystemWatcher watcher in watchers)
{
watcher.Created -= WatcherProcessItem;
watcher.Deleted -= WatcherProcessItem;
watcher.Renamed -= WatcherProcessItem;
watcher.Changed -= WatcherProcessItem;
watcher.Dispose();
}
}
public void SwitchOpenCloseByTaskbarItem()
{ {
SwitchOpenClose(true); SwitchOpenClose(true);
timerStillActiveCheck.Start(); timerStillActiveCheck.Start();
} }
internal bool IsOpenCloseStateOpening() public bool IsOpenCloseStateOpening()
{ {
return openCloseState == OpenCloseState.Opening; return openCloseState == OpenCloseState.Opening;
} }
internal void SwitchOpenClose(bool byClick, bool isMainPreload = false) public void SwitchOpenClose(bool byClick, bool isMainPreload = false)
{ {
// Ignore open close events during main preload #248 // Ignore open close events during main preload #248
if (IconReader.MainPreload && !isMainPreload) if (IconReader.MainPreload && !isMainPreload)
@ -448,13 +228,18 @@ namespace SystemTrayMenu.Business
{ {
if (menuToDispose != null) if (menuToDispose != null)
{ {
menuToDispose.UserClickedOpenFolder -= OpenFolder;
menuToDispose.MouseWheel -= AdjustMenusSizeAndLocation; menuToDispose.MouseWheel -= AdjustMenusSizeAndLocation;
menuToDispose.MouseLeave -= waitLeave.Start; menuToDispose.MouseLeave -= waitLeave.Start;
menuToDispose.MouseEnter -= waitLeave.Stop; menuToDispose.MouseEnter -= waitLeave.Stop;
menuToDispose.CmdKeyProcessed -= keyboardInput.CmdKeyProcessed; menuToDispose.CmdKeyProcessed -= keyboardInput.CmdKeyProcessed;
menuToDispose.SearchTextChanging -= keyboardInput.SearchTextChanging;
menuToDispose.KeyPressCheck -= Menu_KeyPressCheck; menuToDispose.KeyPressCheck -= Menu_KeyPressCheck;
menuToDispose.SearchTextChanging -= Menu_SearchTextChanging;
menuToDispose.SearchTextChanged -= Menu_SearchTextChanged; menuToDispose.SearchTextChanged -= Menu_SearchTextChanged;
menuToDispose.UserDragsMenu -= Menu_UserDragsMenu;
menuToDispose.Activated -= Menu_Activated;
menuToDispose.Deactivate -= Menu_Deactivate;
menuToDispose.VisibleChanged -= MenuVisibleChanged;
DataGridView dgv = menuToDispose.GetDataGridView(); DataGridView dgv = menuToDispose.GetDataGridView();
if (dgv != null) if (dgv != null)
{ {
@ -470,6 +255,7 @@ namespace SystemTrayMenu.Business
dgv.MouseDoubleClick -= Dgv_MouseDoubleClick; dgv.MouseDoubleClick -= Dgv_MouseDoubleClick;
dgv.SelectionChanged -= Dgv_SelectionChanged; dgv.SelectionChanged -= Dgv_SelectionChanged;
dgv.RowPostPaint -= Dgv_RowPostPaint; dgv.RowPostPaint -= Dgv_RowPostPaint;
dgv.DataError -= Dgv_DataError;
dgv.ClearSelection(); dgv.ClearSelection();
foreach (DataGridViewRow row in dgv.Rows) foreach (DataGridViewRow row in dgv.Rows)
@ -477,6 +263,9 @@ namespace SystemTrayMenu.Business
RowData rowData = (RowData)row.Cells[2].Value; RowData rowData = (RowData)row.Cells[2].Value;
DisposeMenu(rowData.SubMenu); DisposeMenu(rowData.SubMenu);
} }
DataTable dataTable = (DataTable)dgv.DataSource;
dataTable.Dispose();
} }
menuToDispose.Dispose(); menuToDispose.Dispose();
@ -620,6 +409,197 @@ namespace SystemTrayMenu.Business
} }
} }
private void LoadMainMenuCompleted(object sender, RunWorkerCompletedEventArgs e)
{
keyboardInput.ResetSelectedByKey();
LoadStopped();
if (e.Result == null)
{
// Clean up menu status IsMenuOpen for previous one
DataGridView dgvMainMenu = menus[0].GetDataGridView();
foreach (DataRow row in ((DataTable)dgvMainMenu.DataSource).Rows)
{
RowData rowDataToClear = (RowData)row[2];
rowDataToClear.IsMenuOpen = false;
rowDataToClear.IsClicking = false;
rowDataToClear.IsSelected = false;
rowDataToClear.IsContextMenuOpen = false;
}
RefreshSelection(dgvMainMenu);
if (Properties.Settings.Default.AppearAtMouseLocation)
{
menus[0].Tag = null;
}
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
}
else
{
MenuData menuData = (MenuData)e.Result;
switch (menuData.Validity)
{
case MenuDataValidity.Valid:
if (IconReader.MainPreload)
{
workerMainMenu.DoWork -= LoadMenu;
menus[0] = Create(menuData, new DirectoryInfo(Config.Path).Name);
menus[0].HandleCreated += (s, e) => ExecuteWatcherHistory();
Scaling.CalculateFactorByDpi(menus[0].GetDataGridView().CreateGraphics());
IconReader.MainPreload = false;
if (showMenuAfterMainPreload)
{
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
}
}
else
{
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
}
break;
case MenuDataValidity.Empty:
MessageBox.Show(Translator.GetText("Your root directory for the app does not exist or is empty! Change the root directory or put some files, directories or shortcuts into the root directory."));
OpenFolder();
Config.SetFolderByUser();
AppRestart.ByConfigChange();
break;
case MenuDataValidity.NoAccess:
MessageBox.Show(Translator.GetText("You have no access to the root directory of the app. Grant access to the directory or change the root directory."));
OpenFolder();
Config.SetFolderByUser();
AppRestart.ByConfigChange();
break;
case MenuDataValidity.Undefined:
Log.Info($"{nameof(MenuDataValidity)}.{nameof(MenuDataValidity.Undefined)}");
break;
default:
break;
}
}
openCloseState = OpenCloseState.Default;
}
private void WaitToOpenMenu_StopLoadMenu()
{
foreach (BackgroundWorker workerSubMenu in workersSubMenu.Where(w => w.IsBusy))
{
workerSubMenu.CancelAsync();
}
LoadStopped();
}
private void StartLoadMenu(RowData rowData)
{
if (menus[0].IsUsable &&
(menus[rowData.Level + 1] == null ||
menus[rowData.Level + 1].Tag as RowData != rowData))
{
CreateAndShowLoadingMenu(rowData);
void CreateAndShowLoadingMenu(RowData rowData)
{
MenuData menuDataLoading = new(rowData.Level + 1)
{
Validity = MenuDataValidity.Valid,
};
Menu menuLoading = Create(menuDataLoading, new DirectoryInfo(rowData.Path).Name);
menuLoading.IsLoadingMenu = true;
AdjustMenusSizeAndLocation();
menus[rowData.Level + 1] = menuLoading;
menuLoading.Tag = menuDataLoading.RowDataParent = rowData;
menuDataLoading.RowDataParent.SubMenu = menuLoading;
menuLoading.SetTypeLoading();
ShowSubMenu(menuLoading);
}
BackgroundWorker workerSubMenu = workersSubMenu.
Where(w => !w.IsBusy).FirstOrDefault();
if (workerSubMenu == null)
{
workerSubMenu = new BackgroundWorker()
{
WorkerSupportsCancellation = true,
};
workerSubMenu.DoWork += LoadMenu;
workerSubMenu.RunWorkerCompleted += LoadSubMenuCompleted;
workersSubMenu.Add(workerSubMenu);
}
workerSubMenu.RunWorkerAsync(rowData);
}
}
private void CloseMenu(int level)
{
if (level < menus.Length && menus[level] != null)
{
HideOldMenu(menus[level]);
}
if (level - 1 < menus.Length && menus[level - 1] != null)
{
menus[level - 1].FocusTextBox();
}
}
private void LoadSubMenuCompleted(object senderCompleted, RunWorkerCompletedEventArgs e)
{
MenuData menuData = (MenuData)e.Result;
Menu menuLoading = menus[menuData.Level];
string userSearchText = string.Empty;
bool closedLoadingMenu = false;
if (menuLoading != null && menuLoading.IsLoadingMenu)
{
menuLoading.HideWithFade();
userSearchText = menuLoading.GetSearchText();
menus[menuLoading.Level] = null;
closedLoadingMenu = true;
}
if (menuData.Validity != MenuDataValidity.Undefined &&
menus[0].IsUsable)
{
Menu menu = Create(menuData);
switch (menuData.Validity)
{
case MenuDataValidity.Valid:
menu.SetTypeSub();
break;
case MenuDataValidity.Empty:
menu.SetTypeEmpty();
break;
case MenuDataValidity.NoAccess:
menu.SetTypeNoAccess();
break;
}
menu.Tag = menuData.RowDataParent;
menuData.RowDataParent.SubMenu = menu;
if (menus[0].IsUsable)
{
ShowSubMenu(menu);
menu.SetSearchText(userSearchText);
}
}
else if (closedLoadingMenu && menus[0].IsUsable)
{
menuData.RowDataParent.IsMenuOpen = false;
menuData.RowDataParent.IsClicking = false;
menuData.RowDataParent.IsSelected = false;
Menu menuPrevious = menus[menuData.Level - 1];
if (menuPrevious != null)
{
RefreshSelection(menuPrevious.GetDataGridView());
}
}
}
private bool IsActive() private bool IsActive()
{ {
bool IsShellContextMenuOpen() bool IsShellContextMenuOpen()
@ -653,22 +633,21 @@ namespace SystemTrayMenu.Business
private Menu Create(MenuData menuData, string title = null) private Menu Create(MenuData menuData, string title = null)
{ {
Menu menu = new(); Menu menu = new();
menu.Level = menuData.Level;
string path = Config.Path; menu.Path = Config.Path;
if (title == null) if (title == null)
{ {
title = new DirectoryInfo(menuData.RowDataParent.ResolvedPath).Name; title = new DirectoryInfo(menuData.RowDataParent.ResolvedPath).Name;
path = menuData.RowDataParent.ResolvedPath; menu.Path = menuData.RowDataParent.ResolvedPath;
} }
if (string.IsNullOrEmpty(title)) if (string.IsNullOrEmpty(title))
{ {
title = Path.GetPathRoot(path); title = Path.GetPathRoot(menu.Path);
} }
menu.AdjustControls(title, menuData.Validity); menu.AdjustControls(title, menuData.Validity);
menu.UserClickedOpenFolder += () => OpenFolder(path); menu.UserClickedOpenFolder += OpenFolder;
menu.Level = menuData.Level;
menu.MouseWheel += AdjustMenusSizeAndLocation; menu.MouseWheel += AdjustMenusSizeAndLocation;
menu.MouseLeave += waitLeave.Start; menu.MouseLeave += waitLeave.Start;
menu.MouseEnter += waitLeave.Stop; menu.MouseEnter += waitLeave.Stop;
@ -677,43 +656,8 @@ namespace SystemTrayMenu.Business
menu.SearchTextChanging += Menu_SearchTextChanging; menu.SearchTextChanging += Menu_SearchTextChanging;
menu.SearchTextChanged += Menu_SearchTextChanged; menu.SearchTextChanged += Menu_SearchTextChanged;
menu.UserDragsMenu += Menu_UserDragsMenu; menu.UserDragsMenu += Menu_UserDragsMenu;
void Menu_UserDragsMenu() menu.Activated += Menu_Activated;
{ menu.Deactivate += Menu_Deactivate;
if (menus[1] != null)
{
HideOldMenu(menus[1]);
}
}
menu.Deactivate += Deactivate;
void Deactivate(object sender, EventArgs e)
{
if (IsOpenCloseStateOpening())
{
Log.Info("Ignored Deactivate, because openCloseState == OpenCloseState.Opening");
}
else if (!Properties.Settings.Default.StaysOpenWhenFocusLostAfterEnterPressed ||
!waitingForReactivate)
{
FadeHalfOrOutIfNeeded();
if (!IsActive())
{
deactivatedTime = DateTime.Now;
}
}
}
menu.Activated += (sender, e) => Activated();
void Activated()
{
if (IsActive() && menus[0].IsUsable)
{
AsList.ForEach(m => m.ShowWithFade());
timerStillActiveCheck.Stop();
timerStillActiveCheck.Start();
}
}
menu.VisibleChanged += MenuVisibleChanged; menu.VisibleChanged += MenuVisibleChanged;
AddItemsToMenu(menuData.RowDatas, menu, out int foldersCount, out int filesCount); AddItemsToMenu(menuData.RowDatas, menu, out int foldersCount, out int filesCount);
@ -731,18 +675,47 @@ namespace SystemTrayMenu.Business
dgv.SelectionChanged += Dgv_SelectionChanged; dgv.SelectionChanged += Dgv_SelectionChanged;
dgv.RowPostPaint += Dgv_RowPostPaint; dgv.RowPostPaint += Dgv_RowPostPaint;
dgv.DataError += Dgv_DataError; dgv.DataError += Dgv_DataError;
void Dgv_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
// WARN Dgv_DataError occured System.ObjectDisposedException: Cannot access a disposed object. Object name: 'Icon'
// => Rare times occured (e.g. when focused an close other application => closed and activated at same time)
Log.Warn("Dgv_DataError occured", e.Exception);
}
menu.SetCounts(foldersCount, filesCount); menu.SetCounts(foldersCount, filesCount);
return menu; return menu;
} }
private void Menu_UserDragsMenu()
{
if (menus[1] != null)
{
HideOldMenu(menus[1]);
}
}
private void Menu_Activated(object sender, EventArgs e)
{
if (IsActive() && menus[0].IsUsable)
{
AsList.ForEach(m => m.ShowWithFade());
timerStillActiveCheck.Stop();
timerStillActiveCheck.Start();
}
}
private void Menu_Deactivate(object sender, EventArgs e)
{
if (IsOpenCloseStateOpening())
{
Log.Info("Ignored Deactivate, because openCloseState == OpenCloseState.Opening");
}
else if (!Properties.Settings.Default.StaysOpenWhenFocusLostAfterEnterPressed ||
!waitingForReactivate)
{
FadeHalfOrOutIfNeeded();
if (!IsActive())
{
deactivatedTime = DateTime.Now;
}
}
}
private void MenuVisibleChanged(object sender, EventArgs e) private void MenuVisibleChanged(object sender, EventArgs e)
{ {
Menu menu = (Menu)sender; Menu menu = (Menu)sender;
@ -1058,6 +1031,13 @@ namespace SystemTrayMenu.Business
} }
} }
private void Dgv_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
// WARN Dgv_DataError occured System.ObjectDisposedException: Cannot access a disposed object. Object name: 'Icon'
// => Rare times occured (e.g. when focused an close other application => closed and activated at same time)
Log.Warn("Dgv_DataError occured", e.Exception);
}
private void ShowSubMenu(Menu menuToShow) private void ShowSubMenu(Menu menuToShow)
{ {
HideOldMenu(menuToShow, true); HideOldMenu(menuToShow, true);
@ -1142,6 +1122,68 @@ namespace SystemTrayMenu.Business
joystickHelper.Disable(); joystickHelper.Disable();
} }
private void CreateWatchers()
{
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()
{
Path = path,
NotifyFilter = NotifyFilters.Attributes |
NotifyFilters.DirectoryName |
NotifyFilters.FileName |
NotifyFilters.LastWrite,
Filter = "*.*",
};
watcher.Created += WatcherProcessItem;
watcher.Deleted += WatcherProcessItem;
watcher.Renamed += WatcherProcessItem;
watcher.Changed += WatcherProcessItem;
watcher.IncludeSubdirectories = recursiv;
watcher.EnableRaisingEvents = true;
watchers.Add(watcher);
}
catch (Exception ex)
{
Log.Warn($"Failed to {nameof(CreateWatcher)}: {path}", ex);
}
}
}
private void AdjustScrollbarToDisplayedRow(DataGridView dgv, int index)
{
Menu menu = (Menu)dgv.FindForm();
menu.AdjustScrollbar();
}
private void JoystickHelper_KeyPressed(Keys keys)
{
menus[0].Invoke(keyboardInput.CmdKeyProcessed, null, keys);
}
private void TimerStillActiveCheck_Tick(object sender, EventArgs e)
{
if (!IsActive())
{
FadeHalfOrOutIfNeeded();
}
timerStillActiveCheck.Stop();
}
private void KeyboardInput_HotKeyPressed()
{
SwitchOpenClose(false);
}
private void AdjustMenusSizeAndLocation() private void AdjustMenusSizeAndLocation()
{ {
Rectangle screenBounds; Rectangle screenBounds;

View file

@ -28,7 +28,7 @@ namespace SystemTrayMenu
{ {
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += (sender, e) => AskUserSendError(e.Exception); Application.ThreadException += Application_ThreadException;
Scaling.Initialize(); Scaling.Initialize();
FolderOptions.Initialize(); FolderOptions.Initialize();
@ -40,6 +40,7 @@ namespace SystemTrayMenu
} }
} }
Application.ThreadException -= Application_ThreadException;
Config.Dispose(); Config.Dispose();
} }
catch (Exception ex) catch (Exception ex)
@ -50,32 +51,37 @@ namespace SystemTrayMenu
{ {
Log.Close(); Log.Close();
} }
}
static void AskUserSendError(Exception ex) private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
AskUserSendError(e.Exception);
}
private static void AskUserSendError(Exception ex)
{
Log.Error("Application Crashed", ex);
DialogResult dialogResult = MessageBox.Show(
"A problem has been encountered and the application needs to restart. " +
"Reporting this error will help us make our product better. " +
"Press 'Yes' to open your standard email app (emailto: Markus@Hofknecht.eu). " + Environment.NewLine +
@"You can also create an issue manually here https://github.com/Hofknecht/SystemTrayMenu/issues" + Environment.NewLine +
"Press 'Cancel' to quit SystemTrayMenu.",
"SystemTrayMenu Crashed",
MessageBoxButtons.YesNoCancel);
if (dialogResult == DialogResult.Yes)
{ {
Log.Error("Application Crashed", ex); Log.ProcessStart("mailto:" + "markus@hofknecht.eu" +
"?subject=SystemTrayMenu Bug reported " +
Assembly.GetEntryAssembly().GetName().Version +
"&body=" + ex.ToString());
}
DialogResult dialogResult = MessageBox.Show( if (!isStartup && dialogResult != DialogResult.Cancel)
"A problem has been encountered and the application needs to restart. " + {
"Reporting this error will help us make our product better. " + AppRestart.ByThreadException();
"Press 'Yes' to open your standard email app (emailto: Markus@Hofknecht.eu). " + Environment.NewLine +
@"You can also create an issue manually here https://github.com/Hofknecht/SystemTrayMenu/issues" + Environment.NewLine +
"Press 'Cancel' to quit SystemTrayMenu.",
"SystemTrayMenu Crashed",
MessageBoxButtons.YesNoCancel);
if (dialogResult == DialogResult.Yes)
{
Log.ProcessStart("mailto:" + "markus@hofknecht.eu" +
"?subject=SystemTrayMenu Bug reported " +
Assembly.GetEntryAssembly().GetName().Version +
"&body=" + ex.ToString());
}
if (!isStartup && dialogResult != DialogResult.Cancel)
{
AppRestart.ByThreadException();
}
} }
} }
} }

View file

@ -18,10 +18,11 @@ namespace SystemTrayMenu.Handler
timerLeaveCheck.Tick += TimerLeaveCheckTick; timerLeaveCheck.Tick += TimerLeaveCheckTick;
} }
public event EventHandlerEmpty LeaveTriggered; public event Action LeaveTriggered;
public void Dispose() public void Dispose()
{ {
timerLeaveCheck.Tick -= TimerLeaveCheckTick;
timerLeaveCheck.Dispose(); timerLeaveCheck.Dispose();
} }

View file

@ -33,7 +33,7 @@ namespace SystemTrayMenu.Handler
internal event Action<int> CloseMenu; internal event Action<int> CloseMenu;
internal event EventHandlerEmpty StopLoadMenu; internal event Action StopLoadMenu;
internal event Action<DataGridView, int> MouseEnterOk; internal event Action<DataGridView, int> MouseEnterOk;
@ -41,6 +41,7 @@ namespace SystemTrayMenu.Handler
public void Dispose() public void Dispose()
{ {
timerStartLoad.Tick -= WaitStartLoad_Tick;
timerStartLoad.Stop(); timerStartLoad.Stop();
timerStartLoad.Dispose(); timerStartLoad.Dispose();
dgv?.Dispose(); dgv?.Dispose();
@ -92,7 +93,7 @@ namespace SystemTrayMenu.Handler
} }
} }
internal void RowDeselected(int rowIndex, DataGridView dgv) internal void RowDeselected(DataGridView dgv, int rowIndex)
{ {
timerStartLoad.Stop(); timerStartLoad.Stop();
StopLoadMenu?.Invoke(); StopLoadMenu?.Invoke();

View file

@ -16,12 +16,12 @@ namespace SystemTrayMenu.Helper
internal DgvMouseRow() internal DgvMouseRow()
{ {
timerRaiseRowMouseLeave.Interval = 200; timerRaiseRowMouseLeave.Interval = 200;
timerRaiseRowMouseLeave.Tick += Elapsed; timerRaiseRowMouseLeave.Tick += TimerRaiseRowMouseLeave_Tick;
void Elapsed(object sender, EventArgs e) }
{
timerRaiseRowMouseLeave.Stop(); ~DgvMouseRow() // the finalizer
TriggerRowMouseLeave(); {
} Dispose(false);
} }
internal event Action<object, DataGridViewCellEventArgs> RowMouseEnter; internal event Action<object, DataGridViewCellEventArgs> RowMouseEnter;
@ -75,11 +75,18 @@ namespace SystemTrayMenu.Helper
{ {
if (disposing) if (disposing)
{ {
timerRaiseRowMouseLeave.Tick -= TimerRaiseRowMouseLeave_Tick;
timerRaiseRowMouseLeave.Dispose(); timerRaiseRowMouseLeave.Dispose();
dgv?.Dispose(); dgv = null;
} }
} }
private void TimerRaiseRowMouseLeave_Tick(object sender, EventArgs e)
{
timerRaiseRowMouseLeave.Stop();
TriggerRowMouseLeave();
}
private void TriggerRowMouseLeave() private void TriggerRowMouseLeave()
{ {
if (dgv != null) if (dgv != null)

View file

@ -28,14 +28,19 @@ namespace SystemTrayMenu.Helper
internal Fading() internal Fading()
{ {
timer.Interval = Interval100FPS; timer.Interval = Interval100FPS;
timer.Tick += (sender, e) => FadeStep(); timer.Tick += Timer_Tick;
} }
internal event EventHandlerEmpty Hide; ~Fading() // the finalizer
{
Dispose(false);
}
internal event EventHandlerEmpty Show; internal event Action Hide;
internal event EventHandler<double> ChangeOpacity; internal event Action Show;
internal event Action<double> ChangeOpacity;
internal enum FadingState internal enum FadingState
{ {
@ -62,6 +67,7 @@ namespace SystemTrayMenu.Helper
{ {
if (disposing) if (disposing)
{ {
timer.Tick -= Timer_Tick;
timer.Dispose(); timer.Dispose();
} }
} }
@ -80,6 +86,11 @@ namespace SystemTrayMenu.Helper
} }
} }
private void Timer_Tick(object sender, EventArgs e)
{
FadeStep();
}
private void FadeStep() private void FadeStep()
{ {
switch (state) switch (state)
@ -90,13 +101,13 @@ namespace SystemTrayMenu.Helper
visible = true; visible = true;
Show?.Invoke(); Show?.Invoke();
opacity = 0; opacity = 0;
ChangeOpacity?.Invoke(this, opacity); ChangeOpacity?.Invoke(opacity);
} }
else if (Properties.Settings.Default.UseFading && else if (Properties.Settings.Default.UseFading &&
opacity < ShownMinus) opacity < ShownMinus)
{ {
opacity += StepIn; opacity += StepIn;
ChangeOpacity?.Invoke(this, opacity); ChangeOpacity?.Invoke(opacity);
} }
else else
{ {
@ -104,11 +115,11 @@ namespace SystemTrayMenu.Helper
{ {
// #393 provoke a redraw for the CS_DROPSHADOW to work // #393 provoke a redraw for the CS_DROPSHADOW to work
opacity = ShownMinus; opacity = ShownMinus;
ChangeOpacity?.Invoke(this, opacity); ChangeOpacity?.Invoke(opacity);
} }
opacity = Shown; opacity = Shown;
ChangeOpacity?.Invoke(this, opacity); ChangeOpacity?.Invoke(opacity);
StartStopTimer(FadingState.Idle); StartStopTimer(FadingState.Idle);
} }
@ -119,24 +130,24 @@ namespace SystemTrayMenu.Helper
visible = true; visible = true;
Show?.Invoke(); Show?.Invoke();
opacity = 0; opacity = 0;
ChangeOpacity?.Invoke(this, opacity); ChangeOpacity?.Invoke(opacity);
} }
else if (Properties.Settings.Default.UseFading && else if (Properties.Settings.Default.UseFading &&
opacity < TransparentMinus) opacity < TransparentMinus)
{ {
opacity += StepIn; opacity += StepIn;
ChangeOpacity?.Invoke(this, opacity); ChangeOpacity?.Invoke(opacity);
} }
else if (Properties.Settings.Default.UseFading && else if (Properties.Settings.Default.UseFading &&
opacity > TransparentPlus) opacity > TransparentPlus)
{ {
opacity -= StepOut; opacity -= StepOut;
ChangeOpacity?.Invoke(this, opacity); ChangeOpacity?.Invoke(opacity);
} }
else else
{ {
opacity = Transparent; opacity = Transparent;
ChangeOpacity?.Invoke(this, opacity); ChangeOpacity?.Invoke(opacity);
StartStopTimer(FadingState.Idle); StartStopTimer(FadingState.Idle);
} }
@ -146,12 +157,12 @@ namespace SystemTrayMenu.Helper
opacity > StepOut) opacity > StepOut)
{ {
opacity -= StepOut; opacity -= StepOut;
ChangeOpacity?.Invoke(this, opacity); ChangeOpacity?.Invoke(opacity);
} }
else if (visible) else if (visible)
{ {
opacity = 0; opacity = 0;
ChangeOpacity?.Invoke(this, opacity); ChangeOpacity?.Invoke(opacity);
visible = false; visible = false;
Hide?.Invoke(); Hide?.Invoke();
StartStopTimer(FadingState.Idle); StartStopTimer(FadingState.Idle);

View file

@ -32,6 +32,11 @@ namespace SystemTrayMenu.Helpers
} }
} }
~JoystickHelper() // the finalizer
{
Dispose(false);
}
public event Action<Keys> KeyPressed; public event Action<Keys> KeyPressed;
public void Enable() public void Enable()
@ -54,6 +59,7 @@ namespace SystemTrayMenu.Helpers
{ {
if (disposing) if (disposing)
{ {
timerReadJoystick.Elapsed -= ReadJoystickLoop;
timerReadJoystick?.Dispose(); timerReadJoystick?.Dispose();
joystick?.Dispose(); joystick?.Dispose();
} }

View file

@ -13,7 +13,7 @@ namespace SystemTrayMenu.Helper
/// The enumeration of possible modifiers. /// The enumeration of possible modifiers.
/// </summary> /// </summary>
[Flags] [Flags]
internal enum KeyboardHookModifierKeys : uint public enum KeyboardHookModifierKeys : uint
{ {
None = 0, None = 0,
Alt = 1, Alt = 1,
@ -30,7 +30,7 @@ namespace SystemTrayMenu.Helper
public KeyboardHook() public KeyboardHook()
{ {
// register the event of the inner native window. // register the event of the inner native window.
window.KeyPressed += (sender, e) => KeyPressed?.Invoke(this, e); window.KeyPressed += Window_KeyPressed;
} }
/// <summary> /// <summary>
@ -47,6 +47,7 @@ namespace SystemTrayMenu.Helper
} }
// dispose the inner native window. // dispose the inner native window.
window.KeyPressed -= Window_KeyPressed;
window.Dispose(); window.Dispose();
} }
@ -104,6 +105,11 @@ namespace SystemTrayMenu.Helper
RegisterHotKey((uint)modifier, key); RegisterHotKey((uint)modifier, key);
} }
private void Window_KeyPressed(object sender, KeyPressedEventArgs e)
{
KeyPressed?.Invoke(this, e);
}
private void RegisterHotKey(uint modifier, Keys key) private void RegisterHotKey(uint modifier, Keys key)
{ {
currentId += 1; currentId += 1;

View file

@ -39,5 +39,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.3.1.7")] [assembly: AssemblyVersion("1.3.1.9")]
[assembly: AssemblyFileVersion("1.3.1.7")] [assembly: AssemblyFileVersion("1.3.1.9")]

View file

@ -15,7 +15,7 @@ namespace SystemTrayMenu.Helper
internal class AppContextMenu internal class AppContextMenu
{ {
public event EventHandlerEmpty ClickedOpenLog; public event Action ClickedOpenLog;
public ContextMenuStrip Create() public ContextMenuStrip Create()
{ {

View file

@ -41,9 +41,9 @@ namespace SystemTrayMenu.UserInterface
} }
} }
public event EventHandlerEmpty Click; public event Action Click;
public event EventHandlerEmpty OpenLog; public event Action OpenLog;
public void Dispose() public void Dispose()
{ {

View file

@ -204,6 +204,11 @@ namespace SystemTrayMenu.UserInterface
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
MouseDown -= CustomScrollbar_MouseDown;
MouseMove -= CustomScrollbar_MouseMove;
MouseUp -= CustomScrollbar_MouseUp;
MouseLeave -= CustomScrollbar_MouseLeave;
timerMouseStillClicked.Tick -= TimerMouseStillClicked_Tick;
timerMouseStillClicked.Dispose(); timerMouseStillClicked.Dispose();
base.Dispose(disposing); base.Dispose(disposing);
} }

View file

@ -14,6 +14,11 @@ namespace SystemTrayMenu.UserInterface.FolderBrowseDialog
{ {
private bool isDisposed; private bool isDisposed;
~FolderDialog() // the finalizer
{
Dispose(false);
}
/// <summary> /// <summary>
/// Gets or sets /sets folder in which dialog will be open. /// Gets or sets /sets folder in which dialog will be open.
/// </summary> /// </summary>

View file

@ -1,4 +1,7 @@
namespace SystemTrayMenu.UserInterface using System.Windows.Forms;
using SystemTrayMenu.Helper;
namespace SystemTrayMenu.UserInterface
{ {
partial class Menu partial class Menu
{ {
@ -19,9 +22,45 @@
} }
timerUpdateIcons.Stop(); timerUpdateIcons.Stop();
timerUpdateIcons.Tick -= TimerUpdateIcons_Tick;
timerUpdateIcons.Tick += TimerUpdateIcons_Tick_Loading;
timerUpdateIcons.Dispose(); timerUpdateIcons.Dispose();
fading.ChangeOpacity -= Fading_ChangeOpacity;
fading.Show -= Fading_Show;
fading.Hide -= Hide;
fading.Dispose(); fading.Dispose();
dgv.GotFocus -= Dgv_GotFocus;
dgv.MouseEnter -= ControlsMouseEnter;
dgv.MouseLeave -= ControlsMouseLeave;
customScrollbar.GotFocus -= CustomScrollbar_GotFocus;
customScrollbar.Scroll -= CustomScrollbar_Scroll;
customScrollbar.MouseEnter -= ControlsMouseEnter;
customScrollbar.MouseLeave -= ControlsMouseLeave;
customScrollbar.Dispose(); customScrollbar.Dispose();
labelTitle.MouseEnter -= ControlsMouseEnter;
labelTitle.MouseLeave -= ControlsMouseLeave;
textBoxSearch.MouseEnter -= ControlsMouseEnter;
textBoxSearch.MouseLeave -= ControlsMouseLeave;
pictureBoxOpenFolder.MouseEnter -= ControlsMouseEnter;
pictureBoxOpenFolder.MouseLeave -= ControlsMouseLeave;
pictureBoxMenuAlwaysOpen.MouseEnter -= ControlsMouseEnter;
pictureBoxMenuAlwaysOpen.MouseLeave -= ControlsMouseLeave;
pictureBoxMenuAlwaysOpen.Paint -= PictureBoxMenuAlwaysOpen_Paint;
pictureBoxMenuAlwaysOpen.Paint -= LoadingMenu_Paint;
pictureBoxSettings.MouseEnter -= ControlsMouseEnter;
pictureBoxSettings.MouseLeave -= ControlsMouseLeave;
pictureBoxRestart.MouseEnter -= ControlsMouseEnter;
pictureBoxRestart.MouseLeave -= ControlsMouseLeave;
pictureBoxSearch.MouseEnter -= ControlsMouseEnter;
pictureBoxSearch.MouseLeave -= ControlsMouseLeave;
tableLayoutPanelMenu.MouseEnter -= ControlsMouseEnter;
tableLayoutPanelMenu.MouseLeave -= ControlsMouseLeave;
tableLayoutPanelDgvAndScrollbar.MouseEnter -= ControlsMouseEnter;
tableLayoutPanelDgvAndScrollbar.MouseLeave -= ControlsMouseLeave;
tableLayoutPanelBottom.MouseEnter -= ControlsMouseEnter;
tableLayoutPanelBottom.MouseLeave -= ControlsMouseLeave;
labelItems.MouseEnter -= ControlsMouseEnter;
labelItems.MouseLeave -= ControlsMouseLeave;
base.Dispose(disposing); base.Dispose(disposing);
} }

View file

@ -32,144 +32,41 @@ namespace SystemTrayMenu.UserInterface
internal Menu() internal Menu()
{ {
fading.ChangeOpacity += Fading_ChangeOpacity; fading.ChangeOpacity += Fading_ChangeOpacity;
void Fading_ChangeOpacity(object sender, double newOpacity)
{
if (newOpacity != Opacity && !IsDisposed && !Disposing)
{
Opacity = newOpacity;
}
}
fading.Show += Fading_Show; fading.Show += Fading_Show;
void Fading_Show()
{
try
{
isShowing = true;
Visible = true;
isShowing = false;
timerUpdateIcons.Start();
}
catch (ObjectDisposedException)
{
Visible = false;
isShowing = false;
Log.Info($"Could not open menu, old menu was disposing," +
$" IsDisposed={IsDisposed}");
}
if (Visible)
{
if (Level == 0)
{
Activate();
NativeMethods.User32ShowInactiveTopmost(this);
NativeMethods.ForceForegroundWindow(Handle);
}
else
{
NativeMethods.User32ShowInactiveTopmost(this);
}
}
}
fading.Hide += Hide; fading.Hide += Hide;
InitializeComponent(); InitializeComponent();
SetDoubleBuffer(dgv, true); SetDoubleBuffer(dgv, true);
AdjustColors();
Color foreColor = Color.Black; dgv.GotFocus += Dgv_GotFocus;
Color backColor = AppColors.Background;
Color backColorSearch = AppColors.SearchField;
Color backgroundBorder = AppColors.BackgroundBorder;
if (Config.IsDarkMode())
{
foreColor = Color.White;
labelTitle.ForeColor = foreColor;
textBoxSearch.ForeColor = foreColor;
backColor = AppColors.DarkModeBackground;
backColorSearch = AppColors.DarkModeSearchField;
backgroundBorder = AppColors.DarkModeBackgroundBorder;
}
ColorConverter colorConverter = new();
labelItems.ForeColor = MenuDefines.ColorIcons;
if (backColor.R == 0)
{
backColor = Color.White;
}
BackColor = backgroundBorder;
labelTitle.BackColor = backColor;
tableLayoutPanelDgvAndScrollbar.BackColor = backColor;
tableLayoutPanelBottom.BackColor = backColor;
tableLayoutPanelMenu.BackColor = backColor;
dgv.BackgroundColor = backColor;
textBoxSearch.BackColor = backColorSearch;
panelLine.BackColor = AppColors.Icons;
pictureBoxSearch.BackColor = backColorSearch;
tableLayoutPanelSearch.BackColor = backColorSearch;
dgv.DefaultCellStyle = new DataGridViewCellStyle
{
SelectionForeColor = foreColor,
ForeColor = foreColor,
BackColor = backColor,
};
dgv.GotFocus += (sender, e) => FocusTextBox();
customScrollbar.GotFocus += (sender, e) => FocusTextBox();
customScrollbar.Margin = new Padding(0);
customScrollbar.Scroll += CustomScrollbar_Scroll;
void CustomScrollbar_Scroll(object sender, EventArgs e)
{
decimal firstIndex = customScrollbar.Value * dgv.Rows.Count / (decimal)customScrollbar.Maximum;
int firstIndexRounded = (int)Math.Ceiling(firstIndex);
if (firstIndexRounded > -1 && firstIndexRounded < dgv.RowCount)
{
dgv.FirstDisplayedScrollingRowIndex = firstIndexRounded;
}
}
customScrollbar.MouseEnter += ControlsMouseEnter;
dgv.MouseEnter += ControlsMouseEnter; dgv.MouseEnter += ControlsMouseEnter;
labelTitle.MouseEnter += ControlsMouseEnter;
textBoxSearch.MouseEnter += ControlsMouseEnter;
pictureBoxOpenFolder.MouseEnter += ControlsMouseEnter;
pictureBoxMenuAlwaysOpen.MouseEnter += ControlsMouseEnter;
pictureBoxSettings.MouseEnter += ControlsMouseEnter;
pictureBoxRestart.MouseEnter += ControlsMouseEnter;
pictureBoxSearch.MouseEnter += ControlsMouseEnter;
tableLayoutPanelMenu.MouseEnter += ControlsMouseEnter;
tableLayoutPanelDgvAndScrollbar.MouseEnter += ControlsMouseEnter;
tableLayoutPanelBottom.MouseEnter += ControlsMouseEnter;
labelItems.MouseEnter += ControlsMouseEnter;
void ControlsMouseEnter(object sender, EventArgs e)
{
MouseEnter?.Invoke();
}
customScrollbar.MouseLeave += ControlsMouseLeave;
dgv.MouseLeave += ControlsMouseLeave; dgv.MouseLeave += ControlsMouseLeave;
customScrollbar.Margin = new Padding(0);
customScrollbar.GotFocus += CustomScrollbar_GotFocus;
customScrollbar.Scroll += CustomScrollbar_Scroll;
customScrollbar.MouseEnter += ControlsMouseEnter;
customScrollbar.MouseLeave += ControlsMouseLeave;
labelTitle.MouseEnter += ControlsMouseEnter;
labelTitle.MouseLeave += ControlsMouseLeave; labelTitle.MouseLeave += ControlsMouseLeave;
textBoxSearch.MouseEnter += ControlsMouseEnter;
textBoxSearch.MouseLeave += ControlsMouseLeave; textBoxSearch.MouseLeave += ControlsMouseLeave;
pictureBoxMenuAlwaysOpen.MouseLeave += ControlsMouseLeave; pictureBoxOpenFolder.MouseEnter += ControlsMouseEnter;
pictureBoxOpenFolder.MouseLeave += ControlsMouseLeave; pictureBoxOpenFolder.MouseLeave += ControlsMouseLeave;
pictureBoxMenuAlwaysOpen.MouseEnter += ControlsMouseEnter;
pictureBoxMenuAlwaysOpen.MouseLeave += ControlsMouseLeave;
pictureBoxSettings.MouseEnter += ControlsMouseEnter;
pictureBoxSettings.MouseLeave += ControlsMouseLeave; pictureBoxSettings.MouseLeave += ControlsMouseLeave;
pictureBoxRestart.MouseEnter += ControlsMouseEnter;
pictureBoxRestart.MouseLeave += ControlsMouseLeave; pictureBoxRestart.MouseLeave += ControlsMouseLeave;
pictureBoxSearch.MouseEnter += ControlsMouseEnter;
pictureBoxSearch.MouseLeave += ControlsMouseLeave; pictureBoxSearch.MouseLeave += ControlsMouseLeave;
tableLayoutPanelMenu.MouseEnter += ControlsMouseEnter;
tableLayoutPanelMenu.MouseLeave += ControlsMouseLeave; tableLayoutPanelMenu.MouseLeave += ControlsMouseLeave;
tableLayoutPanelDgvAndScrollbar.MouseEnter += ControlsMouseEnter;
tableLayoutPanelDgvAndScrollbar.MouseLeave += ControlsMouseLeave; tableLayoutPanelDgvAndScrollbar.MouseLeave += ControlsMouseLeave;
tableLayoutPanelBottom.MouseEnter += ControlsMouseEnter;
tableLayoutPanelBottom.MouseLeave += ControlsMouseLeave; tableLayoutPanelBottom.MouseLeave += ControlsMouseLeave;
labelItems.MouseEnter += ControlsMouseEnter;
labelItems.MouseLeave += ControlsMouseLeave; labelItems.MouseLeave += ControlsMouseLeave;
void ControlsMouseLeave(object sender, EventArgs e)
{
MouseLeave?.Invoke();
}
bool isTouchEnabled = NativeMethods.IsTouchEnabled(); bool isTouchEnabled = NativeMethods.IsTouchEnabled();
if ((isTouchEnabled && Properties.Settings.Default.DragDropItemsEnabledTouch) || if ((isTouchEnabled && Properties.Settings.Default.DragDropItemsEnabledTouch) ||
(!isTouchEnabled && Properties.Settings.Default.DragDropItemsEnabled)) (!isTouchEnabled && Properties.Settings.Default.DragDropItemsEnabled))
@ -180,23 +77,23 @@ namespace SystemTrayMenu.UserInterface
} }
} }
internal new event EventHandlerEmpty MouseWheel; internal new event Action MouseWheel;
internal new event EventHandlerEmpty MouseEnter; internal new event Action MouseEnter;
internal new event EventHandlerEmpty MouseLeave; internal new event Action MouseLeave;
internal event EventHandlerEmpty UserClickedOpenFolder; internal event Action<string> UserClickedOpenFolder;
internal event EventHandler<Keys> CmdKeyProcessed; internal event EventHandler<Keys> CmdKeyProcessed;
internal event EventHandler<KeyPressEventArgs> KeyPressCheck; internal event EventHandler<KeyPressEventArgs> KeyPressCheck;
internal event EventHandlerEmpty SearchTextChanging; internal event Action SearchTextChanging;
internal event EventHandler<bool> SearchTextChanged; internal event EventHandler<bool> SearchTextChanged;
internal event EventHandlerEmpty UserDragsMenu; internal event Action UserDragsMenu;
internal enum MenuType internal enum MenuType
{ {
@ -218,6 +115,8 @@ namespace SystemTrayMenu.UserInterface
internal int Level { get; set; } internal int Level { get; set; }
internal string Path { get; set; }
internal bool IsUsable => Visible && !fading.IsHiding && !IsDisposed && !Disposing; internal bool IsUsable => Visible && !fading.IsHiding && !IsDisposed && !Disposing;
internal bool ScrollbarVisible { get; private set; } internal bool ScrollbarVisible { get; private set; }
@ -324,7 +223,7 @@ namespace SystemTrayMenu.UserInterface
pictureBoxMenuAlwaysOpen.Paint -= PictureBoxMenuAlwaysOpen_Paint; pictureBoxMenuAlwaysOpen.Paint -= PictureBoxMenuAlwaysOpen_Paint;
pictureBoxMenuAlwaysOpen.Paint += LoadingMenu_Paint; pictureBoxMenuAlwaysOpen.Paint += LoadingMenu_Paint;
timerUpdateIcons.Tick -= TimerUpdateIcons_Tick; timerUpdateIcons.Tick -= TimerUpdateIcons_Tick;
timerUpdateIcons.Tick += (sender, e) => pictureBoxMenuAlwaysOpen.Invalidate(); timerUpdateIcons.Tick += TimerUpdateIcons_Tick_Loading;
timerUpdateIcons.Interval = 15; timerUpdateIcons.Interval = 15;
break; break;
default: default:
@ -718,6 +617,117 @@ namespace SystemTrayMenu.UserInterface
CultureInfo.InvariantCulture); CultureInfo.InvariantCulture);
} }
private void Fading_ChangeOpacity(double newOpacity)
{
if (newOpacity != Opacity && !IsDisposed && !Disposing)
{
Opacity = newOpacity;
}
}
private void Fading_Show()
{
try
{
isShowing = true;
Visible = true;
isShowing = false;
timerUpdateIcons.Start();
}
catch (ObjectDisposedException)
{
Visible = false;
isShowing = false;
Log.Info($"Could not open menu, old menu was disposing," +
$" IsDisposed={IsDisposed}");
}
if (Visible)
{
if (Level == 0)
{
Activate();
NativeMethods.User32ShowInactiveTopmost(this);
NativeMethods.ForceForegroundWindow(Handle);
}
else
{
NativeMethods.User32ShowInactiveTopmost(this);
}
}
}
private void AdjustColors()
{
Color foreColor = Color.Black;
Color backColor = AppColors.Background;
Color backColorSearch = AppColors.SearchField;
Color backgroundBorder = AppColors.BackgroundBorder;
if (Config.IsDarkMode())
{
foreColor = Color.White;
labelTitle.ForeColor = foreColor;
textBoxSearch.ForeColor = foreColor;
backColor = AppColors.DarkModeBackground;
backColorSearch = AppColors.DarkModeSearchField;
backgroundBorder = AppColors.DarkModeBackgroundBorder;
}
ColorConverter colorConverter = new();
labelItems.ForeColor = MenuDefines.ColorIcons;
if (backColor.R == 0)
{
backColor = Color.White;
}
BackColor = backgroundBorder;
labelTitle.BackColor = backColor;
tableLayoutPanelDgvAndScrollbar.BackColor = backColor;
tableLayoutPanelBottom.BackColor = backColor;
tableLayoutPanelMenu.BackColor = backColor;
dgv.BackgroundColor = backColor;
textBoxSearch.BackColor = backColorSearch;
panelLine.BackColor = AppColors.Icons;
pictureBoxSearch.BackColor = backColorSearch;
tableLayoutPanelSearch.BackColor = backColorSearch;
dgv.DefaultCellStyle = new DataGridViewCellStyle
{
SelectionForeColor = foreColor,
ForeColor = foreColor,
BackColor = backColor,
};
}
private void Dgv_GotFocus(object sender, EventArgs e)
{
FocusTextBox();
}
private void CustomScrollbar_GotFocus(object sender, EventArgs e)
{
FocusTextBox();
}
private void CustomScrollbar_Scroll(object sender, EventArgs e)
{
decimal firstIndex = customScrollbar.Value * dgv.Rows.Count / (decimal)customScrollbar.Maximum;
int firstIndexRounded = (int)Math.Ceiling(firstIndex);
if (firstIndexRounded > -1 && firstIndexRounded < dgv.RowCount)
{
dgv.FirstDisplayedScrollingRowIndex = firstIndexRounded;
}
}
private void ControlsMouseEnter(object sender, EventArgs e)
{
MouseEnter?.Invoke();
}
private void ControlsMouseLeave(object sender, EventArgs e)
{
MouseLeave?.Invoke();
}
private void AdjustDataGridViewHeight(Menu menuPredecessor, int screenHeightMax) private void AdjustDataGridViewHeight(Menu menuPredecessor, int screenHeightMax)
{ {
double factor = Properties.Settings.Default.RowHeighteInPercentage / 100f; double factor = Properties.Settings.Default.RowHeighteInPercentage / 100f;
@ -753,12 +763,12 @@ namespace SystemTrayMenu.UserInterface
row.Height = dgv.RowTemplate.Height; row.Height = dgv.RowTemplate.Height;
} }
int dgvHeightByItems = dgv.Rows.GetRowsHeight(DataGridViewElementStates.None); int dgvHeightByItems = Math.Max(dgv.Rows.GetRowsHeight(DataGridViewElementStates.None), 1);
int dgvHeightMaxByScreen = screenHeightMax - (Height - dgv.Height); int dgvHeightMaxByScreen = screenHeightMax - (Height - dgv.Height);
int dgvHeightMaxByOptions = (int)(Scaling.Factor * Scaling.FactorByDpi * int dgvHeightMaxByOptions = (int)(Scaling.Factor * Scaling.FactorByDpi *
450f * (Properties.Settings.Default.HeightMaxInPercent / 100f)); 450f * (Properties.Settings.Default.HeightMaxInPercent / 100f));
int dgvHeightMax = Math.Min(dgvHeightMaxByScreen, dgvHeightMaxByOptions); int dgvHeightMax = Math.Min(dgvHeightMaxByScreen, dgvHeightMaxByOptions);
if (!dgvHeightSet && dgvHeightByItems > 0 && dgvHeightMax > 0) if (!dgvHeightSet)
{ {
dgv.Height = Math.Min(dgvHeightByItems, dgvHeightMax); dgv.Height = Math.Min(dgvHeightByItems, dgvHeightMax);
dgvHeightSet = true; dgvHeightSet = true;
@ -1035,7 +1045,7 @@ namespace SystemTrayMenu.UserInterface
{ {
if (e.Button == MouseButtons.Left) if (e.Button == MouseButtons.Left)
{ {
UserClickedOpenFolder?.Invoke(); UserClickedOpenFolder?.Invoke(Path);
} }
} }
@ -1145,6 +1155,11 @@ namespace SystemTrayMenu.UserInterface
} }
} }
private void TimerUpdateIcons_Tick_Loading(object sender, EventArgs e)
{
pictureBoxMenuAlwaysOpen.Invalidate();
}
private void Menu_MouseDown(object sender, MouseEventArgs e) private void Menu_MouseDown(object sender, MouseEventArgs e)
{ {
if (Level == 0) if (Level == 0)

View file

@ -4,6 +4,7 @@
namespace SystemTrayMenu.Utilities namespace SystemTrayMenu.Utilities
{ {
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -11,7 +12,7 @@ namespace SystemTrayMenu.Utilities
internal class AppRestart internal class AppRestart
{ {
public static event EventHandlerEmpty BeforeRestarting; public static event Action BeforeRestarting;
internal static void ByThreadException() internal static void ByThreadException()
{ {

View file

@ -1,8 +0,0 @@
// <copyright file="EventHandlerEmpty.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Utilities
{
public delegate void EventHandlerEmpty();
}