Code Analyze and Refactor 0.12 (#109), version 0.11.4.4

This commit is contained in:
Markus Hofknecht 2020-07-07 17:05:19 +02:00
parent 2686adf0df
commit d38750c0b9
47 changed files with 1615 additions and 1550 deletions

View file

@ -1,12 +1,11 @@
// <copyright file="App.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu
{
using Microsoft.Win32;
using System;
using System.Windows.Forms;
using Microsoft.Win32;
using SystemTrayMenu.Business;
using SystemTrayMenu.UserInterface;
using SystemTrayMenu.Utilities;
@ -61,6 +60,13 @@ namespace SystemTrayMenu
DllImports.NativeMethods.User32ShowInactiveTopmost(taskbarForm);
}
public void Dispose()
{
taskbarForm.Dispose();
menus.Dispose();
menuNotifyIcon.Dispose();
}
private void TaskbarForm_Deactivate(object sender, EventArgs e)
{
SetStateNormal();
@ -76,12 +82,5 @@ namespace SystemTrayMenu
taskbarForm.WindowState = FormWindowState.Normal;
}
}
public void Dispose()
{
taskbarForm.Dispose();
menus.Dispose();
menuNotifyIcon.Dispose();
}
}
}

View file

@ -16,8 +16,6 @@ namespace SystemTrayMenu.Handler
internal class KeyboardInput : IDisposable
{
internal bool InUse = false;
private readonly Menu[] menus;
private readonly KeyboardHook hook = new KeyboardHook();
@ -41,6 +39,8 @@ namespace SystemTrayMenu.Handler
internal event EventHandlerEmpty Cleared;
internal bool InUse { get; set; } = false;
public void Dispose()
{
hook.Dispose();
@ -205,6 +205,26 @@ namespace SystemTrayMenu.Handler
ClearIsSelectedByKey(iMenuKey, iRowKey);
}
internal void Select(DataGridView dgv, int i, bool refreshview)
{
int newiMenuKey = ((Menu)dgv.TopLevelControl).Level;
if (i != iRowKey || newiMenuKey != iMenuKey)
{
ClearIsSelectedByKey();
}
iRowKey = i;
iMenuKey = newiMenuKey;
DataGridViewRow row = dgv.Rows[i];
RowData rowData = (RowData)row.Cells[2].Value;
rowData.IsSelected = true;
if (refreshview)
{
row.Selected = false;
row.Selected = true;
}
}
private bool IsAnyMenuSelectedByKey(
ref DataGridView dgv,
ref Menu menuFromSelected,
@ -453,26 +473,6 @@ namespace SystemTrayMenu.Handler
return found;
}
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;
DataGridViewRow row = dgv.Rows[i];
RowData rowData = (RowData)row.Cells[2].Value;
rowData.IsSelected = true;
if (refreshview)
{
row.Selected = false;
row.Selected = true;
}
}
private bool Select(DataGridView dgv, int i, string keyInput = "")
{
bool found = false;

View file

@ -194,43 +194,6 @@ namespace SystemTrayMenu.Business
private List<Menu> AsList => AsEnumerable.ToList();
internal void SwitchOpenCloseByTaskbarItem()
{
SwitchOpenClose(true);
timerStillActiveCheck.Start();
}
internal void SwitchOpenClose(bool byClick)
{
waitToOpenMenu.MouseActive = byClick;
if (byClick && (DateTime.Now - deactivatedTime).TotalMilliseconds < 200)
{
// By click on notifyicon the menu gets deactivated and closed
}
else if (string.IsNullOrEmpty(Config.Path))
{
// Case when Folder Dialog open
}
else if (openCloseState == OpenCloseState.Opening ||
(menus[0].Visible && openCloseState == OpenCloseState.Default))
{
openCloseState = OpenCloseState.Closing;
MenusFadeOut();
StopWorker();
if (!AsEnumerable.Any(m => m.Visible))
{
openCloseState = OpenCloseState.Default;
}
}
else
{
openCloseState = OpenCloseState.Opening;
StartWorker();
}
deactivatedTime = DateTime.MinValue;
}
public void Dispose()
{
workerMainMenu.Dispose();
@ -247,38 +210,6 @@ namespace SystemTrayMenu.Business
DisposeMenu(menus[0]);
}
internal void DisposeMenu(Menu menuToDispose)
{
if (menuToDispose != null)
{
menuToDispose.MouseWheel -= AdjustMenusSizeAndLocation;
menuToDispose.MouseLeave -= waitLeave.Start;
menuToDispose.MouseEnter -= waitLeave.Stop;
menuToDispose.KeyPress -= keyboardInput.KeyPress;
menuToDispose.CmdKeyProcessed -= keyboardInput.CmdKeyProcessed;
menuToDispose.SearchTextChanging -= keyboardInput.SearchTextChanging;
menuToDispose.SearchTextChanged -= Menu_SearchTextChanged;
DataGridView dgv = menuToDispose.GetDataGridView();
dgv.CellMouseEnter -= waitToOpenMenu.MouseEnter;
dgv.CellMouseLeave -= waitToOpenMenu.MouseLeave;
dgv.MouseMove -= waitToOpenMenu.MouseMove;
dgv.MouseDown -= Dgv_MouseDown;
dgv.MouseDoubleClick -= Dgv_MouseDoubleClick;
dgv.SelectionChanged -= Dgv_SelectionChanged;
dgv.RowPostPaint -= Dgv_RowPostPaint;
dgv.ClearSelection();
foreach (DataGridViewRow row in dgv.Rows)
{
RowData rowData = (RowData)row.Cells[2].Value;
rowData.Dispose();
DisposeMenu(rowData.SubMenu);
}
menuToDispose.Dispose();
}
}
internal static MenuData GetData(BackgroundWorker worker, string path, int level)
{
MenuData menuData = new MenuData
@ -434,6 +365,75 @@ namespace SystemTrayMenu.Business
return menuData;
}
internal void SwitchOpenCloseByTaskbarItem()
{
SwitchOpenClose(true);
timerStillActiveCheck.Start();
}
internal void SwitchOpenClose(bool byClick)
{
waitToOpenMenu.MouseActive = byClick;
if (byClick && (DateTime.Now - deactivatedTime).TotalMilliseconds < 200)
{
// By click on notifyicon the menu gets deactivated and closed
}
else if (string.IsNullOrEmpty(Config.Path))
{
// Case when Folder Dialog open
}
else if (openCloseState == OpenCloseState.Opening ||
(menus[0].Visible && openCloseState == OpenCloseState.Default))
{
openCloseState = OpenCloseState.Closing;
MenusFadeOut();
StopWorker();
if (!AsEnumerable.Any(m => m.Visible))
{
openCloseState = OpenCloseState.Default;
}
}
else
{
openCloseState = OpenCloseState.Opening;
StartWorker();
}
deactivatedTime = DateTime.MinValue;
}
internal void DisposeMenu(Menu menuToDispose)
{
if (menuToDispose != null)
{
menuToDispose.MouseWheel -= AdjustMenusSizeAndLocation;
menuToDispose.MouseLeave -= waitLeave.Start;
menuToDispose.MouseEnter -= waitLeave.Stop;
menuToDispose.KeyPress -= keyboardInput.KeyPress;
menuToDispose.CmdKeyProcessed -= keyboardInput.CmdKeyProcessed;
menuToDispose.SearchTextChanging -= keyboardInput.SearchTextChanging;
menuToDispose.SearchTextChanged -= Menu_SearchTextChanged;
DataGridView dgv = menuToDispose.GetDataGridView();
dgv.CellMouseEnter -= waitToOpenMenu.MouseEnter;
dgv.CellMouseLeave -= waitToOpenMenu.MouseLeave;
dgv.MouseMove -= waitToOpenMenu.MouseMove;
dgv.MouseDown -= Dgv_MouseDown;
dgv.MouseDoubleClick -= Dgv_MouseDoubleClick;
dgv.SelectionChanged -= Dgv_SelectionChanged;
dgv.RowPostPaint -= Dgv_RowPostPaint;
dgv.ClearSelection();
foreach (DataGridViewRow row in dgv.Rows)
{
RowData rowData = (RowData)row.Cells[2].Value;
rowData.Dispose();
DisposeMenu(rowData.SubMenu);
}
menuToDispose.Dispose();
}
}
internal void MainPreload()
{
menus[0] = Create(
@ -509,6 +509,12 @@ namespace SystemTrayMenu.Business
return rowData;
}
private static bool IsActive()
{
return Form.ActiveForm is Menu ||
Form.ActiveForm is UserInterface.TaskbarForm;
}
private Menu Create(MenuData menuData, string title = null)
{
Menu menu = new Menu();
@ -777,12 +783,6 @@ namespace SystemTrayMenu.Business
}
}
private static bool IsActive()
{
return Form.ActiveForm is Menu ||
Form.ActiveForm is UserInterface.TaskbarForm;
}
private void MenusFadeOut()
{
openCloseState = OpenCloseState.Closing;

View file

@ -20,26 +20,26 @@ namespace SystemTrayMenu.Handler
public event EventHandlerEmpty LeaveTriggered;
public void Start()
public void Dispose()
{
timerLeaveCheck.Dispose();
}
internal void Start()
{
timerLeaveCheck.Stop();
timerLeaveCheck.Start();
}
public void Stop()
internal void Stop()
{
timerLeaveCheck.Stop();
}
private void TimerLeaveCheckTick(object sender, EventArgs e)
internal void TimerLeaveCheckTick(object sender, EventArgs e)
{
timerLeaveCheck.Stop();
LeaveTriggered?.Invoke();
}
public void Dispose()
{
timerLeaveCheck.Dispose();
}
}
}

