Processing Ajax...
Save 25% on our desktop apps during our Black Friday/Cyber Monday sale!Save 25% on our desktop apps during our Black Friday/Cyber Monday sale, including DisplayFusion, ClipboardFusion, FileSeek, LogFusion, TrayStatus, and VoiceBot!Save 25% on our desktop apps during our Black Friday/Cyber Monday sale!

Title
Close Dialog

Message

Confirm
Close Dialog

Confirm
Close Dialog

Fade All Monitors Except the Primary Monitor to Black

Description
Fades all monitors except the primary monitor to black over a two second period.
Language
C#.net
Minimum Version
Created By
NetMage
Contributors
-
Date Created
Jun 24, 2015
Date Last Modified
Nov 5, 2019

Scripted Function (Macro) Code

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Collections.Generic;

// Fade all monitors except the primary monitor to black over a two second period
// Adjust 

// Based entirely on Thomas Malloch's very brilliant Dim All Monitors Except Primary
// Hope he will forgive the change to K&R style and general clean-up to be more abbreviated

// The 'windowHandle' parameter will contain the window handle for the:
//   - Active window when run by hotkey
//   - Window Location target when run by a Window Location rule
//   - TitleBar Button owner when run by a TitleBar Button
//   - Jump List owner when run from a Taskbar Jump List
//   - Currently focused window if none of these match
public static class DisplayFusionFunction {
	private static readonly string SettingName = "BlackenMonitors_Run";
	public static void Run(IntPtr windowHandle) {
		//toggle the setting from running to not running, and vice versa
		ToggleSetting();

		if (RunFadeMonitors()) {
            //add all but the primary monitor to the list of monitors that will be dimmed
            var forms = new List<Form>();
            uint primaryMonitorID = BFS.Monitor.GetPrimaryMonitorID();
            foreach(uint id in BFS.Monitor.GetMonitorIDs())
                if(id != primaryMonitorID)
                    forms.Add(new TransparentForm(id));
		
            //this will open the forms we added to the list by using our custom application context
            Application.Run(new MultipleFormApplicationContext(forms));
        }
	}
	
	//this function allows us to see the currect state of the script
	private static bool RunFadeMonitors() {
		return BFS.ScriptSettings.ReadValue(SettingName) == "run";
	}

	//this function toggles the script settings from running to not running
	private static void ToggleSetting() {
		BFS.ScriptSettings.WriteValue(SettingName, RunFadeMonitors() ? "not" : "run");
	}

	//extend the ApplicationContext class to support opening multiple forms
	private class MultipleFormApplicationContext : ApplicationContext {
		internal MultipleFormApplicationContext(List<Form> forms) {
			//open each of the forms, and add our closing event to them
			foreach(Form form in forms) {
				form.FormClosed += OnFormClosed;
				form.Show();
			}
		}

		//when all the forms close, make sure to exit the application
		private void OnFormClosed(object sender, EventArgs e) {
			if(Application.OpenForms.Count == 0)
				ExitThread();
		}
	}
	
	//extend the Form class to get the behavior we want
	private class TransparentForm : Form {
		//this will tell us what monitor to open on
		private uint MonitorId;
		private uint FadeWait;
		private decimal TransparentIncrement;
        private IntPtr HandleTHREADSAFE;
		
		//this will tell us our current transparency
		private decimal Transparency;
		
		//the contructor for our class
		internal TransparentForm(uint monitorId) {		
			MonitorId = monitorId;
			Transparency = 0m;
			const decimal FadeTime = 2.0m; // seconds
			TransparentIncrement = 1m; // percent
			FadeWait = (uint)(TransparentIncrement * 10m * FadeTime);
			
			SuspendLayout();
			
			//setup the layout of this form
			BackColor = Color.Black;
			FormBorderStyle = FormBorderStyle.None;
			ShowInTaskbar = false;
			//move the window to the desired monitor
			Rectangle bounds = BFS.Monitor.GetMonitorBoundsByID(MonitorId);
			Location = new Point(bounds.X, bounds.Y);
			Size = new Size(bounds.Width, bounds.Height);
			StartPosition = FormStartPosition.Manual;
			
			BFS.Window.SetAlwaysOnTop(Handle, true);
			BFS.Window.SetTransparency(Handle, Transparency);

			//setup the form load event
			Load += Form_Load;			
			
			ResumeLayout(false);
		}
		
		private void Form_Load(object sender, EventArgs e) {
            HandleTHREADSAFE = Handle;
            
			//add a windows style to the current style that will
			//tell this window to ignore user input
			uint style = (uint)BFS.Window.GetWindowStyleEx(Handle) | (uint)BFS.WindowEnum.WindowStyleEx.WS_EX_TRANSPARENT | (uint)BFS.WindowEnum.WindowStyleEx.WS_EX_LAYERED;
			BFS.Window.SetWindowStyleEx((BFS.WindowEnum.WindowStyleEx)style, Handle);
			
			//start up a thread to listen for an exit event
			new Thread(new ThreadStart(ExitListener)).Start();
		}

		private void ExitListener() {
            try {
                while(true) {
                    //if we should close, tell the main thread to close the form
                    if(RunFadeMonitors()) {
                        // Fade to Black
                        if (Transparency < 100m) {
                            Transparency += TransparentIncrement;
                            BFS.Window.SetTransparency(HandleTHREADSAFE, Transparency);
                        }

                        //sleep
                        BFS.General.ThreadWait((Transparency < 100m) ? FadeWait : 250u);				
                    }
                    else {
                        if (this.Transparency > 0m) {
                            // Fade back in
                            Transparency -= TransparentIncrement;
                            BFS.Window.SetTransparency(HandleTHREADSAFE, Transparency);

                            //sleep
                            BFS.General.ThreadWait((Transparency < 100m) ? FadeWait : 250u);
                        }
                        else {
                            try {
                                this.Invoke((MethodInvoker) delegate {
                                    Close();
                                });
                            }
                            catch { //something went wrong, ignore
                            }
                            
                            break;
                        }
                    }
                }                
			}
			catch { }
		}
	}
}