When juggling between a high-performance gaming setup and a cozy home theater experience, convenience is key. I own a 32-inch high refresh rate gaming monitor and a 40-inch Samsung TV, each tailored for distinct purposes. The gaming monitor, paired with Logitech Z625 THX speakers, delivers impeccable sound for immersive gaming, while the Samsung TV, connected to a Xiaomi Soundbar, sets the perfect tone for movies. However, manually switching between these displays and their audio setups through the Windows Control Panel was cumbersome and broke the seamless experience I sought.
Motivated by this inconvenience, I decided to develop a custom solution using Windows C#. My aim was to create a program that could effortlessly manage the transition between the two setups. The program would not only switch displays but also ensure that the audio devices changed in tandem, eliminating the need for repetitive manual configurations. It became a personal project to simplify my digital life.
To handle audio device switching, I incorporated the powerful utility nircmd, a command-line tool that allows for quick adjustments of system settings. By integrating nircmd into my program, I enabled automatic audio device changes depending on the active display. This feature saved me countless clicks and added a layer of automation that aligned perfectly with my vision of convenience.
One of the unique challenges I faced was ensuring the TV was ready for use before switching the display. To address this, I added a prompt UI in my program. This simple yet effective alert reminds the user to turn on the Samsung TV using its remote control before proceeding. It's a small feature, but it significantly enhances the user experience by avoiding any unnecessary frustrations caused by a blank screen.
Beyond managing displays and audio, I tailored the program to adapt my Rainmeter layout based on the active display. My gaming monitor uses a Rainmeter setup optimized for productivity and everyday computer use, while the Samsung TV transitions to a layout focused on entertainment. The latter showcases widgets designed for streaming services, media libraries, and other TV-friendly visuals, creating an immersive entertainment experience.
This integration of display-specific Rainmeter layouts proved to be a game-changer. It added a layer of personalization that not only enhanced functionality but also elevated the aesthetic appeal of both setups. Switching from work mode to entertainment mode became a breeze, with everything configured perfectly with just a click. In the end, this project became more than just a solution to a problem. It was a rewarding journey of blending technology with convenience, showcasing how small customizations can lead to significant improvements in daily routines. Now, with my Windows C# program, I can effortlessly switch between gaming and movie-watching modes, enjoying the best of both worlds without breaking a sweat.
Program was developed using Visual Studio in a C# language as below.
using System; using System.Diagnostics; using System.Drawing; using System.Windows.Forms; namespace MonitorSwitcher { public partial class Form1 : Form { public Form1() { InitializeComponent(); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); KillRainmeter(); // Kill Rainmeter on application launch RunMonitorSwitchLogic(); // Run logic on form load this.Close(); // Close the form after executing the logic } private void KillRainmeter() { // Taskkill Rainmeter.exe try { foreach (var process in Process.GetProcessesByName("Rainmeter")) { process.Kill(); } } catch { // Fail silently if process killing fails } } private void RestartRainmeter() { // Restart Rainmeter.exe ExecuteCommand(@"C:\Program Files\Rainmeter\Rainmeter.exe", ""); } private void RunMonitorSwitchLogic() { string activeMonitor = GetActiveMonitorByRefreshRate(); if (activeMonitor == "PHL 322M8CP") { if (!ShowImageWithOkCancel()) // Show image and wait for user decision { RestartRainmeter(); // Restart Rainmeter if the user clicks "Cancel" Application.Exit(); // Cancel the process return; } ExecuteCommand("DisplaySwitch.exe", "4"); System.Threading.Thread.Sleep(1000); ExecuteCommand(@"c:\system\nircmd\nircmd.exe", "mutesysvolume 1 \"Speakers\""); ExecuteCommand(@"c:\system\nircmd\nircmd.exe", "mutesysvolume 0 \"SPDIF-OUT\""); ExecuteCommand(@"c:\system\nircmd\nircmd.exe", "setdefaultsounddevice SPDIF-OUT"); ExecuteCommand(@"C:\Program Files\Rainmeter\Rainmeter.exe", @"!LoadLayout LEMON-Q9550-PC-03-DISP2"); } else if (activeMonitor == "SAMSUNG") { ExecuteCommand("DisplaySwitch.exe", "1"); System.Threading.Thread.Sleep(1000); ExecuteCommand(@"c:\system\nircmd\nircmd.exe", "mutesysvolume 1 \"SPDIF-OUT\""); ExecuteCommand(@"c:\system\nircmd\nircmd.exe", "mutesysvolume 0 \"Speakers\""); ExecuteCommand(@"c:\system\nircmd\nircmd.exe", "setdefaultsounddevice Speakers"); ExecuteCommand(@"C:\Program Files\Rainmeter\Rainmeter.exe", @"!LoadLayout LEMON-Q9550-PC-03-DISP1"); } Application.Exit(); // Ensure the application exits completely } private bool ShowImageWithOkCancel() { bool userConfirmed = false; using (Form imageForm = new Form()) { imageForm.Text = string.Empty; // Remove title text imageForm.StartPosition = FormStartPosition.CenterScreen; imageForm.ClientSize = new System.Drawing.Size(800, 549); imageForm.BackColor = Color.White; imageForm.FormBorderStyle = FormBorderStyle.None; // Remove control buttons and title bar imageForm.Icon = null; // Remove icon imageForm.Opacity = 0; // Start with fully transparent // Timer for fade-in effect System.Windows.Forms.Timer fadeTimer = new System.Windows.Forms.Timer { Interval = 25 // Adjust to control the fade-in speed (50ms per step) }; fadeTimer.Tick += (s, e) => { if (imageForm.Opacity < 1) { imageForm.Opacity += 0.05; // Incrementally increase opacity } else { fadeTimer.Stop(); // Stop the timer when fully opaque } }; fadeTimer.Start(); // Start the fade-in timer // Add a visible border for the entire form int borderThickness = 5; // Thickness of the border Color borderColor = Color.Black; // Color of the border imageForm.Paint += (s, e) => { using (var borderPen = new Pen(borderColor, borderThickness)) { e.Graphics.DrawRectangle(borderPen, new Rectangle(borderThickness / 2, borderThickness / 2, imageForm.ClientSize.Width - borderThickness, imageForm.ClientSize.Height - borderThickness)); } }; PictureBox pictureBox = new PictureBox { ImageLocation = "TV-ON-Guide.gif", // Ensure the image path is correct SizeMode = PictureBoxSizeMode.Zoom, Dock = DockStyle.Fill }; Panel buttonPanel = new Panel { Dock = DockStyle.Bottom, Height = 50, BackColor = Color.White }; Button okButton = new Button { Text = "OK", Dock = DockStyle.Left, BackColor = Color.Green, ForeColor = Color.White, Font = new Font("Segoe UI", 12, FontStyle.Bold), FlatStyle = FlatStyle.Flat, Width = imageForm.ClientSize.Width / 2 }; okButton.FlatAppearance.BorderSize = 0; okButton.Click += (s, e) => { userConfirmed = true; imageForm.Close(); }; Button cancelButton = new Button { Text = "CANCEL", Dock = DockStyle.Right, BackColor = Color.Red, ForeColor = Color.White, Font = new Font("Segoe UI", 12, FontStyle.Bold), FlatStyle = FlatStyle.Flat, Width = imageForm.ClientSize.Width / 2 }; cancelButton.FlatAppearance.BorderSize = 0; cancelButton.Click += (s, e) => { userConfirmed = false; imageForm.Close(); }; buttonPanel.Controls.Add(okButton); buttonPanel.Controls.Add(cancelButton); imageForm.Controls.Add(pictureBox); imageForm.Controls.Add(buttonPanel); imageForm.ShowDialog(); } return userConfirmed; } private string GetActiveMonitorByRefreshRate() { try { using (var searcher = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_VideoController")) { foreach (System.Management.ManagementObject obj in searcher.Get()) { int refreshRate = Convert.ToInt32(obj["CurrentRefreshRate"] ?? 0); // Map refresh rate to the monitor if (refreshRate == 239) { return "PHL 322M8CP"; // Display 1 } else if (refreshRate == 60) { return "SAMSUNG"; // Display 2 } } } } catch { // Fail silently if detection fails } return "Unknown"; } private void ExecuteCommand(string fileName, string arguments) { try { Process.Start(new ProcessStartInfo { FileName = fileName, Arguments = arguments, UseShellExecute = true, }); } catch { // Fail silently if command execution fails } } } }
Switching between my 32-inch high refresh rate gaming monitor and 40-inch Samsung TV used to be a hassle, as it required manual adjustments in the Windows Control Panel for both displays and audio devices. The gaming monitor, connected to Logitech Z625 THX speakers, was perfect for immersive gaming, while the Samsung TV, paired with a Xiaomi Soundbar, created an ideal movie-watching experience. To streamline this process, I developed a custom Windows C# program to automate switching between these setups, saving time and effort.
The program leverages nircmd commands to seamlessly change audio devices based on the active display, ensuring a smooth transition between setups. Additionally, it features a prompt UI that reminds the user to turn on the Samsung TV before switching, avoiding unnecessary delays. To further enhance functionality, the program adapts my Rainmeter layout to the active display, with a productivity-focused setup for the gaming monitor and an entertainment-centric design for the TV.
This project not only solved my problem but also improved the overall experience of using both setups. With a single click, I can switch between gaming and entertainment modes, complete with tailored visuals, audio configurations, and functionality. It's a testament to how simple automation can transform everyday routines into seamless, enjoyable experiences.