View file

@ -13,8 +13,6 @@ namespace SystemTrayMenu.Handler
internal class WaitToLoadMenu : IDisposable
{
internal bool MouseActive = false;
private readonly Timer timerStartLoad = new Timer();
private DataGridView dgv = null;
private int rowIndex = 0;
@ -39,6 +37,16 @@ namespace SystemTrayMenu.Handler
internal event Action<DataGridView, int> MouseEnterOk;
internal bool MouseActive { get; set; } = false;
public void Dispose()
{
timerStartLoad.Stop();
timerStartLoad.Dispose();
dgv?.Dispose();
dgvTmp?.Dispose();
}
internal void MouseEnter(object sender, DataGridViewCellEventArgs e)
{
if (MouseActive)
@ -193,13 +201,5 @@ namespace SystemTrayMenu.Handler
this.rowIndex = 0;
}
}
public void Dispose()
{
timerStartLoad.Stop();
timerStartLoad.Dispose();
dgv?.Dispose();
dgvTmp?.Dispose();
}
}
}

19
Config/AppColors.cs Normal file
View file

@ -0,0 +1,19 @@
// <copyright file="AppColors.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu
{
using System.Drawing;
internal static class AppColors
{
internal static readonly Color Blue = Color.FromArgb(204, 232, 255);
internal static readonly Color BlueBorder = Color.FromArgb(153, 209, 255);
internal static readonly Color Green = Color.FromArgb(194, 245, 222);
internal static readonly Color GreenBorder = Color.FromArgb(153, 255, 165);
internal static readonly Color Red = Color.FromArgb(255, 204, 232);
internal static readonly Color Yellow = Color.LightYellow;
internal static readonly Color Azure = Color.Azure;
}
}

View file

@ -8,7 +8,7 @@ namespace SystemTrayMenu
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using SystemTrayMenu.UserInterface.Dialogs;
using SystemTrayMenu.UserInterface.FolderBrowseDialog;
using SystemTrayMenu.Utilities;
public static class Config

View file

@ -23,15 +23,4 @@ namespace SystemTrayMenu
internal static readonly Color ColorTitleSelected = AppColors.Yellow;
internal static readonly Color ColorTitleBackground = AppColors.Azure;
}
internal static class AppColors
{
internal static readonly Color Blue = Color.FromArgb(204, 232, 255);
internal static readonly Color BlueBorder = Color.FromArgb(153, 209, 255);
internal static readonly Color Green = Color.FromArgb(194, 245, 222);
internal static readonly Color GreenBorder = Color.FromArgb(153, 255, 165);
internal static readonly Color Red = Color.FromArgb(255, 204, 232);
internal static readonly Color Yellow = Color.LightYellow;
internal static readonly Color Azure = Color.Azure;
}
}

View file

@ -4,7 +4,6 @@
namespace SystemTrayMenu.DataClasses
{
using IWshRuntimeLibrary;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -16,24 +15,13 @@ namespace SystemTrayMenu.DataClasses
using System.Security;
using System.Text;
using System.Windows.Forms;
using IWshRuntimeLibrary;
using SystemTrayMenu.Utilities;
using TAFactory.IconPack;
using Menu = SystemTrayMenu.UserInterface.Menu;
internal class RowData : IDisposable
{
internal FileInfo FileInfo;
internal Menu SubMenu;
internal bool IsMenuOpen;
internal bool IsSelected;
internal bool ContainsMenu;
internal bool IsContextMenuOpen;
internal bool IsResolvedLnk;
internal bool HiddenEntry;
internal string TargetFilePath;
internal string TargetFilePathOrig;
internal int RowIndex;
internal int MenuLevel;
private static DateTime contextMenuClosed;
private string workingDirectory;
private string arguments;
@ -46,6 +34,36 @@ namespace SystemTrayMenu.DataClasses
{
}
internal FileInfo FileInfo { get; set; }
internal Menu SubMenu { get; set; }
internal bool IsMenuOpen { get; set; }
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 string TargetFilePath { get; set; }
internal string TargetFilePathOrig { get; set; }
internal int RowIndex { get; set; }
internal int MenuLevel { get; set; }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
internal void SetText(string text)
{
this.text = text;
@ -225,12 +243,6 @@ namespace SystemTrayMenu.DataClasses
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)

View file

@ -4,8 +4,10 @@
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1600:Elements should be documented", Justification = "TODO")]
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:Partial elements should be documented", Justification = "TODO")]
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1602:Enumeration items should be documented", Justification = "TODO")]
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA0001:XML comment analysis is disabled due to project configuration", Justification = "no idea what this is")]
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "we need to document")]
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:Partial elements should be documented", Justification = "we need to document")]
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1602:Enumeration items should be documented", Justification = "we need to document")]
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:Prefix local calls with this", Justification = "Standard codecleanup removes the this")]

View file

@ -51,11 +51,25 @@ namespace SystemTrayMenu.UserInterface
internal bool IsHiding => state == FadingState.Hide;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
internal void Fade(FadingState state)
{
StartStopTimer(state);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
timer.Dispose();
}
}
private void StartStopTimer(FadingState newState)
{
if (newState == FadingState.Idle)
@ -143,19 +157,5 @@ namespace SystemTrayMenu.UserInterface
break;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
timer.Dispose();
}
}
}
}

View file

@ -0,0 +1,28 @@
// <copyright file="KeyPressedEventArgs.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Helper
{
using System;
using System.Windows.Forms;
/// <summary>
/// Event Args for the event that is fired after the hot key has been pressed.
/// </summary>
internal class KeyPressedEventArgs : EventArgs
{
private readonly KeyboardHookModifierKeys modifier;
private readonly Keys key;
internal KeyPressedEventArgs(KeyboardHookModifierKeys modifier, Keys key)
{
this.modifier = modifier;
this.key = key;
}
internal KeyboardHookModifierKeys Modifier => modifier;
internal Keys Key => key;
}
}

View file

@ -6,7 +6,7 @@ namespace SystemTrayMenu.Helper
{
using System;
using System.Windows.Forms;
using SystemTrayMenu.UserInterface.Controls;
using SystemTrayMenu.UserInterface.HotkeyTextboxControl;
using SystemTrayMenu.Utilities;
/// <summary>
@ -160,23 +160,4 @@ namespace SystemTrayMenu.Helper
}
}
}
/// <summary>
/// Event Args for the event that is fired after the hot key has been pressed.
/// </summary>
internal class KeyPressedEventArgs : EventArgs
{
private readonly KeyboardHookModifierKeys modifier;
private readonly Keys key;
internal KeyPressedEventArgs(KeyboardHookModifierKeys modifier, Keys key)
{
this.modifier = modifier;
this.key = key;
}
internal KeyboardHookModifierKeys Modifier => modifier;
internal Keys Key => key;
}
}

View file

@ -12,13 +12,13 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
// The CreatePopupMenu function creates a drop-down menu, submenu, or shortcut menu. The menu is initially empty. You can insert or append menu items by using the InsertMenuItem function. You can also use the InsertMenu function to insert menu items and the AppendMenu function to append menu items.
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr CreatePopupMenu();
public static IntPtr User32CreatePopupMenu()
{
return CreatePopupMenu();
}
// The CreatePopupMenu function creates a drop-down menu, submenu, or shortcut menu. The menu is initially empty. You can insert or append menu items by using the InsertMenuItem function. You can also use the InsertMenu function to insert menu items and the AppendMenu function to append menu items.
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr CreatePopupMenu();
}
}

View file

@ -12,12 +12,12 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
[DllImport("User32.dll")]
private static extern int DestroyIcon(IntPtr hIcon);
public static void User32DestroyIcon(IntPtr hIcon)
{
_ = DestroyIcon(hIcon);
}
[DllImport("User32.dll")]
private static extern int DestroyIcon(IntPtr hIcon);
}
}

View file

