using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Threading; namespace DD2Switcher { internal static class Program { private static int NumProc = 19; private static Process[] windows = new Process[NumProc]; private static int ActiveIndex = -1; private static bool AltPressed = false; // Simple list to track last 5 windows private static List lastWindows = new List(); private static readonly IntPtr defaultAffinity = new(0xFF000000); private static readonly IntPtr fullAffinity = new(0xFFFFFFFF); private static readonly KeyboardHook keyboardHook = new(); [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] private static extern short GetKeyState(int nVirtKey); [DllImport("kernel32.dll", SetLastError = true)] [return:MarshalAs(UnmanagedType.Bool)] static extern bool AllocConsole(); [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo); private static void CleanWindows() { for (int i = 0; i < NumProc; i++) { var window = windows[i]; if (window == null) continue; if (window.MainWindowHandle == IntPtr.Zero) { Console.WriteLine($"Window at index {i} has no main window, removing from tracked windows"); windows[i] = null; } } } private static void AdjustAffinities() { CleanWindows(); for (int i = 0; i < NumProc; i++) { var window = windows[i]; if (window == null) continue; if (i != ActiveIndex) { try { window.ProcessorAffinity = defaultAffinity; } catch (Exception e) { windows[i] = null; } } } var active = windows[ActiveIndex]; if (active != null) { try { active.ProcessorAffinity = fullAffinity; } catch (Exception e) { windows[ActiveIndex] = null; } } } private static void AdjustPriorities() { CleanWindows(); for (int i = 0; i < NumProc; i++) { var window = windows[i]; if (window == null) continue; if (i != ActiveIndex) { try { window.PriorityClass = ProcessPriorityClass.Idle; } catch (Exception e) { windows[i] = null; } } } var active = windows[ActiveIndex]; if (active != null) { try { active.PriorityClass = ProcessPriorityClass.High; } catch (Exception e) { windows[ActiveIndex] = null; } } } private static Process GetForegroundProcess() { var foregroundWindow = GetForegroundWindow(); var process = Process.GetProcesses(); Process foregroundProcess = null; foreach (var p in process) if (foregroundWindow == p.MainWindowHandle) { foregroundProcess = p; break; } if (foregroundProcess == null) return null; return foregroundProcess; } private static Boolean ProcessTracked(int id) { for (int i = 0; i < NumProc; i++) { if (windows[i] != null && windows[i].Id == id) { return true; } } return false; } private static void Track(Process process) { // First find the first null slot int firstNullIndex = -1; for (int i = 0; i < NumProc; i++) { if (windows[i] == null) { firstNullIndex = i; break; } } if (firstNullIndex == -1) { Console.WriteLine("No slots available for tracking"); return; } // Compact the array by shifting non-null elements to the left for (int i = firstNullIndex + 1; i < NumProc; i++) { if (windows[i] != null) { windows[firstNullIndex] = windows[i]; windows[i] = null; firstNullIndex++; } } // Add the new process at the first null slot windows[firstNullIndex] = process; PushHistory(firstNullIndex); ActiveIndex = firstNullIndex; Console.WriteLine($"Added {process.ProcessName} to tracked windows at index {firstNullIndex}"); } private static void TrackProcess() { CleanWindows(); var foregroundWindow = GetForegroundWindow(); var foregroundProcess = Process.GetProcesses().FirstOrDefault(p => p.MainWindowHandle == foregroundWindow); if (foregroundProcess == null) { Console.WriteLine("No foreground process found"); return; } Console.WriteLine($"Foreground process: {foregroundProcess.ProcessName} PID: {foregroundProcess.Id}"); var processes = Process.GetProcesses().OrderBy(p => p.Id).ToList(); foreach (var process in processes) { // Console.WriteLine($"Checking {process.ProcessName} at pid {process.Id}"); if (process.ProcessName == foregroundProcess.ProcessName) { Console.WriteLine($"Found {foregroundProcess.ProcessName} at pid {process.Id}"); if (ProcessTracked(process.Id)) continue; Track(process); } } } private static void Swap(int index) { index = (index - 1) % NumProc; if (index < 0) index = NumProc - 1; if (index >= NumProc) return; CleanWindows(); Console.WriteLine($"Swapping window at index {index}"); var process = GetForegroundProcess(); if (process == null) return; Console.WriteLine($"Foreground process: {process}"); bool found = false; for (int i = 0; i < NumProc; i++) { var window = windows[i]; if (window != null && window.Id == process.Id) { found = true; break; } } if (!found) { for (int i = 0; i < NumProc; i++) { var window = windows[i]; if (window == null) { Console.WriteLine($"Adding foreground window to tracked at index {i}..."); windows[i] = process; break; } } } for (int i = 0; i < NumProc; i++) { var window = windows[i]; if (window != null && window.Id == process.Id) { windows[i] = windows[index]; windows[index] = window; Console.WriteLine($"Swapped window at index {i} to {index}"); return; } } } private static void TabTo(int index) { index = (index - 1) % NumProc; if (index < 0) index = NumProc - 1; if (index >= NumProc) return; CleanWindows(); Console.WriteLine($"Tab to window at index {index}"); var window = windows[index]; if (window == null || window.MainWindowHandle == IntPtr.Zero) { Console.WriteLine($"Window at index {index} does not exist, removing from tracked windows"); windows[index] = null; } else { if (ActiveIndex != -1) PushHistory(ActiveIndex); SetForegroundWindow(window.MainWindowHandle); ActiveIndex = index; AdjustAffinities(); AdjustPriorities(); } } private static void TabToPrevious() { try { var foreground = GetForegroundProcess(); if (!ProcessTracked(foreground.Id)) { Console.WriteLine("Foreground process not tracked, skipping"); return; } } catch (Exception e) { Console.WriteLine($"Error setting foreground window: {e}"); } if (lastWindows.Count == 0) { Console.WriteLine("No previous window to switch to"); return; } CleanWindows(); for (int i = lastWindows.Count - 1; i >= 0; i--) { int index = lastWindows[i]; if (index != ActiveIndex) { TabTo(index + 1); // Our windows are 1-indexed because... I don't remember why break; } } } private static bool IsCapsLockOn() { return (GetKeyState(0x14) & 1) == 1; } private static void ToggleCapsLock() { keybd_event(0x14, 0, 0, 0); // KEYEVENTF_KEYDOWN keybd_event(0x14, 0, 0x0002, 0); // KEYEVENTF_KEYUP } private static void PushHistory(int index) { lastWindows.Add(index); if (lastWindows.Count > 50) lastWindows.RemoveAt(0); } [STAThread] private static void Main() { // AllocConsole(); var processes = Process.GetProcesses(); var currentProcess = Process.GetCurrentProcess(); foreach (var process in processes) if (process.Id != currentProcess.Id && process.ProcessName == currentProcess.ProcessName) { process.Kill(); Process.GetCurrentProcess().Kill(); } bool onlyAlt = false; KeyboardHook.Start(); KeyboardHook.KeyDown += (sender, e) => { Console.WriteLine($"Key down: {e}"); if (e == 164 && !onlyAlt) { Console.WriteLine("Only alt"); onlyAlt = true; } else { Console.WriteLine("Not only alt"); onlyAlt = false; } }; KeyboardHook.KeyUp += (sender, e) => { Console.WriteLine($"Key up: {e}"); if (e == 164 && onlyAlt) { // Left alt Console.WriteLine("Tab to previous"); onlyAlt = false; TabToPrevious(); } }; HotKeyManager.RegisterHotKey(Keys.Capital, KeyModifiers.NoRepeat); // Register main number keys (0-9) for (int i = 0; i < 10; i++) HotKeyManager.RegisterHotKey(Keys.D0 + i, KeyModifiers.Alt); // Register numpad keys (1-9) for (int i = 0; i < 9; i++) HotKeyManager.RegisterHotKey(Keys.NumPad1 + i, KeyModifiers.Alt); HotKeyManager.RegisterHotKey(Keys.Oemtilde, KeyModifiers.Alt); HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed; void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e) { if (e.Key == Keys.Oemtilde && e.Modifiers == KeyModifiers.Alt && IsCapsLockOn()) { TrackProcess(); ToggleCapsLock(); return; } int index; if (e.Key >= Keys.D0 && e.Key <= Keys.D9) { index = e.Key - Keys.D0; } else if (e.Key >= Keys.NumPad1 && e.Key <= Keys.NumPad9) { index = 10 + (e.Key - Keys.NumPad1); } else { return; } if (e.Modifiers == KeyModifiers.Alt) { if (IsCapsLockOn()) { Swap(index); ToggleCapsLock(); } else { TabTo(index); } } } // Console.CancelKeyPress += (sender, e) => { Process.GetCurrentProcess().Kill(); }; Application.Run(); KeyboardHook.Stop(); } } }