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:
2026-10-01 20:19:32 +02:00
co-authored by Claude Opus 5.5
commit 77bb3e6b9d
36 changed files with 5894 additions and 0 deletions
+138
View File
@@ -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;
}
}