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 Selected Monitor to Black

Description
Fades the selected monitor to black over a two second period. On the second run, the monitor unfades.
Language
C#.net
Minimum Version
Created By
Keith Lammers (BFS)
Contributors
-
Date Created
Aug 28, 2017
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;

// Based entirely on NetMage's "Fade All Monitors Except the Primary Monitor to Black" which was based on Thomas' "Dim All Monitors Except Primary"

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 the selected monitor to the form
            var forms = new List<Form>();
            forms.Add(new TransparentForm(BFS.Monitor.ShowMonitorSelector()));
		
            //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 { }
       }
	}
}