@ -12,13 +12,13 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
// The DestroyMenu function destroys the specified menu and frees any memory that the menu occupies.
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool DestroyMenu(IntPtr hMenu);
public static bool User32DestroyMenu(IntPtr hMenu)
{
return DestroyMenu(hMenu);
}
// The DestroyMenu function destroys the specified menu and frees any memory that the menu occupies.
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool DestroyMenu(IntPtr hMenu);
}
}

View file

@ -12,12 +12,12 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
private static extern int FindExecutable(string lpFile, string lpDirectory, [Out] StringBuilder lpResult);
public static void Shell32FindExecutable(string lpFile, string lpDirectory, [Out] StringBuilder lpResult)
{
_ = FindExecutable(lpFile, lpDirectory, lpResult);
}
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
private static extern int FindExecutable(string lpFile, string lpDirectory, [Out] StringBuilder lpResult);
}
}

View file

@ -12,13 +12,13 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
// Determines the default menu item on the specified menu
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int GetMenuDefaultItem(IntPtr hMenu, bool fByPos, uint gmdiFlags);
public static int User32GetMenuDefaultItem(IntPtr hMenu, bool fByPos, uint gmdiFlags)
{
return GetMenuDefaultItem(hMenu, fByPos, gmdiFlags);
}
// Determines the default menu item on the specified menu
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int GetMenuDefaultItem(IntPtr hMenu, bool fByPos, uint gmdiFlags);
}
}

View file

@ -13,20 +13,6 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint virtualKeyCode);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int GetKeyNameText(uint lParam, [Out] StringBuilder lpString, int nSize);
public static bool User32RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk)
{
return RegisterHotKey(hWnd, id, fsModifiers, vk);
@ -46,5 +32,19 @@ namespace SystemTrayMenu.DllImports
{
return GetKeyNameText(lParam, lpString, nSize);
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint virtualKeyCode);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int GetKeyNameText(uint lParam, [Out] StringBuilder lpString, int nSize);
}
}

View file

@ -12,13 +12,13 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
// Retrieves the IShellFolder interface for the desktop folder, which is the root of the Shell's namespace.
[DllImport("shell32.dll")]
private static extern int SHGetDesktopFolder(out IntPtr ppshf);
public static int Shell32SHGetDesktopFolder(out IntPtr ppshf)
{
return SHGetDesktopFolder(out ppshf);
}
// Retrieves the IShellFolder interface for the desktop folder, which is the root of the Shell's namespace.
[DllImport("shell32.dll")]
private static extern int SHGetDesktopFolder(out IntPtr ppshf);
}
}

View file

@ -13,12 +13,12 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
[DllImport("shfolder.dll", CharSet = CharSet.Unicode)]
private static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, StringBuilder lpszPath);
public static int ShfolderSHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, StringBuilder lpszPath)
{
return SHGetFolderPath(hwndOwner, nFolder, hToken, dwFlags, lpszPath);
}
[DllImport("shfolder.dll", CharSet = CharSet.Unicode)]
private static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, StringBuilder lpszPath);
}
}

View file

@ -11,12 +11,12 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
[DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
public static void User32SetProcessDPIAware()
{
_ = SetProcessDPIAware();
}
[DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
}
}

View file

@ -11,12 +11,12 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern int StrCmpLogicalW(string x, string y);
public static int ShlwapiStrCmpLogicalW(string x, string y)
{
return StrCmpLogicalW(x, y);
}
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern int StrCmpLogicalW(string x, string y);
}
}

View file

@ -13,13 +13,13 @@ namespace SystemTrayMenu.DllImports
/// </summary>
public static partial class NativeMethods
{
// Takes a STRRET structure returned by IShellFolder::GetDisplayNameOf, converts it to a string, and places the result in a buffer.
[DllImport("shlwapi.dll", EntryPoint = "StrRetToBuf", ExactSpelling = false, CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int StrRetToBuf(IntPtr pstr, IntPtr pidl, StringBuilder pszBuf, int cchBuf);
public static int ShlwapiStrRetToBuf(IntPtr pstr, IntPtr pidl, StringBuilder pszBuf, int cchBuf)
{
return StrRetToBuf(pstr, pidl, pszBuf, cchBuf);
}
// Takes a STRRET structure returned by IShellFolder::GetDisplayNameOf, converts it to a string, and places the result in a buffer.
[DllImport("shlwapi.dll", EntryPoint = "StrRetToBuf", ExactSpelling = false, CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int StrRetToBuf(IntPtr pstr, IntPtr pidl, StringBuilder pszBuf, int cchBuf);
}
}

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
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.11.4.3")]
[assembly: AssemblyFileVersion("0.11.4.3")]
[assembly: AssemblyVersion("0.11.4.4")]
[assembly: AssemblyFileVersion("0.11.4.4")]

View file

@ -197,10 +197,6 @@
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.164">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View file

@ -4,7 +4,6 @@
namespace SystemTrayMenu.UserInterface
{
using Microsoft.Win32;
using System;
using System.Collections.Specialized;
using System.Drawing;
@ -14,6 +13,7 @@ namespace SystemTrayMenu.UserInterface
using System.Security;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Microsoft.Win32;
using SystemTrayMenu.Utilities;
/// <summary>
@ -189,14 +189,6 @@ namespace SystemTrayMenu.UserInterface
set => buttonDetails.Visible = value;
}
private void TabPanelDetails_SelectedIndexChanged(object sender, EventArgs e)
{
if (TabPanelDetails.SelectedTab == TabPageAssemblyDetails)
{
AssemblyNamesComboBox.Focus();
}
}
// <summary>
// exception-safe retrieval of LastWriteTime for this assembly.
// </summary>
@ -438,6 +430,64 @@ namespace SystemTrayMenu.UserInterface
return strSysInfoPath;
}
// <summary>
// populate a listview with the specified key and value strings
// </summary>
private static void Populate(ListView lvw, string key, string value)
{
if (!string.IsNullOrEmpty(value))
{
ListViewItem lvi = new ListViewItem
{
Text = key,
};
lvi.SubItems.Add(value);
lvw.Items.Add(lvi);
}
}
// <summary>
// populate details for a single assembly
// </summary>
private static void PopulateAssemblyDetails(Assembly a, ListView lvw)
{
lvw.Items.Clear();
// this assembly property is only available in framework versions 1.1+
Populate(lvw, "Image Runtime Version", a.ImageRuntimeVersion);
Populate(lvw, "Loaded from GAC", a.GlobalAssemblyCache.ToString(CultureInfo.InvariantCulture));
NameValueCollection nvc = AssemblyAttribs(a);
foreach (string strKey in nvc)
{
Populate(lvw, strKey, nvc[strKey]);
}
}
// <summary>
// matches assembly by Assembly.GetName.Name; returns nothing if no match
// </summary>
private static Assembly MatchAssemblyByName(string assemblyName)
{
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
if (a.GetName().Name == assemblyName)
{
return a;
}
}
return null;
}
private void TabPanelDetails_SelectedIndexChanged(object sender, EventArgs e)
{
if (TabPanelDetails.SelectedTab == TabPageAssemblyDetails)
{
AssemblyNamesComboBox.Focus();
}
}
// <summary>
// launch the MSInfo "system information" application (works on XP, 2003, and Vista)
// </summary>
@ -464,22 +514,6 @@ namespace SystemTrayMenu.UserInterface
Log.ProcessStart(strSysInfoPath);
}
// <summary>
// populate a listview with the specified key and value strings
// </summary>
private static void Populate(ListView lvw, string key, string value)
{
if (!string.IsNullOrEmpty(value))
{
ListViewItem lvi = new ListViewItem
{
Text = key,
};
lvi.SubItems.Add(value);
lvw.Items.Add(lvi);
}
}
// <summary>
// populates the Application Information listview
// </summary>
@ -620,40 +654,6 @@ namespace SystemTrayMenu.UserInterface
return s;
}
// <summary>
// populate details for a single assembly
// </summary>
private static void PopulateAssemblyDetails(Assembly a, ListView lvw)
{
lvw.Items.Clear();
// this assembly property is only available in framework versions 1.1+
Populate(lvw, "Image Runtime Version", a.ImageRuntimeVersion);
Populate(lvw, "Loaded from GAC", a.GlobalAssemblyCache.ToString(CultureInfo.InvariantCulture));
NameValueCollection nvc = AssemblyAttribs(a);
foreach (string strKey in nvc)
{
Populate(lvw, strKey, nvc[strKey]);
}
}
// <summary>
// matches assembly by Assembly.GetName.Name; returns nothing if no match
// </summary>
private static Assembly MatchAssemblyByName(string assemblyName)
{
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
if (a.GetName().Name == assemblyName)
{
return a;
}
}
return null;
}
// <summary>
// things to do when form is loaded
// </summary>

View file

