Processing Ajax...

Title
Close Dialog

Message

Confirm
Close Dialog

Confirm
Close Dialog

Dim All Monitors

Description
This script creates a translucent black window that overlays all monitors, effectively dimming the monitors.
Language
C#.net
Minimum Version
Created By
NetMage, Thomas Malloch (BFS)
Contributors
-
Date Created
Feb 3, 2015
Date Last Modified
Jun 30, 2016

Scripted Function (Macro) Code

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

// 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
{
	public static void Run(IntPtr windowHandle) {
        ToggleSetting(); // toggle the setting from run to not run, and vice versa

        var forms = new List<Form>();

		if(RunDimMonitor()) {
            //make a list of forms for each monitor
            //the second argument is the transparency
            foreach (var monitor in BFS.Monitor.GetMonitorIDs()) {
                forms.Add(new TransparentForm(monitor, 30m));
            }
		
            //this will open the forms using our custom application context
            Application.Run(new MultipleFormApplicationContext(forms));
        }
    }

	private static readonly string SettingName = "DimMonitor_Run";

	//this function toggles the script settings from run to not run
	private static void ToggleSetting() {
		if(BFS.ScriptSettings.ReadValue(SettingName).Equals("run", StringComparison.Ordinal))
			BFS.ScriptSettings.WriteValue(SettingName, "not");
		else
			BFS.ScriptSettings.WriteValue(SettingName, "run");
	}

	//this function allows us to see the currect state of the script
	private static bool RunDimMonitor() {
		return BFS.ScriptSettings.ReadValue(SettingName).Equals("run", StringComparison.Ordinal);
	}
	
	//extend the ApplicationContext class to support opening multiple forms
	private class MultipleFormApplicationContext : ApplicationContext  {
		internal MultipleFormApplicationContext(List<Form> forms) {
			//add our closing event to each of the forms and open 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 {
		private uint MonitorId;
		private decimal Transparency;
		
		internal TransparentForm(uint monitorId, decimal transparency) {
			MonitorId = monitorId;
			Transparency = transparency;

			SuspendLayout();

			//setup the layout of this form
			BackColor = Color.Black;
			FormBorderStyle = FormBorderStyle.None;
			ShowInTaskbar = false;

			//move the window over 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, this.Transparency);

			//setup the form load event
			Load += Form_Load;			
			
			ResumeLayout(false);
		}

		private void Form_Load(object sender, EventArgs e) {
			//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() {
			while(true) {
				//if we should close, tell the main thread to close the form
				if(!RunDimMonitor()) {
					try {
						Invoke((MethodInvoker) delegate { Close(); });
					}
					catch { //something went wrong, ignore
					}
						
					break;
				}
				
				//sleep for a quarter of a second
				BFS.General.ThreadWait(250);
			}
		}
	}
}