Processing Ajax...

Title

Message

Confirm

Confirm

Confirm

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure?

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);
			}
		}
	}
}