1using System; 2using System.Diagnostics; 3using System.Drawing; 4using System.Threading; 5using System.Windows.Forms; 6 7namespace WindowCapture.App 8{ 9 /// <summary>The separable applications WindowCapture splits into. Each runs as its own 10 /// process (selected by a command-line flag) with its own tray icon and only the global 11 /// hooks it needs. The Launcher is the hub that starts the others via a radial menu.</summary> 12 public enum AppMode { Launcher, Screenshot, TextAssist, Clipboard, Soundpad, Search, MediaCore } 13 14 public static class AppModes 15 { 16 public static AppMode Parse(string[] args) 17 { 18 if (args != null) 19 foreach (var a in args) 20 { 21 switch ((a ?? "").Trim().ToLowerInvariant()) 22 { 23 case "--screenshot": case "-s": return AppMode.Screenshot; 24 case "--textassist": case "--autocorrect": case "-t": return AppMode.TextAssist; 25 case "--clipboard": case "-c": return AppMode.Clipboard; 26 case "--soundpad": return AppMode.Soundpad; 27 case "--search": return AppMode.Search; 28 case "--launcher": case "-l": return AppMode.Launcher; 29 case "--mediacore": case "-m": return AppMode.MediaCore; 30 } 31 } 32 return AppMode.MediaCore; // no flag -> the unified MediaCore app (single tray, module toggles) 33 } 34 35 public static string Flag(AppMode m) 36 { 37 switch (m) 38 { 39 case AppMode.Screenshot: return "--screenshot"; 40 case AppMode.TextAssist: return "--textassist"; 41 case AppMode.Clipboard: return "--clipboard"; 42 case AppMode.Soundpad: return "--soundpad"; 43 case AppMode.Search: return "--search"; 44 case AppMode.MediaCore: return "--mediacore"; 45 default: return "--launcher"; 46 } 47 } 48 49 public static string Title(AppMode m) 50 { 51 switch (m) 52 { 53 case AppMode.Screenshot: return "Скриншот"; 54 case AppMode.TextAssist: return "Автозамена"; 55 case AppMode.Clipboard: return "Буфер"; 56 case AppMode.Soundpad: return "Саундпад"; 57 case AppMode.Search: return "Поиск"; 58 case AppMode.MediaCore: return "MediaCore"; 59 default: return "Лаунчер"; 60 } 61 } 62 63 /// <summary>Single glyph drawn in the radial slice (kept simple — no icon assets needed).</summary> 64 public static string Glyph(AppMode m) 65 { 66 switch (m) 67 { 68 case AppMode.Screenshot: return "▢"; 69 case AppMode.TextAssist: return "Aa"; 70 case AppMode.Clipboard: return "❏"; 71 case AppMode.Soundpad: return "♪"; 72 case AppMode.Search: return "⌕"; 73 default: return "◎"; 74 } 75 } 76 77 public static Color Accent(AppMode m) 78 { 79 switch (m) 80 { 81 case AppMode.Screenshot: return Color.FromArgb(90, 160, 250); 82 case AppMode.TextAssist: return Color.FromArgb(110, 210, 140); 83 case AppMode.Clipboard: return Color.FromArgb(245, 180, 90); 84 case AppMode.Soundpad: return Color.FromArgb(210, 120, 235); 85 case AppMode.Search: return Color.FromArgb(95, 205, 220); 86 case AppMode.MediaCore: return Color.FromArgb(99, 102, 241); // indigo brand 87 default: return Color.FromArgb(120, 170, 240); 88 } 89 } 90 91 public static string MutexName(AppMode m) { return "WindowCapture_SingleInstance_" + m; } 92 public static string ShowEventName(AppMode m) { return "WindowCapture_ShowEvent_" + m; } 93 94 /// <summary>Launch the given app mode as its own process. If an instance is already running 95 /// and exposes a "show" event (windowed apps + launcher), signal it to surface instead of 96 /// starting a duplicate.</summary> 97 public static void Launch(AppMode m) 98 { 99 try 100 { 101 EventWaitHandle ev; 102 if (EventWaitHandle.TryOpenExisting(ShowEventName(m), out ev)) 103 { 104 ev.Set(); 105 ev.Close(); 106 return; 107 } 108 } 109 catch { } 110 try { Process.Start(Application.ExecutablePath, Flag(m)); } catch { } 111 } 112 113 /// <summary>Tiny programmatic tray icon (a colored disc) so each app is distinguishable 114 /// without shipping icon assets.</summary> 115 public static Icon CreateDiscIcon(Color color) 116 { 117 using (var bmp = new Bitmap(32, 32)) 118 { 119 using (var g = Graphics.FromImage(bmp)) 120 { 121 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; 122 g.Clear(Color.Transparent); 123 using (var b = new SolidBrush(color)) g.FillEllipse(b, 4, 4, 24, 24); 124 using (var p = new Pen(Color.FromArgb(230, 255, 255, 255), 2)) g.DrawEllipse(p, 4, 4, 24, 24); 125 } 126 IntPtr h = bmp.GetHicon(); 127 try { using (var tmp = Icon.FromHandle(h)) return (Icon)tmp.Clone(); } 128 finally { DestroyIcon(h); } 129 } 130 } 131 132 [System.Runtime.InteropServices.DllImport("user32.dll")] 133 private static extern bool DestroyIcon(IntPtr hIcon); 134 } 135}