DeskCore 1.0.0
Desktop-Icons in eigene Kategorien sortieren: Windows-11-Design (hell/dunkel), Desktop-Boxen, automatisches Einsortieren nach Regeln, Rückgängig, Suche, Infobereich mit Tastenkürzel, Sicherung als ZIP und Installer ohne Adminrechte. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace DeskCore;
|
||||
|
||||
/// <summary>Systemweites Tastenkürzel (RegisterHotKey).</summary>
|
||||
public sealed class Hotkey : IDisposable
|
||||
{
|
||||
public const int ModAlt = 0x1, ModCtrl = 0x2, ModShift = 0x4, ModWin = 0x8;
|
||||
private const int ModNoRepeat = 0x4000, WmHotkey = 0x0312, Id = 0xB001;
|
||||
|
||||
private readonly IntPtr _hwnd;
|
||||
private readonly HwndSource _source;
|
||||
private bool _registered;
|
||||
|
||||
public event Action? Pressed;
|
||||
|
||||
public Hotkey(IntPtr hwnd)
|
||||
{
|
||||
_hwnd = hwnd;
|
||||
_source = HwndSource.FromHwnd(hwnd);
|
||||
_source.AddHook(Hook);
|
||||
}
|
||||
|
||||
/// <summary>Registriert das Kürzel. false = schon von einem anderen Programm belegt.</summary>
|
||||
public bool Register(int modifiers, int vk)
|
||||
{
|
||||
Unregister();
|
||||
if (vk == 0) return false;
|
||||
_registered = RegisterHotKey(_hwnd, Id, modifiers | ModNoRepeat, vk);
|
||||
return _registered;
|
||||
}
|
||||
|
||||
public void Unregister()
|
||||
{
|
||||
if (_registered) UnregisterHotKey(_hwnd, Id);
|
||||
_registered = false;
|
||||
}
|
||||
|
||||
private IntPtr Hook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||
{
|
||||
if (msg == WmHotkey && wParam.ToInt32() == Id)
|
||||
{
|
||||
Pressed?.Invoke();
|
||||
handled = true;
|
||||
}
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
public static string Describe(int modifiers, int vk)
|
||||
{
|
||||
if (vk == 0) return "–";
|
||||
var parts = new List<string>();
|
||||
if ((modifiers & ModWin) != 0) parts.Add("Win");
|
||||
if ((modifiers & ModCtrl) != 0) parts.Add("Strg");
|
||||
if ((modifiers & ModAlt) != 0) parts.Add("Alt");
|
||||
if ((modifiers & ModShift) != 0) parts.Add("Umschalt");
|
||||
var key = KeyInterop.KeyFromVirtualKey(vk);
|
||||
parts.Add(key switch
|
||||
{
|
||||
>= Key.D0 and <= Key.D9 => ((char)('0' + (key - Key.D0))).ToString(),
|
||||
Key.Space => "Leertaste",
|
||||
_ => key.ToString(),
|
||||
});
|
||||
return string.Join(" + ", parts);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Unregister();
|
||||
_source.RemoveHook(Hook);
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")] private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
|
||||
[DllImport("user32.dll")] private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
|
||||
}
|
||||
|
||||
/// <summary>Start mit Windows über HKCU\...\Run.</summary>
|
||||
public static class Autostart
|
||||
{
|
||||
private const string Key = @"Software\Microsoft\Windows\CurrentVersion\Run";
|
||||
private const string Name = "DeskCore";
|
||||
// Frühere Namen dieser App. "DeskHub" heißt auch ein anderes Programm → nur übernehmen, wenn der Eintrag eindeutig von uns ist.
|
||||
private static readonly string[] OldNames = ["DesktopSortierer", "DeskHub"];
|
||||
|
||||
public static bool Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
using var k = Registry.CurrentUser.OpenSubKey(Key);
|
||||
return k?.GetValue(Name) is string;
|
||||
}
|
||||
catch { return false; }
|
||||
}
|
||||
set
|
||||
{
|
||||
try
|
||||
{
|
||||
using var k = Registry.CurrentUser.OpenSubKey(Key, writable: true) ?? Registry.CurrentUser.CreateSubKey(Key);
|
||||
if (value) k.SetValue(Name, $"\"{Environment.ProcessPath}\" --minimized");
|
||||
else k.DeleteValue(Name, throwOnMissingValue: false);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Alten Autostart-Eintrag ("DesktopSortierer") auf den neuen Namen umstellen.</summary>
|
||||
public static void Migrate()
|
||||
{
|
||||
try
|
||||
{
|
||||
using var k = Registry.CurrentUser.OpenSubKey(Key, writable: true);
|
||||
if (k is null) return;
|
||||
bool wasEnabled = false;
|
||||
foreach (var old in OldNames)
|
||||
{
|
||||
if (k.GetValue(old) is not string cmd) continue;
|
||||
bool ours = old == "DesktopSortierer" ||
|
||||
(cmd.Contains($"{old}.exe", StringComparison.OrdinalIgnoreCase) && cmd.Contains("--minimized"));
|
||||
if (!ours) continue;
|
||||
k.DeleteValue(old, throwOnMissingValue: false);
|
||||
wasEnabled = true;
|
||||
}
|
||||
if (wasEnabled) Enabled = true;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>Falls die exe verschoben wurde: Pfad im Autostart aktualisieren.</summary>
|
||||
public static void RefreshPath()
|
||||
{
|
||||
if (Enabled) Enabled = true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user