mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-01 18:35:13 +00:00
Refactor tray icon to use TrayIconHost
This commit is contained in:
@@ -213,9 +213,6 @@ public partial class App : Application
|
||||
// Initialize MessageBox patching
|
||||
bool modernMessageBox = SettingHelper.Get("ModernMessageBox", true, "QuickLook");
|
||||
if (modernMessageBox) MessageBoxPatcher.Initialize();
|
||||
// Initialize TrayIcon patching
|
||||
bool modernTrayIcon = SettingHelper.Get("ModernTrayIcon", true, "QuickLook");
|
||||
if (modernTrayIcon) TrayIconPatcher.Initialize();
|
||||
|
||||
// Set initial theme based on system settings
|
||||
ThemeManager.Apply(OSThemeHelper.AppsUseDarkTheme() ? ApplicationTheme.Dark : ApplicationTheme.Light);
|
||||
@@ -223,6 +220,9 @@ public partial class App : Application
|
||||
ThemeManager.Apply(OSThemeHelper.AppsUseDarkTheme() ? ApplicationTheme.Dark : ApplicationTheme.Light);
|
||||
UxTheme.ApplyPreferredAppMode();
|
||||
|
||||
// Initialize TrayIcon
|
||||
_ = TrayIconManager.GetInstance();
|
||||
|
||||
base.OnStartup(e);
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ public partial class App : Application
|
||||
CheckUpdate();
|
||||
RunListener(e);
|
||||
|
||||
// first instance: run and preview this file
|
||||
// First instance: run and preview this file
|
||||
if (e.Args.Any() && (Directory.Exists(e.Args.First()) || File.Exists(e.Args.First())))
|
||||
PipeServerManager.SendMessage(PipeMessages.Toggle, e.Args.First());
|
||||
}
|
||||
@@ -318,12 +318,12 @@ public partial class App : Application
|
||||
if (isFirst)
|
||||
return true;
|
||||
|
||||
// second instance: preview this file
|
||||
// Second instance: preview this file
|
||||
if (args.Any() && (Directory.Exists(args.First()) || File.Exists(args.First())))
|
||||
{
|
||||
PipeServerManager.SendMessage(PipeMessages.Toggle, args.First(), [.. args.Skip(1)]);
|
||||
}
|
||||
// second instance: duplicate
|
||||
// Second instance: duplicate
|
||||
else
|
||||
MessageBox.Show(TranslationHelper.Get("APP_SECOND_TEXT"), TranslationHelper.Get("APP_SECOND"),
|
||||
MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
|
@@ -1,298 +0,0 @@
|
||||
// Copyright © 2017-2025 QL-Win Contributors
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using HarmonyLib;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace QuickLook.Helpers;
|
||||
|
||||
public static class TrayIconPatcher
|
||||
{
|
||||
private static readonly Harmony Harmony = new("com.quicklook.trayicon.patch");
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
var targetMethod = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
if (targetMethod != null)
|
||||
{
|
||||
_ = Harmony.Patch(targetMethod, transpiler: new HarmonyMethod(typeof(TrayIconPatcher).GetMethod(nameof(ShowContextMenuTranspiler))));
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShowContextMenu(this NotifyIcon icon)
|
||||
{
|
||||
var targetMethod = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
targetMethod?.Invoke(icon, []);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We need to change the NotifyIcon.ShowContextMenu to use TPM_RIGHTBUTTON instead of TPM_VERTICAL.
|
||||
/// private void ShowContextMenu()
|
||||
/// {
|
||||
/// if (contextMenu != null || contextMenuStrip != null)
|
||||
/// {
|
||||
/// NativeMethods.POINT pOINT = new NativeMethods.POINT();
|
||||
/// UnsafeNativeMethods.GetCursorPos(pOINT);
|
||||
/// UnsafeNativeMethods.SetForegroundWindow(new HandleRef(window, window.Handle));
|
||||
/// if (contextMenu != null)
|
||||
/// {
|
||||
/// contextMenu.OnPopup(EventArgs.Empty);
|
||||
/// SafeNativeMethods.TrackPopupMenuEx(new HandleRef(contextMenu, contextMenu.Handle), 72, pOINT.x, pOINT.y, new HandleRef(window, window.Handle), null);
|
||||
/// UnsafeNativeMethods.PostMessage(new HandleRef(window, window.Handle), 0, IntPtr.Zero, IntPtr.Zero);
|
||||
/// }
|
||||
/// else if (contextMenuStrip != null)
|
||||
/// {
|
||||
/// contextMenuStrip.ShowInTaskbar(pOINT.x, pOINT.y);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ---
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: System.Windows.Forms.ContextMenu contextMenu
|
||||
/// Opcode: brtrue.s, Operand: System.Reflection.Emit.Label
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: System.Windows.Forms.ContextMenuStrip contextMenuStrip
|
||||
/// Opcode: brfalse, Operand: System.Reflection.Emit.Label
|
||||
/// Opcode: newobj, Operand: Void.ctor()
|
||||
/// Opcode: stloc.0, Operand:
|
||||
/// Opcode: ldloc.0, Operand:
|
||||
/// Opcode: call, Operand: Boolean GetCursorPos(POINT)
|
||||
/// Opcode: pop, Operand:
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: NotifyIconNativeWindow window
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: NotifyIconNativeWindow window
|
||||
/// Opcode: callvirt, Operand: IntPtr get_Handle()
|
||||
/// Opcode: newobj, Operand: Void.ctor(System.Object, IntPtr)
|
||||
/// Opcode: call, Operand: Boolean SetForegroundWindow(System.Runtime.InteropServices.HandleRef)
|
||||
/// Opcode: pop, Operand:
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: System.Windows.Forms.ContextMenu contextMenu
|
||||
/// Opcode: brfalse.s, Operand: System.Reflection.Emit.Label
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: System.Windows.Forms.ContextMenu contextMenu
|
||||
/// Opcode: ldsfld, Operand: System.EventArgs Empty
|
||||
/// Opcode: callvirt, Operand: Void OnPopup(System.EventArgs)
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: System.Windows.Forms.ContextMenu contextMenu
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: System.Windows.Forms.ContextMenu contextMenu
|
||||
/// Opcode: callvirt, Operand: IntPtr get_Handle()
|
||||
/// Opcode: newobj, Operand: Void.ctor(System.Object, IntPtr)
|
||||
/// Opcode: ldc.i4.s, Operand: 72
|
||||
/// Opcode: ldloc.0, Operand:
|
||||
/// Opcode: ldfld, Operand: Int32 x
|
||||
/// Opcode: ldloc.0, Operand:
|
||||
/// Opcode: ldfld, Operand: Int32 y
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: NotifyIconNativeWindow window
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: NotifyIconNativeWindow window
|
||||
/// Opcode: callvirt, Operand: IntPtr get_Handle()
|
||||
/// Opcode: newobj, Operand: Void.ctor(System.Object, IntPtr)
|
||||
/// Opcode: ldnull, Operand:
|
||||
/// Opcode: call, Operand: Boolean TrackPopupMenuEx(System.Runtime.InteropServices.HandleRef, Int32, Int32, Int32, System.Runtime.InteropServices.HandleRef, TPMPARAMS)
|
||||
/// Opcode: pop, Operand:
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: NotifyIconNativeWindow window
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: NotifyIconNativeWindow window
|
||||
/// Opcode: callvirt, Operand: IntPtr get_Handle()
|
||||
/// Opcode: newobj, Operand: Void.ctor(System.Object, IntPtr)
|
||||
/// Opcode: ldc.i4.0, Operand:
|
||||
/// Opcode: ldsfld, Operand: IntPtr Zero
|
||||
/// Opcode: ldsfld, Operand: IntPtr Zero
|
||||
/// Opcode: call, Operand: Boolean PostMessage(System.Runtime.InteropServices.HandleRef, Int32, IntPtr, IntPtr)
|
||||
/// Opcode: pop, Operand:
|
||||
/// Opcode: ret, Operand:
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: System.Windows.Forms.ContextMenuStrip contextMenuStrip
|
||||
/// Opcode: brfalse.s, Operand: System.Reflection.Emit.Label
|
||||
/// Opcode: ldarg.0, Operand:
|
||||
/// Opcode: ldfld, Operand: System.Windows.Forms.ContextMenuStrip contextMenuStrip
|
||||
/// Opcode: ldloc.0, Operand:
|
||||
/// Opcode: ldfld, Operand: Int32 x
|
||||
/// Opcode: ldloc.0, Operand:
|
||||
/// Opcode: ldfld, Operand: Int32 y
|
||||
/// Opcode: callvirt, Operand: Void ShowInTaskbar(Int32, Int32)
|
||||
/// Opcode: ret, Operand:
|
||||
/// </summary>
|
||||
/// <param name="instructions"></param>
|
||||
/// <returns></returns>
|
||||
[HarmonyTranspiler]
|
||||
public static IEnumerable<CodeInstruction> ShowContextMenuTranspiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
try
|
||||
{
|
||||
var codes = instructions.ToArray();
|
||||
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
// Test code to print the IL codes
|
||||
foreach (var code in codes)
|
||||
{
|
||||
Debug.WriteLine($"Opcode: {code.opcode}, Operand: {code.operand}");
|
||||
}
|
||||
}
|
||||
|
||||
// How to change source code for proxy:
|
||||
// from SafeNativeMethods.TrackPopupMenuEx(new HandleRef(contextMenu, contextMenu.Handle), 72, pOINT.x, pOINT.y, new HandleRef(window, window.Handle), null);
|
||||
// to SafeNativeMethods.TrackPopupMenuEx(new HandleRef(contextMenu, contextMenu.Handle), 66, pOINT.x, pOINT.y, new HandleRef(window, window.Handle), null);
|
||||
// [TrackPopupMenuEx] uFlags: A set of flags that determine how the menu behaves.
|
||||
// The number 72 in binary is 0100 1000. Breaking it down:
|
||||
// * TPM_VERTICAL(0x0040)
|
||||
// * TPM_RIGHTALIGN(0x0008)
|
||||
// The number 64 in binary is 0100 0000. Breaking it down:
|
||||
// * TPM_VERTICAL(0x0040)
|
||||
// * TPM_LEFTALIGN(0x0000)
|
||||
const sbyte sourceFlag = (sbyte)(TrackPopupMenuFlags.TPM_VERTICAL | TrackPopupMenuFlags.TPM_RIGHTALIGN);
|
||||
const sbyte targetFlag = (sbyte)(TrackPopupMenuFlags.TPM_VERTICAL | TrackPopupMenuFlags.TPM_LEFTALIGN);
|
||||
|
||||
for (int i = 0; i < codes.Length; i++)
|
||||
{
|
||||
if (codes[i].opcode == OpCodes.Ldc_I4_S && (sbyte)codes[i].operand == sourceFlag)
|
||||
{
|
||||
codes[i].operand = targetFlag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return codes;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// No fallback needed in this case
|
||||
}
|
||||
|
||||
return instructions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-trackpopupmenuex
|
||||
/// </summary>
|
||||
[Flags]
|
||||
private enum TrackPopupMenuFlags : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// The user can select menu items with only the left mouse button.
|
||||
/// </summary>
|
||||
TPM_LEFTBUTTON = 0x0000,
|
||||
|
||||
/// <summary>
|
||||
/// The user can select menu items with both the left and right mouse buttons.
|
||||
/// </summary>
|
||||
TPM_RIGHTBUTTON = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// Positions the shortcut menu so that its left side is aligned with the coordinate specified by the x parameter.
|
||||
/// </summary>
|
||||
TPM_LEFTALIGN = 0x0000,
|
||||
|
||||
/// <summary>
|
||||
/// Centers the shortcut menu horizontally relative to the coordinate specified by the x parameter.
|
||||
/// </summary>
|
||||
TPM_CENTERALIGN = 0x0004,
|
||||
|
||||
/// <summary>
|
||||
/// Positions the shortcut menu so that its right side is aligned with the coordinate specified by the x parameter.
|
||||
/// </summary>
|
||||
TPM_RIGHTALIGN = 0x0008,
|
||||
|
||||
/// <summary>
|
||||
/// Positions the shortcut menu so that its top side is aligned with the coordinate specified by the y parameter.
|
||||
/// </summary>
|
||||
TPM_TOPALIGN = 0x0000,
|
||||
|
||||
/// <summary>
|
||||
/// Centers the shortcut menu vertically relative to the coordinate specified by the y parameter.
|
||||
/// </summary>
|
||||
TPM_VCENTERALIGN = 0x0010,
|
||||
|
||||
/// <summary>
|
||||
/// Positions the shortcut menu so that its bottom side is aligned with the coordinate specified by the y parameter.
|
||||
/// </summary>
|
||||
TPM_BOTTOMALIGN = 0x0020,
|
||||
|
||||
/// <summary>
|
||||
/// TPM_HORIZONTAL
|
||||
/// </summary>
|
||||
TPM_HORIZONTAL = 0x0000,
|
||||
|
||||
/// <summary>
|
||||
/// TPM_VERTICAL
|
||||
/// </summary>
|
||||
TPM_VERTICAL = 0x0040,
|
||||
|
||||
/// <summary>
|
||||
/// The function does not send notification messages when the user clicks a menu item.
|
||||
/// </summary>
|
||||
TPM_NONOTIFY = 0x0080,
|
||||
|
||||
/// <summary>
|
||||
/// The function returns the menu item identifier of the user's selection in the return value.
|
||||
/// </summary>
|
||||
TPM_RETURNCMD = 0x0100,
|
||||
|
||||
/// <summary>
|
||||
/// TPM_RECURSE
|
||||
/// </summary>
|
||||
TPM_RECURSE = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// Animates the menu from left to right.
|
||||
/// </summary>
|
||||
TPM_HORPOSANIMATION = 0x0400,
|
||||
|
||||
/// <summary>
|
||||
/// Animates the menu from right to left.
|
||||
/// </summary>
|
||||
TPM_HORNEGANIMATION = 0x0800,
|
||||
|
||||
/// <summary>
|
||||
/// Animates the menu from top to bottom.
|
||||
/// </summary>
|
||||
TPM_VERPOSANIMATION = 0x1000,
|
||||
|
||||
/// <summary>
|
||||
/// Animates the menu from bottom to top.
|
||||
/// </summary>
|
||||
TPM_VERNEGANIMATION = 0x2000,
|
||||
|
||||
/// <summary>
|
||||
/// Displays menu without animation.
|
||||
/// </summary>
|
||||
TPM_NOANIMATION = 0x4000,
|
||||
|
||||
/// <summary>
|
||||
/// TPM_LAYOUTRTL
|
||||
/// </summary>
|
||||
TPM_LAYOUTRTL = 0x8000,
|
||||
|
||||
/// <summary>
|
||||
/// TPM_WORKAREA
|
||||
/// </summary>
|
||||
TPM_WORKAREA = 0x10000,
|
||||
}
|
||||
}
|
@@ -102,7 +102,7 @@
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="WPF-UI.Violeta" Version="4.0.3">
|
||||
<PackageReference Include="WPF-UI.Violeta" Version="4.0.3.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Lib.Harmony" Version="2.3.6">
|
||||
|
@@ -15,79 +15,91 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using QuickLook.Common.Commands;
|
||||
using QuickLook.Common.Helpers;
|
||||
using QuickLook.Helpers;
|
||||
using QuickLook.Properties;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using Wpf.Ui.Violeta.Win32;
|
||||
using ToolTipIcon = Wpf.Ui.Violeta.Win32.ToolTipIcon;
|
||||
|
||||
namespace QuickLook;
|
||||
|
||||
internal class TrayIconManager : IDisposable
|
||||
internal partial class TrayIconManager : IDisposable
|
||||
{
|
||||
private static TrayIconManager _instance;
|
||||
|
||||
private readonly NotifyIcon _icon;
|
||||
private readonly TrayIconHost _icon;
|
||||
|
||||
private readonly MenuItem _itemAutorun =
|
||||
new(TranslationHelper.Get("Icon_RunAtStartup"),
|
||||
(sender, e) =>
|
||||
private readonly TrayMenuItem _itemAutorun =
|
||||
new()
|
||||
{
|
||||
Header = TranslationHelper.Get("Icon_RunAtStartup"),
|
||||
Command = new RelayCommand(() =>
|
||||
{
|
||||
if (AutoStartupHelper.IsAutorun())
|
||||
AutoStartupHelper.RemoveAutorunShortcut();
|
||||
else
|
||||
AutoStartupHelper.CreateAutorunShortcut();
|
||||
})
|
||||
{ Enabled = !App.IsUWP };
|
||||
}),
|
||||
IsEnabled = !App.IsUWP,
|
||||
};
|
||||
|
||||
private TrayIconManager()
|
||||
{
|
||||
_icon = new NotifyIcon
|
||||
_icon = new TrayIconHost
|
||||
{
|
||||
Text = string.Format(TranslationHelper.Get("Icon_ToolTip"),
|
||||
ToolTipText = string.Format(TranslationHelper.Get("Icon_ToolTip"),
|
||||
Application.ProductVersion),
|
||||
Icon = GetTrayIconByDPI(),
|
||||
ContextMenu = new ContextMenu(
|
||||
Menu =
|
||||
[
|
||||
new MenuItem($"v{Application.ProductVersion}{(App.IsUWP ? " (UWP)" : string.Empty)}") {Enabled = false},
|
||||
new MenuItem("-"),
|
||||
new MenuItem(TranslationHelper.Get("Icon_CheckUpdate"), (_, _) => Updater.CheckForUpdates()),
|
||||
new MenuItem(TranslationHelper.Get("Icon_GetPlugin"),
|
||||
(_, _) => Process.Start("https://github.com/QL-Win/QuickLook/wiki/Available-Plugins")),
|
||||
new MenuItem(TranslationHelper.Get("Icon_OpenDataFolder"), (_, _) => Process.Start("explorer.exe", SettingHelper.LocalDataPath)),
|
||||
new TrayMenuItem()
|
||||
{
|
||||
Header = $"v{Application.ProductVersion}{(App.IsUWP ? " (UWP)" : string.Empty)}",
|
||||
IsEnabled = false,
|
||||
},
|
||||
new TraySeparator(),
|
||||
new TrayMenuItem()
|
||||
{
|
||||
Header = TranslationHelper.Get("Icon_CheckUpdate"),
|
||||
Command = new RelayCommand(() => Updater.CheckForUpdates()),
|
||||
},
|
||||
new TrayMenuItem()
|
||||
{
|
||||
Header = TranslationHelper.Get("Icon_GetPlugin"),
|
||||
Command = new RelayCommand(() => Process.Start("https://github.com/QL-Win/QuickLook/wiki/Available-Plugins")),
|
||||
},
|
||||
new TrayMenuItem()
|
||||
{
|
||||
Header = TranslationHelper.Get("Icon_OpenDataFolder"),
|
||||
Command = new RelayCommand(() => Process.Start("explorer.exe", SettingHelper.LocalDataPath)),
|
||||
},
|
||||
_itemAutorun,
|
||||
new MenuItem(TranslationHelper.Get("Icon_Restart"), (_, _) => Restart(forced: true)),
|
||||
new MenuItem(TranslationHelper.Get("Icon_Quit"),
|
||||
(_, _) => System.Windows.Application.Current.Shutdown())
|
||||
]),
|
||||
Visible = SettingHelper.Get("ShowTrayIcon", true)
|
||||
new TrayMenuItem()
|
||||
{
|
||||
Header = TranslationHelper.Get("Icon_Restart"),
|
||||
Command = new RelayCommand(() => Restart(forced: true)),
|
||||
},
|
||||
new TrayMenuItem()
|
||||
{
|
||||
Header = TranslationHelper.Get("Icon_Quit"),
|
||||
Command = new RelayCommand(System.Windows.Application.Current.Shutdown),
|
||||
}
|
||||
],
|
||||
IsVisible = SettingHelper.Get("ShowTrayIcon", true)
|
||||
};
|
||||
|
||||
_icon.ContextMenu.Popup += (sender, e) => { _itemAutorun.Checked = AutoStartupHelper.IsAutorun(); };
|
||||
|
||||
// Readjust the display position of ContextMenu
|
||||
if (SettingHelper.Get("ModernTrayIcon", true, "QuickLook"))
|
||||
{
|
||||
_icon.MouseDown += (_, e) =>
|
||||
{
|
||||
if (e.Button == MouseButtons.Right)
|
||||
{
|
||||
// Call ShowContextMenu here will be later than the native call,
|
||||
// so here can readjust the ContextMenu position.
|
||||
// You can check the source code to determine the behavior.
|
||||
_icon.ShowContextMenu();
|
||||
}
|
||||
};
|
||||
}
|
||||
_icon.RightDown += (sender, e) => { _itemAutorun.IsChecked = AutoStartupHelper.IsAutorun(); };
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_icon.Visible = false;
|
||||
_icon.IsVisible = false;
|
||||
}
|
||||
|
||||
public void Restart(string fileName = null, string dir = null, string args = null, int? exitCode = null, bool forced = false)
|
||||
@@ -118,16 +130,16 @@ internal class TrayIconManager : IDisposable
|
||||
Environment.Exit(exitCode ?? 'r' + 'e' + 's' + 't' + 'a' + 'r' + 't');
|
||||
}
|
||||
|
||||
private Icon GetTrayIconByDPI()
|
||||
private nint GetTrayIconByDPI()
|
||||
{
|
||||
var scale = DisplayDeviceHelper.GetCurrentScaleFactor().Vertical;
|
||||
|
||||
if (!App.IsWin10)
|
||||
return scale > 1 ? Resources.app : Resources.app_16;
|
||||
return scale > 1 ? Resources.app.Handle : Resources.app_16.Handle;
|
||||
|
||||
return OSThemeHelper.SystemUsesDarkTheme()
|
||||
? (scale > 1 ? Resources.app_white : Resources.app_white_16)
|
||||
: (scale > 1 ? Resources.app_black : Resources.app_black_16);
|
||||
? (scale > 1 ? Resources.app_white.Handle : Resources.app_white_16.Handle)
|
||||
: (scale > 1 ? Resources.app_black.Handle : Resources.app_black_16.Handle);
|
||||
}
|
||||
|
||||
public static void ShowNotification(string title, string content, bool isError = false, int timeout = 5000,
|
||||
|
Reference in New Issue
Block a user