@ -82,14 +82,6 @@ namespace SystemTrayMenu.UserInterface
public event EventHandlerEmpty Exit;
private void VerifyClick(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Click?.Invoke();
}
}
public void Dispose()
{
notifyIcon.Icon = null;
@ -109,6 +101,14 @@ namespace SystemTrayMenu.UserInterface
threadsLoading = false;
}
private void VerifyClick(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Click?.Invoke();
}
}
private void Load_Tick(object sender, EventArgs e)
{
if (threadsLoading)

View file

@ -0,0 +1,157 @@
// <copyright file="FolderDialog.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.UserInterface.FolderBrowseDialog
{
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using SystemTrayMenu.Utilities;
public class FolderDialog : IFolderDialog, IDisposable
{
private bool isDisposed;
/// <summary>
/// Gets or sets /sets folder in which dialog will be open.
/// </summary>
public string InitialFolder { get; set; }
/// <summary>
/// Gets or sets /sets directory in which dialog will be open
/// if there is no recent directory available.
/// </summary>
public string DefaultFolder { get; set; }
/// <summary>
/// Gets or sets selected folder.
/// </summary>
public string Folder { get; set; }
public DialogResult ShowDialog()
{
return ShowDialog(owner: new WindowWrapper(IntPtr.Zero));
}
public DialogResult ShowDialog(IWin32Window owner)
{
if (Environment.OSVersion.Version.Major >= 6)
{
return ShowVistaDialog(owner);
}
else
{
return ShowLegacyDialog(owner);
}
}
public DialogResult ShowVistaDialog(IWin32Window owner)
{
NativeMethods.IFileDialog frm = (NativeMethods.IFileDialog)new NativeMethods.FileOpenDialogRCW();
frm.GetOptions(out uint options);
options |= NativeMethods.FOS_PICKFOLDERS |
NativeMethods.FOS_FORCEFILESYSTEM |
NativeMethods.FOS_NOVALIDATE |
NativeMethods.FOS_NOTESTFILECREATE |
NativeMethods.FOS_DONTADDTORECENT;
frm.SetOptions(options);
if (InitialFolder != null)
{
Guid riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); // IShellItem
if (NativeMethods.SHCreateItemFromParsingName(
InitialFolder,
IntPtr.Zero,
ref riid,
out NativeMethods.IShellItem directoryShellItem) == NativeMethods.S_OK)
{
frm.SetFolder(directoryShellItem);
}
}
if (DefaultFolder != null)
{
Guid riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); // IShellItem
if (NativeMethods.SHCreateItemFromParsingName(
DefaultFolder,
IntPtr.Zero,
ref riid,
out NativeMethods.IShellItem directoryShellItem) == NativeMethods.S_OK)
{
frm.SetDefaultFolder(directoryShellItem);
}
}
if (owner != null && frm.Show(owner.Handle) == NativeMethods.S_OK)
{
if (frm.GetResult(out NativeMethods.IShellItem shellItem) == NativeMethods.S_OK)
{
if (shellItem.GetDisplayName(
NativeMethods.SIGDN_FILESYSPATH,
out IntPtr pszString) == NativeMethods.S_OK)
{
if (pszString != IntPtr.Zero)
{
try
{
Folder = Marshal.PtrToStringAuto(pszString);
return DialogResult.OK;
}
finally
{
Marshal.FreeCoTaskMem(pszString);
}
}
}
}
}
return DialogResult.Cancel;
}
public DialogResult ShowLegacyDialog(IWin32Window owner)
{
using SaveFileDialog frm = new SaveFileDialog
{
CheckFileExists = false,
CheckPathExists = true,
CreatePrompt = false,
Filter = "|" + Guid.Empty.ToString(),
FileName = "any",
};
if (InitialFolder != null)
{
frm.InitialDirectory = InitialFolder;
}
frm.OverwritePrompt = false;
frm.Title = Translator.GetText("Select Folder");
frm.ValidateNames = false;
if (frm.ShowDialog(owner) == DialogResult.OK)
{
Folder = Path.GetDirectoryName(frm.FileName);
return DialogResult.OK;
}
else
{
return DialogResult.Cancel;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)
{
}
isDisposed = true;
}
}
}

View file

@ -2,7 +2,7 @@
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.UserInterface.Dialogs
namespace SystemTrayMenu.UserInterface.FolderBrowseDialog
{
using System.Windows.Forms;

View file

@ -1,179 +1,12 @@
// <copyright file="FolderDialog.cs" company="PlaceholderCompany">
// <copyright file="NativeMethods.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.UserInterface.Dialogs
namespace SystemTrayMenu.UserInterface.FolderBrowseDialog
{
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using SystemTrayMenu.Utilities;
public class FolderDialog : IFolderDialog, IDisposable
{
private bool isDisposed;
/// <summary>
/// Gets or sets /sets folder in which dialog will be open.
/// </summary>
public string InitialFolder { get; set; }
/// <summary>
/// Gets or sets /sets directory in which dialog will be open
/// if there is no recent directory available.
/// </summary>
public string DefaultFolder { get; set; }
/// <summary>
/// Gets or sets selected folder.
/// </summary>
public string Folder { get; set; }
public DialogResult ShowDialog()
{
return ShowDialog(owner: new WindowWrapper(IntPtr.Zero));
}
public DialogResult ShowDialog(IWin32Window owner)
{
if (Environment.OSVersion.Version.Major >= 6)
{
return ShowVistaDialog(owner);
}
else
{
return ShowLegacyDialog(owner);
}
}
public DialogResult ShowVistaDialog(IWin32Window owner)
{
NativeMethods.IFileDialog frm = (NativeMethods.IFileDialog)new NativeMethods.FileOpenDialogRCW();
frm.GetOptions(out uint options);
options |= NativeMethods.FOS_PICKFOLDERS |
NativeMethods.FOS_FORCEFILESYSTEM |
NativeMethods.FOS_NOVALIDATE |
NativeMethods.FOS_NOTESTFILECREATE |
NativeMethods.FOS_DONTADDTORECENT;
frm.SetOptions(options);
if (InitialFolder != null)
{
Guid riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); // IShellItem
if (NativeMethods.SHCreateItemFromParsingName(
InitialFolder,
IntPtr.Zero,
ref riid,
out NativeMethods.IShellItem directoryShellItem) == NativeMethods.S_OK)
{
frm.SetFolder(directoryShellItem);
}
}
if (DefaultFolder != null)
{
Guid riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); // IShellItem
if (NativeMethods.SHCreateItemFromParsingName(
DefaultFolder,
IntPtr.Zero,
ref riid,
out NativeMethods.IShellItem directoryShellItem) == NativeMethods.S_OK)
{
frm.SetDefaultFolder(directoryShellItem);
}
}
if (owner != null && frm.Show(owner.Handle) == NativeMethods.S_OK)
{
if (frm.GetResult(out NativeMethods.IShellItem shellItem) == NativeMethods.S_OK)
{
if (shellItem.GetDisplayName(
NativeMethods.SIGDN_FILESYSPATH,
out IntPtr pszString) == NativeMethods.S_OK)
{
if (pszString != IntPtr.Zero)
{
try
{
Folder = Marshal.PtrToStringAuto(pszString);
return DialogResult.OK;
}
finally
{
Marshal.FreeCoTaskMem(pszString);
}
}
}
}
}
return DialogResult.Cancel;
}
public DialogResult ShowLegacyDialog(IWin32Window owner)
{
using SaveFileDialog frm = new SaveFileDialog
{
CheckFileExists = false,
CheckPathExists = true,
CreatePrompt = false,
Filter = "|" + Guid.Empty.ToString(),
FileName = "any",
};
if (InitialFolder != null)
{
frm.InitialDirectory = InitialFolder;
}
frm.OverwritePrompt = false;
frm.Title = Translator.GetText("Select Folder");
frm.ValidateNames = false;
if (frm.ShowDialog(owner) == DialogResult.OK)
{
Folder = Path.GetDirectoryName(frm.FileName);
return DialogResult.OK;
}
else
{
return DialogResult.Cancel;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)
{
}
isDisposed = true;
}
}
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
/// <summary>
/// Initializes a new instance of the <see cref="WindowWrapper"/> class.
/// </summary>
/// <param name="handle">Handle to wrap.</param>
public WindowWrapper(IntPtr handle)
{
hwnd = handle;
}
/// <summary>
/// Gets original ptr.
/// </summary>
public IntPtr Handle => hwnd;
private readonly IntPtr hwnd;
}
internal static class NativeMethods
{
@ -187,14 +20,6 @@ namespace SystemTrayMenu.UserInterface.Dialogs
public const uint SIGDN_FILESYSPATH = 0x80058000;
[ComImport]
[ClassInterface(ClassInterfaceType.None)]
[TypeLibType(TypeLibTypeFlags.FCanCreate)]
[Guid("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7")]
internal class FileOpenDialogRCW
{
}
[ComImport]
[Guid("42F85136-DB7E-439C-85F1-E4075D135FC8")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
@ -308,5 +133,13 @@ namespace SystemTrayMenu.UserInterface.Dialogs
IntPtr pbc,
ref Guid riid,
[MarshalAs(UnmanagedType.Interface)] out IShellItem ppv);
[ComImport]
[ClassInterface(ClassInterfaceType.None)]
[TypeLibType(TypeLibTypeFlags.FCanCreate)]
[Guid("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7")]
internal class FileOpenDialogRCW
{
}
}
}

View file

@ -0,0 +1,27 @@
// <copyright file="WindowWrapper.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.UserInterface.FolderBrowseDialog
{
using System;
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
private readonly IntPtr hwnd;
/// <summary>
/// Initializes a new instance of the <see cref="WindowWrapper"/> class.
/// </summary>
/// <param name="handle">Handle to wrap.</param>
public WindowWrapper(IntPtr handle)
{
hwnd = handle;
}
/// <summary>
/// Gets original ptr.
/// </summary>
public IntPtr Handle => hwnd;
}
}

View file

@ -0,0 +1,34 @@
// <copyright file="EventDelay.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.UserInterface.HotkeyTextboxControl
{
using System;
#pragma warning restore CA1308
public class EventDelay
{
private readonly long waitTime;
private long lastCheck;
public EventDelay(long ticks)
{
waitTime = ticks;
}
public bool Check()
{
#pragma warning disable CA2002
lock (this)
#pragma warning restore CA2002
{
long now = DateTime.Now.Ticks;
bool isPassed = now - lastCheck > waitTime;
lastCheck = now;
return isPassed;
}
}
}
}

View file

@ -2,7 +2,7 @@
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.UserInterface.Controls
namespace SystemTrayMenu.UserInterface.HotkeyTextboxControl
{
using System;
using System.Collections.Generic;
@ -55,24 +55,6 @@ namespace SystemTrayMenu.UserInterface.Controls
PopulateModifierLists();
}
/// <summary>
/// Gets or sets used to make sure that there is no right-click menu available.
/// </summary>
public override ContextMenuStrip ContextMenuStrip
{
get => dummy;
set => base.ContextMenuStrip = dummy;
}
/// <summary>
/// Gets or sets a value indicating whether forces the control to be non-multiline.
/// </summary>
public override bool Multiline
{
get => base.Multiline;
set => base.Multiline = false;
}
// Delegates for hooking up events.
public delegate void HotKeyHandler();
@ -96,143 +78,21 @@ namespace SystemTrayMenu.UserInterface.Controls
}
/// <summary>
/// Populates the ArrayLists specifying disallowed hotkeys
/// such as Shift+A, Ctrl+Alt+4 (would produce a dollar sign) etc.
/// Gets or sets used to make sure that there is no right-click menu available.
/// </summary>
private void PopulateModifierLists()
public override ContextMenuStrip ContextMenuStrip
{
// Shift + 0 - 9, A - Z
for (Keys k = Keys.D0; k <= Keys.Z; k++)
{
needNonShiftModifier.Add((int)k);
}
// Shift + Numpad keys
for (Keys k = Keys.NumPad0; k <= Keys.NumPad9; k++)
{
needNonShiftModifier.Add((int)k);
}
// Shift + Misc (,;<./ etc)
for (Keys k = Keys.Oem1; k <= Keys.OemBackslash; k++)
{
needNonShiftModifier.Add((int)k);
}
// Shift + Space, PgUp, PgDn, End, Home
for (Keys k = Keys.Space; k <= Keys.Home; k++)
{
needNonShiftModifier.Add((int)k);
}
// Misc keys that we can't loop through
needNonShiftModifier.Add((int)Keys.Insert);
needNonShiftModifier.Add((int)Keys.Help);
needNonShiftModifier.Add((int)Keys.Multiply);
needNonShiftModifier.Add((int)Keys.Add);
needNonShiftModifier.Add((int)Keys.Subtract);
needNonShiftModifier.Add((int)Keys.Divide);
needNonShiftModifier.Add((int)Keys.Decimal);
needNonShiftModifier.Add((int)Keys.Return);
needNonShiftModifier.Add((int)Keys.Escape);
needNonShiftModifier.Add((int)Keys.NumLock);
// Ctrl+Alt + 0 - 9
for (Keys k = Keys.D0; k <= Keys.D9; k++)
{
needNonAltGrModifier.Add((int)k);
}
get => dummy;
set => base.ContextMenuStrip = dummy;
}
/// <summary>
/// Resets this hotkey control to None.
/// Gets or sets a value indicating whether forces the control to be non-multiline.
/// </summary>
public new void Clear()
public override bool Multiline
{
Hotkey = Keys.None;
HotkeyModifiers = Keys.None;
}
/// <summary>
/// Fires when a key is pushed down. Here, we'll want to update the text in the box
/// to notify the user what combination is currently pressed.
/// </summary>
private void HotkeyControl_KeyDown(object sender, KeyEventArgs e)
{
// Clear the current hotkey
if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete)
{
ResetHotkey();
}
else
{
modifiers = e.Modifiers;
hotkey = e.KeyCode;
Redraw();
}
}
/// <summary>
/// Fires when all keys are released. If the current hotkey isn't valid, reset it.
/// Otherwise, do nothing and keep the text and hotkey as it was.
/// </summary>
private void HotkeyControl_KeyUp(object sender, KeyEventArgs e)
{
// Somehow the PrintScreen only comes as a keyup, therefore we handle it here.
if (e.KeyCode == Keys.PrintScreen)
{
modifiers = e.Modifiers;
hotkey = e.KeyCode;
Redraw();
}
if (hotkey == Keys.None && ModifierKeys == Keys.None)
{
ResetHotkey();
}
}
/// <summary>
/// Prevents the letter/whatever entered to show up in the TextBox
/// Without this, a "A" key press would appear as "aControl, Alt + A".
/// </summary>
private void HotkeyControl_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = true;
}
/// <summary>
/// Handles some misc keys, such as Ctrl+Delete and Shift+Insert.
/// </summary>
/// <param name="msg">msg.</param>
/// <param name="keyData">keyData.</param>
/// <returns>bool if handled.</returns>
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Delete || keyData == (Keys.Control | Keys.Delete))
{
ResetHotkey();
return true;
}
// Paste
if (keyData == (Keys.Shift | Keys.Insert))
{
return true; // Don't allow
}
// Allow the rest
return base.ProcessCmdKey(ref msg, keyData);
}
/// <summary>
/// Clears the current hotkey and resets the TextBox.
/// </summary>
public void ResetHotkey()
{
hotkey = Keys.None;
modifiers = Keys.None;
Redraw();
get => base.Multiline;
set => base.Multiline = false;
}
/// <summary>
@ -248,17 +108,6 @@ namespace SystemTrayMenu.UserInterface.Controls
}
}
/// <summary>
/// Used to get/set the hotkey (e.g. Keys.A).
/// </summary>
/// <param name="hotkey">hotkey.</param>
public void SetHotkey(string hotkey)
{
this.hotkey = HotkeyFromString(hotkey);
modifiers = HotkeyModifiersFromString(hotkey);
Redraw(true);
}
/// <summary>
/// Gets or sets used to get/set the modifier keys (e.g. Keys.Alt | Keys.Control).
/// </summary>
@ -272,80 +121,6 @@ namespace SystemTrayMenu.UserInterface.Controls
}
}
/// <summary>
/// Redraws the TextBox when necessary.
/// </summary>
/// <param name="bCalledProgramatically">Specifies whether this function was called by the Hotkey/HotkeyModifiers properties or by the user.</param>
private void Redraw(bool bCalledProgramatically = false)
{
// No hotkey set
if (hotkey == Keys.None)
{
Text = string.Empty;
return;
}
// LWin/RWin doesn't work as hotkeys (neither do they work as modifier keys in .NET 2.0)
if (hotkey == Keys.LWin || hotkey == Keys.RWin)
{
Text = string.Empty;
return;
}
// Only validate input if it comes from the user
if (bCalledProgramatically == false)
{
// No modifier or shift only, AND a hotkey that needs another modifier
if ((modifiers == Keys.Shift || modifiers == Keys.None) && needNonShiftModifier.Contains((int)hotkey))
{
if (modifiers == Keys.None)
{
// Set Ctrl+Alt as the modifier unless Ctrl+Alt+<key> won't work...
if (needNonAltGrModifier.Contains((int)hotkey) == false)
{
modifiers = Keys.Alt | Keys.Control;
}
else
{
// ... in that case, use Shift+Alt instead.
modifiers = Keys.Alt | Keys.Shift;
}
}
else
{
// User pressed Shift and an invalid key (e.g. a letter or a number),
// that needs another set of modifier keys
hotkey = Keys.None;
Text = string.Empty;
return;
}
}
// Check all Ctrl+Alt keys
if ((modifiers == (Keys.Alt | Keys.Control)) && needNonAltGrModifier.Contains((int)hotkey))
{
// Ctrl+Alt+4 etc won't work; reset hotkey and tell the user
hotkey = Keys.None;
Text = string.Empty;
return;
}
}
// I have no idea why this is needed, but it is. Without this code, pressing only Ctrl
// will show up as "Control + ControlKey", etc.
if (hotkey == Keys.Menu /* Alt */ || hotkey == Keys.ShiftKey || hotkey == Keys.ControlKey)
{
hotkey = Keys.None;
}
Text = HotkeyToLocalizedString(modifiers, hotkey);
}
public override string ToString()
{
return HotkeyToString(HotkeyModifiers, Hotkey);
}
public static string GetLocalizedHotkeyStringFromString(string hotkeyString)
{
Keys virtualKeyCode = HotkeyFromString(hotkeyString);
@ -679,30 +454,230 @@ namespace SystemTrayMenu.UserInterface.Controls
return givenKey.ToString();
}
}
}
#pragma warning restore CA1308
public class EventDelay
{
private readonly long waitTime;
private long lastCheck;
public EventDelay(long ticks)
/// <summary>
/// Resets this hotkey control to None.
/// </summary>
public new void Clear()
{
waitTime = ticks;
Hotkey = Keys.None;
HotkeyModifiers = Keys.None;
}
public bool Check()
/// <summary>
/// Clears the current hotkey and resets the TextBox.
/// </summary>
public void ResetHotkey()
{
#pragma warning disable CA2002
lock (this)
#pragma warning restore CA2002
hotkey = Keys.None;
modifiers = Keys.None;
Redraw();
}
/// <summary>
/// Used to get/set the hotkey (e.g. Keys.A).
/// </summary>
/// <param name="hotkey">hotkey.</param>
public void SetHotkey(string hotkey)
{
this.hotkey = HotkeyFromString(hotkey);
modifiers = HotkeyModifiersFromString(hotkey);
Redraw(true);
}
public override string ToString()
{
return HotkeyToString(HotkeyModifiers, Hotkey);
}
/// <summary>
/// Handles some misc keys, such as Ctrl+Delete and Shift+Insert.
/// </summary>
/// <param name="msg">msg.</param>
/// <param name="keyData">keyData.</param>
/// <returns>bool if handled.</returns>
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Delete || keyData == (Keys.Control | Keys.Delete))
{
long now = DateTime.Now.Ticks;
bool isPassed = now - lastCheck > waitTime;
lastCheck = now;
return isPassed;
ResetHotkey();
return true;
}
// Paste
if (keyData == (Keys.Shift | Keys.Insert))
{
return true; // Don't allow
}
// Allow the rest
return base.ProcessCmdKey(ref msg, keyData);
}
/// <summary>
/// Redraws the TextBox when necessary.
/// </summary>
/// <param name="bCalledProgramatically">Specifies whether this function was called by the Hotkey/HotkeyModifiers properties or by the user.</param>
private void Redraw(bool bCalledProgramatically = false)
{
// No hotkey set
if (hotkey == Keys.None)
{
Text = string.Empty;
return;
}
// LWin/RWin doesn't work as hotkeys (neither do they work as modifier keys in .NET 2.0)
if (hotkey == Keys.LWin || hotkey == Keys.RWin)
{
Text = string.Empty;
return;
}
// Only validate input if it comes from the user
if (bCalledProgramatically == false)
{
// No modifier or shift only, AND a hotkey that needs another modifier
if ((modifiers == Keys.Shift || modifiers == Keys.None) && needNonShiftModifier.Contains((int)hotkey))
{
if (modifiers == Keys.None)
{
// Set Ctrl+Alt as the modifier unless Ctrl+Alt+<key> won't work...
if (needNonAltGrModifier.Contains((int)hotkey) == false)
{
modifiers = Keys.Alt | Keys.Control;
}
else
{
// ... in that case, use Shift+Alt instead.
modifiers = Keys.Alt | Keys.Shift;
}
}
else
{
// User pressed Shift and an invalid key (e.g. a letter or a number),
// that needs another set of modifier keys
hotkey = Keys.None;
Text = string.Empty;
return;
}
}
// Check all Ctrl+Alt keys
if ((modifiers == (Keys.Alt | Keys.Control)) && needNonAltGrModifier.Contains((int)hotkey))
{
// Ctrl+Alt+4 etc won't work; reset hotkey and tell the user
hotkey = Keys.None;
Text = string.Empty;
return;
}
}
// I have no idea why this is needed, but it is. Without this code, pressing only Ctrl
// will show up as "Control + ControlKey", etc.
if (hotkey == Keys.Menu /* Alt */ || hotkey == Keys.ShiftKey || hotkey == Keys.ControlKey)
{
hotkey = Keys.None;
}
Text = HotkeyToLocalizedString(modifiers, hotkey);
}
/// <summary>
/// Populates the ArrayLists specifying disallowed hotkeys
/// such as Shift+A, Ctrl+Alt+4 (would produce a dollar sign) etc.
/// </summary>
private void PopulateModifierLists()
{
// Shift + 0 - 9, A - Z
for (Keys k = Keys.D0; k <= Keys.Z; k++)
{
needNonShiftModifier.Add((int)k);
}
// Shift + Numpad keys
for (Keys k = Keys.NumPad0; k <= Keys.NumPad9; k++)
{
needNonShiftModifier.Add((int)k);
}
// Shift + Misc (,;<./ etc)
for (Keys k = Keys.Oem1; k <= Keys.OemBackslash; k++)
{
needNonShiftModifier.Add((int)k);
}
// Shift + Space, PgUp, PgDn, End, Home
for (Keys k = Keys.Space; k <= Keys.Home; k++)
{
needNonShiftModifier.Add((int)k);
}
// Misc keys that we can't loop through
needNonShiftModifier.Add((int)Keys.Insert);
needNonShiftModifier.Add((int)Keys.Help);
needNonShiftModifier.Add((int)Keys.Multiply);
needNonShiftModifier.Add((int)Keys.Add);
needNonShiftModifier.Add((int)Keys.Subtract);
needNonShiftModifier.Add((int)Keys.Divide);
needNonShiftModifier.Add((int)Keys.Decimal);
needNonShiftModifier.Add((int)Keys.Return);
needNonShiftModifier.Add((int)Keys.Escape);
needNonShiftModifier.Add((int)Keys.NumLock);
// Ctrl+Alt + 0 - 9
for (Keys k = Keys.D0; k <= Keys.D9; k++)
{
needNonAltGrModifier.Add((int)k);
}
}
/// <summary>
/// Fires when a key is pushed down. Here, we'll want to update the text in the box
/// to notify the user what combination is currently pressed.
/// </summary>
private void HotkeyControl_KeyDown(object sender, KeyEventArgs e)
{
// Clear the current hotkey
if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete)
{
ResetHotkey();
}
else
{
modifiers = e.Modifiers;
hotkey = e.KeyCode;
Redraw();
}
}
/// <summary>
/// Fires when all keys are released. If the current hotkey isn't valid, reset it.
/// Otherwise, do nothing and keep the text and hotkey as it was.
/// </summary>
private void HotkeyControl_KeyUp(object sender, KeyEventArgs e)
{
// Somehow the PrintScreen only comes as a keyup, therefore we handle it here.
if (e.KeyCode == Keys.PrintScreen)
{
modifiers = e.Modifiers;
hotkey = e.KeyCode;
Redraw();
}
if (hotkey == Keys.None && ModifierKeys == Keys.None)
{
ResetHotkey();
}
}
/// <summary>
/// Prevents the letter/whatever entered to show up in the TextBox
/// Without this, a "A" key press would appear as "aControl, Alt + A".
/// </summary>
private void HotkeyControl_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = true;
}
}
}

13
UserInterface/Language.cs Normal file
View file

@ -0,0 +1,13 @@
// <copyright file="Language.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.UserInterface
{
public class Language
{
public string Name { get; set; }
public string Value { get; set; }
}
}

View file

@ -17,7 +17,6 @@ namespace SystemTrayMenu.UserInterface
internal partial class Menu : Form
{
internal int Level = 0;
private readonly Fading fading = new Fading();
private bool isShowing = false;
@ -131,25 +130,26 @@ namespace SystemTrayMenu.UserInterface
MaxReached,
}
internal int Level { get; set; } = 0;
internal bool IsUsable => Visible && !fading.IsHiding &&
!IsDisposed && !Disposing;
protected override CreateParams CreateParams
{
get
{
CreateParams createparams = base.CreateParams;
createparams.ExStyle |= 0x80;
return createparams;
}
}
internal void FocusTextBox()
{
textBoxSearch.Focus();
}
private static void SetDoubleBuffer(Control ctl, bool doubleBuffered)
{
typeof(Control).InvokeMember(
"DoubleBuffered",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
null,
ctl,
new object[] { doubleBuffered },
CultureInfo.InvariantCulture);
}
internal void SetTypeSub()
{
SetType(MenuType.Sub);
@ -378,6 +378,53 @@ namespace SystemTrayMenu.UserInterface
Location = new Point(x, y);
}
internal void SetTitleColorActive()
{
labelTitle.ForeColor = Color.Black;
}
internal void KeyPressedSearch(string letter)
{
textBoxSearch.Text += letter;
textBoxSearch.SelectionStart = textBoxSearch.Text.Length;
textBoxSearch.SelectionLength = 0;
textBoxSearch.Focus();
}
protected override bool ProcessCmdKey(ref Message msg, Keys keys)
{
switch (keys)
{
case Keys.Enter:
case Keys.Up:
case Keys.Down:
case Keys.Left:
case Keys.Right:
case Keys.Escape:
case Keys.Control | Keys.F:
case Keys.Tab:
case Keys.Tab | Keys.Shift:
case Keys.Apps:
CmdKeyProcessed.Invoke(this, keys);
return true;
default:
break;
}
return base.ProcessCmdKey(ref msg, keys);
}
private static void SetDoubleBuffer(Control ctl, bool doubleBuffered)
{
typeof(Control).InvokeMember(
"DoubleBuffered",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
null,
ctl,
new object[] { doubleBuffered },
CultureInfo.InvariantCulture);
}
private void AdjustDataGridViewWidth()
{
DataGridViewExtensions.FastAutoSizeColumns(dgv);
@ -456,11 +503,6 @@ namespace SystemTrayMenu.UserInterface
MouseWheel?.Invoke();
}
internal void SetTitleColorActive()
{
labelTitle.ForeColor = Color.Black;
}
private void LabelTitle_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
@ -479,39 +521,6 @@ namespace SystemTrayMenu.UserInterface
labelTitle.BackColor = MenuDefines.ColorTitleBackground;
}
protected override CreateParams CreateParams
{
get
{
CreateParams createparams = base.CreateParams;
createparams.ExStyle |= 0x80;
return createparams;
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keys)
{
switch (keys)
{
case Keys.Enter:
case Keys.Up:
case Keys.Down:
case Keys.Left:
case Keys.Right:
case Keys.Escape:
case Keys.Control | Keys.F:
case Keys.Tab:
case Keys.Tab | Keys.Shift:
case Keys.Apps:
CmdKeyProcessed.Invoke(this, keys);
return true;
default:
break;
}
return base.ProcessCmdKey(ref msg, keys);
}
private void TextBoxSearch_TextChanged(object sender, EventArgs e)
{
DataTable data = (DataTable)dgv.DataSource;
@ -531,13 +540,5 @@ namespace SystemTrayMenu.UserInterface
SearchTextChanged.Invoke(this, null);
}
internal void KeyPressedSearch(string letter)
{
textBoxSearch.Text += letter;
textBoxSearch.SelectionStart = textBoxSearch.Text.Length;
textBoxSearch.SelectionLength = 0;
textBoxSearch.Focus();
}
}
}

View file

@ -1,4 +1,4 @@
using SystemTrayMenu.UserInterface.Controls;
using SystemTrayMenu.UserInterface.HotkeyTextboxControl;
namespace SystemTrayMenu.UserInterface
{
@ -37,7 +37,7 @@ namespace SystemTrayMenu.UserInterface
this.tableLayoutPanelGeneral = new System.Windows.Forms.TableLayoutPanel();
this.comboBoxLanguage = new System.Windows.Forms.ComboBox();
this.labelLanguage = new System.Windows.Forms.Label();
this.textBoxHotkey = new SystemTrayMenu.UserInterface.Controls.HotkeyControl();
this.textBoxHotkey = new SystemTrayMenu.UserInterface.HotkeyTextboxControl.HotkeyControl();
this.checkBoxAutostart = new System.Windows.Forms.CheckBox();
this.labelHotkey = new System.Windows.Forms.Label();
this.labelAutostart = new System.Windows.Forms.Label();

View file

@ -4,21 +4,19 @@
namespace SystemTrayMenu.UserInterface
{
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using SystemTrayMenu.UserInterface.Controls;
using Microsoft.Win32;
using SystemTrayMenu.UserInterface.HotkeyTextboxControl;
using SystemTrayMenu.Utilities;
using static SystemTrayMenu.UserInterface.Controls.HotkeyControl;
using static SystemTrayMenu.UserInterface.HotkeyTextboxControl.HotkeyControl;
public partial class SettingsForm : Form
{
public string NewHotKey => newHotKey;
private readonly string newHotKey = string.Empty;
private bool inHotkey = false;
@ -79,82 +77,15 @@ namespace SystemTrayMenu.UserInterface
}
}
private void SettingsForm_Load(object sender, EventArgs e)
{
tabControl1.Size = new Size(
tableLayoutPanelGeneral.Size.Width,
tableLayoutPanelGeneral.Size.Height);
}
public string NewHotKey => newHotKey;
private void ButtonOk_Click(object sender, EventArgs e)
/// <summary>
/// Registers all hotkeys as configured, displaying a dialog in case of hotkey conflicts with other tools.
/// </summary>
/// <returns>Whether the hotkeys could be registered to the users content. This also applies if conflicts arise and the user decides to ignore these (i.e. not to register the conflicting hotkey).</returns>
public static bool RegisterHotkeys()
{
SetAutostart();
SetHotkey();
SetLanguage();
Properties.Settings.Default.Save();
DialogResult = DialogResult.OK;
Close();
}
private void SetAutostart()
{
if (checkBoxAutostart.Checked)
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
key.SetValue(
Assembly.GetExecutingAssembly().GetName().Name,
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
Properties.Settings.Default.IsAutostartActivated = true;
}
else
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
key.DeleteValue("SystemTrayMenu", false);
Properties.Settings.Default.IsAutostartActivated = false;
}
}
private void SetHotkey()
{
Properties.Settings.Default.HotKey =
new KeysConverter().ConvertToInvariantString(
textBoxHotkey.Hotkey | textBoxHotkey.HotkeyModifiers);
}
private void SetLanguage()
{
Properties.Settings.Default.CurrentCultureInfoName =
comboBoxLanguage.SelectedValue.ToString();
}
private void ButtonCancel_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Reload();
DialogResult = DialogResult.Cancel;
Close();
}
private void ButtonChange_Click(object sender, EventArgs e)
{
Config.SetFolderByUser(false);
textBoxFolder.Text = Config.Path;
}
private void TextBoxHotkeyEnter(object sender, EventArgs e)
{
HotkeyControl.UnregisterHotkeys();
inHotkey = true;
}
private void TextBoxHotkey_Leave(object sender, EventArgs e)
{
Properties.Settings.Default.HotKey =
new KeysConverter().ConvertToInvariantString(
textBoxHotkey.Hotkey | textBoxHotkey.HotkeyModifiers);
RegisterHotkeys();
inHotkey = false;
return RegisterHotkeys(false);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
@ -216,15 +147,6 @@ namespace SystemTrayMenu.UserInterface
return success;
}
/// <summary>
/// Registers all hotkeys as configured, displaying a dialog in case of hotkey conflicts with other tools.
/// </summary>
/// <returns>Whether the hotkeys could be registered to the users content. This also applies if conflicts arise and the user decides to ignore these (i.e. not to register the conflicting hotkey).</returns>
public static bool RegisterHotkeys()
{
return RegisterHotkeys(false);
}
/// <summary>
/// Registers all hotkeys as configured, displaying a dialog in case of hotkey conflicts with other tools.
/// </summary>
@ -312,12 +234,83 @@ namespace SystemTrayMenu.UserInterface
return success;
}
}
public class Language
{
public string Name { get; set; }
private void SettingsForm_Load(object sender, EventArgs e)
{
tabControl1.Size = new Size(
tableLayoutPanelGeneral.Size.Width,
tableLayoutPanelGeneral.Size.Height);
}
public string Value { get; set; }
private void ButtonOk_Click(object sender, EventArgs e)
{
SetAutostart();
SetHotkey();
SetLanguage();
Properties.Settings.Default.Save();
DialogResult = DialogResult.OK;
Close();
}
private void SetAutostart()
{
if (checkBoxAutostart.Checked)
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
key.SetValue(
Assembly.GetExecutingAssembly().GetName().Name,
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
Properties.Settings.Default.IsAutostartActivated = true;
}
else
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
key.DeleteValue("SystemTrayMenu", false);
Properties.Settings.Default.IsAutostartActivated = false;
}
}
private void SetHotkey()
{
Properties.Settings.Default.HotKey =
new KeysConverter().ConvertToInvariantString(
textBoxHotkey.Hotkey | textBoxHotkey.HotkeyModifiers);
}
private void SetLanguage()
{
Properties.Settings.Default.CurrentCultureInfoName =
comboBoxLanguage.SelectedValue.ToString();
}
private void ButtonCancel_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Reload();
DialogResult = DialogResult.Cancel;
Close();
}
private void ButtonChange_Click(object sender, EventArgs e)
{
Config.SetFolderByUser(false);
textBoxFolder.Text = Config.Path;
}
private void TextBoxHotkeyEnter(object sender, EventArgs e)
{
HotkeyControl.UnregisterHotkeys();
inHotkey = true;
}
private void TextBoxHotkey_Leave(object sender, EventArgs e)
{
Properties.Settings.Default.HotKey =
new KeysConverter().ConvertToInvariantString(
textBoxHotkey.Hotkey | textBoxHotkey.HotkeyModifiers);
RegisterHotkeys();
inHotkey = false;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -13,6 +13,26 @@ namespace SystemTrayMenu.Utilities
{
public static event EventHandlerEmpty BeforeRestarting;
internal static void ByThreadException()
{
Restart(GetCurrentMethod());
}
internal static void ByMenuNotifyIcon()
{
Restart(GetCurrentMethod());
}
internal static void ByDisplaySettings(object sender, EventArgs e)
{
Restart(GetCurrentMethod());
}
internal static void ByConfigChange()
{
Restart(GetCurrentMethod());
}
private static void Restart(string reason)
{
BeforeRestarting?.Invoke();
@ -38,25 +58,5 @@ namespace SystemTrayMenu.Utilities
return sf.GetMethod().Name;
}
internal static void ByThreadException()
{
Restart(GetCurrentMethod());
}
internal static void ByMenuNotifyIcon()
{
Restart(GetCurrentMethod());
}
internal static void ByDisplaySettings(object sender, EventArgs e)
{
Restart(GetCurrentMethod());
}
internal static void ByConfigChange()
{
Restart(GetCurrentMethod());
}
}
}

View file

@ -4,10 +4,10 @@
namespace SystemTrayMenu.Utilities
{
using Shell32;
using System;
using System.IO;
using System.Threading;
using Shell32;
internal class FileLnk
{
@ -34,6 +34,28 @@ namespace SystemTrayMenu.Utilities
return resolvedFilename;
}
public static bool IsDirectory(string filePath)
{
bool isDirectory = false;
if (Directory.Exists(filePath))
{
FileAttributes attributes = File.GetAttributes(filePath);
if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
{
isDirectory = true;
}
}
return isDirectory;
}
public static bool IsNetworkRoot(string path)
{
return !System.IO.File.Exists(path) &&
path.StartsWith(@"\\", StringComparison.InvariantCulture) &&
!path.Substring(2).Contains(@"\", StringComparison.InvariantCulture);
}
private static string GetShortcutFileNamePath(object shortcutFilename)
{
string resolvedFilename = string.Empty;
@ -65,27 +87,5 @@ namespace SystemTrayMenu.Utilities
return resolvedFilename;
}
public static bool IsDirectory(string filePath)
{
bool isDirectory = false;
if (Directory.Exists(filePath))
{
FileAttributes attributes = File.GetAttributes(filePath);
if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
{
isDirectory = true;
}
}
return isDirectory;
}
public static bool IsNetworkRoot(string path)
{
return !System.IO.File.Exists(path) &&
path.StartsWith(@"\\", StringComparison.InvariantCulture) &&
!path.Substring(2).Contains(@"\", StringComparison.InvariantCulture);
}
}
}

View file

@ -69,83 +69,6 @@ namespace SystemTrayMenu.Utilities
return icon;
}
private static bool IsExtensionWitSameIcon(string fileExtension)
{
bool isExtensionWitSameIcon = true;
List<string> extensionsWithDiffIcons = new List<string>
{ string.Empty, ".EXE", ".LNK", ".ICO", ".URL" };
if (extensionsWithDiffIcons.Contains(fileExtension.ToUpperInvariant()))
{
isExtensionWitSameIcon = false;
}
return isExtensionWitSameIcon;
}
private static Icon GetFileIcon(string filePath, bool linkOverlay, IconSize size = IconSize.Small)
{
Icon icon = null;
DllImports.NativeMethods.SHFILEINFO shfi = default;
uint flags = DllImports.NativeMethods.ShgfiIcon | DllImports.NativeMethods.ShgfiSYSICONINDEX;
if (linkOverlay)
{
flags += DllImports.NativeMethods.ShgfiLINKOVERLAY;
}
/* Check the size specified for return. */
if (size == IconSize.Small)
{
flags += DllImports.NativeMethods.ShgfiSMALLICON;
}
else
{
flags += DllImports.NativeMethods.ShgfiLARGEICON;
}
IntPtr hImageList = DllImports.NativeMethods.Shell32SHGetFileInfo(
filePath,
DllImports.NativeMethods.FileAttributeNormal,
ref shfi,
(uint)Marshal.SizeOf(shfi),
flags);
if (hImageList != IntPtr.Zero)
{
IntPtr hIcon;
if (linkOverlay)
{
hIcon = shfi.hIcon; // Get icon directly
}
else
{
// Get icon from .ink without overlay
hIcon = DllImports.NativeMethods.ImageList_GetIcon(hImageList, shfi.iIcon, DllImports.NativeMethods.IldTransparent);
}
try
{
// Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly
icon = (Icon)Icon.FromHandle(hIcon).Clone();
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
Log.Error($"filePath:'{filePath}'", ex);
}
// Cleanup
if (!linkOverlay)
{
DllImports.NativeMethods.User32DestroyIcon(hIcon);
}
DllImports.NativeMethods.User32DestroyIcon(shfi.hIcon);
}
return icon;
}
public static Icon GetFolderIcon(
string directoryPath,
FolderType folderType,
@ -224,5 +147,82 @@ namespace SystemTrayMenu.Utilities
return icon;
}
private static bool IsExtensionWitSameIcon(string fileExtension)
{
bool isExtensionWitSameIcon = true;
List<string> extensionsWithDiffIcons = new List<string>
{ string.Empty, ".EXE", ".LNK", ".ICO", ".URL" };
if (extensionsWithDiffIcons.Contains(fileExtension.ToUpperInvariant()))
{
isExtensionWitSameIcon = false;
}
return isExtensionWitSameIcon;
}
private static Icon GetFileIcon(string filePath, bool linkOverlay, IconSize size = IconSize.Small)
{
Icon icon = null;
DllImports.NativeMethods.SHFILEINFO shfi = default;
uint flags = DllImports.NativeMethods.ShgfiIcon | DllImports.NativeMethods.ShgfiSYSICONINDEX;
if (linkOverlay)
{
flags += DllImports.NativeMethods.ShgfiLINKOVERLAY;
}
/* Check the size specified for return. */
if (size == IconSize.Small)
{
flags += DllImports.NativeMethods.ShgfiSMALLICON;
}
else
{
flags += DllImports.NativeMethods.ShgfiLARGEICON;
}
IntPtr hImageList = DllImports.NativeMethods.Shell32SHGetFileInfo(
filePath,
DllImports.NativeMethods.FileAttributeNormal,
ref shfi,
(uint)Marshal.SizeOf(shfi),
flags);
if (hImageList != IntPtr.Zero)
{
IntPtr hIcon;
if (linkOverlay)
{
hIcon = shfi.hIcon; // Get icon directly
}
else
{
// Get icon from .ink without overlay
hIcon = DllImports.NativeMethods.ImageList_GetIcon(hImageList, shfi.iIcon, DllImports.NativeMethods.IldTransparent);
}
try
{
// Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly
icon = (Icon)Icon.FromHandle(hIcon).Clone();
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
Log.Error($"filePath:'{filePath}'", ex);
}
// Cleanup
if (!linkOverlay)
{
DllImports.NativeMethods.User32DestroyIcon(hIcon);
}
DllImports.NativeMethods.User32DestroyIcon(shfi.hIcon);
}
return icon;
}
}
}

View file

@ -4,11 +4,11 @@
namespace SystemTrayMenu.Utilities
{
using Shell32;
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Shell32;
internal static class FolderOptions
{

13
Utilities/Language.cs Normal file
View file

@ -0,0 +1,13 @@
// <copyright file="Language.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Utilities
{
internal class Language
{
public string Name { get; set; }
public string Value { get; set; }
}
}

View file

@ -4,13 +4,13 @@
namespace SystemTrayMenu.Utilities
{
using Clearcove.Logging;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using Clearcove.Logging;
internal static class Log
{

View file

@ -9,14 +9,14 @@ namespace SystemTrayMenu.Utilities
internal static class Scaling
{
internal static float Factor = 1;
private enum DeviceCap
{
VERTRES = 10,
DESKTOPVERTRES = 117,
}
public static float Factor { get; private set; } = 1;
internal static void Initialize()
{
CalculateScalingFactor();

View file

@ -34,11 +34,4 @@ namespace SystemTrayMenu.Utilities
return rm.GetString(id, culture);
}
}
public class Language
{
public string Name { get; set; }
public string Value { get; set; }
}
}