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; //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) { //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(RunFadeMonitors()) { // Fade to Black if (Transparency < 100m) { Transparency += TransparentIncrement; BFS.Window.SetTransparency(Handle, Transparency); } //sleep BFS.General.ThreadWait((Transparency < 100m) ? FadeWait : 250u); } else { if (this.Transparency > 0m) { // Fade back in Transparency -= TransparentIncrement; BFS.Window.SetTransparency(Handle, Transparency); //sleep BFS.General.ThreadWait((Transparency < 100m) ? FadeWait : 250u); } else { try { this.Invoke((MethodInvoker) delegate { Close(); }); } catch { //something went wrong, ignore } break; } } } } } }
Sorry for the late response!
I was able to modify the script to be able to listen for the change of transparency value. The only downside is that you'll now need 3 scripts. One to toggle the dimming functionality and listen, another to increase the transparency value, and another to decrease it.
Here's the first script:
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 { private static readonly string SettingName = "DimMonitor_TransparentForm_Running"; private static readonly string TransparencySettingName = "DimMonitor_TransparentForm_TransparencyValue"; public static void Run(IntPtr windowHandle) { // toggle the setting from running to not running, and vice versa ToggleSetting(); // check to see if we should exit bool isExiting = !IsTransparentWindowRunning(); // if we are exiting, exit if(isExiting) return; // get the transparency value. if there's none, set it to 30% decimal transparency = 30; if(new List<string>(BFS.ScriptSettings.GetValueNames()).Contains(TransparencySettingName)) transparency = (decimal)BFS.ScriptSettings.ReadValueInt(TransparencySettingName); else BFS.ScriptSettings.WriteValueInt(TransparencySettingName, 30); // add all but the primary monitor to the list of monitors that will be dimmed List<Form> forms = new List<Form>(); foreach(uint id in BFS.Monitor.GetMonitorIDs()) forms.Add(new TransparentForm(id, transparency)); // this will open the forms we added to the list by using our custom application context Application.Run(new MultipleFormApplicationContext(forms)); } // this function toggles the script settings from running to not running private static void ToggleSetting() { string status = BFS.ScriptSettings.ReadValue(SettingName); if(status.Equals("running", StringComparison.Ordinal)) BFS.ScriptSettings.WriteValue(SettingName, "not"); else BFS.ScriptSettings.WriteValue(SettingName, "running"); } // this function allows us to see the currect state of the script private static bool IsTransparentWindowRunning() { string status = BFS.ScriptSettings.ReadValue(SettingName); return status.Equals("running", StringComparison.Ordinal); } // 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; // this will tell us what transparency to use private decimal LastTransparency; // this will help us with some threading private object ThreadLock = new object(); // the contructor for our class internal TransparentForm(uint monitorId, decimal transparency) { this.MonitorId = monitorId; lock(this.ThreadLock) this.LastTransparency = transparency; this.SuspendLayout(); // setup the layout of this form this.BackColor = Color.Black; this.FormBorderStyle = FormBorderStyle.None; this.ShowInTaskbar = false; // setup the form load event this.Load += Form_Load; this.ResumeLayout(false); } private void Form_Load(object sender, EventArgs e) { // set the window to be always on top BFS.Window.SetAlwaysOnTop(this.Handle, true); // make the window transparent lock(this.ThreadLock) BFS.Window.SetTransparency(this.Handle, this.LastTransparency); // add a windows style to the current style that will // tell this window to ignore user input uint style = (uint)BFS.Window.GetWindowStyleEx(this.Handle); BFS.Window.SetWindowStyleEx((BFS.WindowEnum.WindowStyleEx)(style | (uint)BFS.WindowEnum.WindowStyleEx.WS_EX_TRANSPARENT | (uint)BFS.WindowEnum.WindowStyleEx.WS_EX_LAYERED), this.Handle); // move the window to the desired monitor this.Bounds = BFS.Monitor.GetMonitorBoundsByID(this.MonitorId); // 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(!IsTransparentWindowRunning()) { try { this.Invoke((MethodInvoker) delegate { this.Close(); }); } catch // something went wrong, ignore { } break; } // check to see if we need to update the transparency bool isNeedingToUpdateTransparency = false; int transparency = BFS.ScriptSettings.ReadValueInt(TransparencySettingName); lock(this.ThreadLock) { if(transparency != (int)this.LastTransparency) { this.LastTransparency = (decimal)transparency; isNeedingToUpdateTransparency = true; } } if(isNeedingToUpdateTransparency) { decimal temp = (decimal)transparency; this.Invoke((MethodInvoker) delegate { BFS.Window.SetTransparency(this.Handle, temp); }); } // sleep for a quarter of a second BFS.General.ThreadWait(250); } } } }
Here's the second that will increase the value:
using System; using System.Drawing; // The 'windowHandle' parameter will contain the window handle for the: // - Active window when run by hotkey // - Trigger target when run by a Trigger 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 TransparencySettingName = "DimMonitor_TransparentForm_TransparencyValue"; public static void Run(IntPtr windowHandle) { int transparency = BFS.ScriptSettings.ReadValueInt(TransparencySettingName) + 5; if(transparency > 100) transparency = 100; BFS.ScriptSettings.WriteValueInt(TransparencySettingName, transparency); } }
Here's the third that will decrease the value:
using System; using System.Drawing; // The 'windowHandle' parameter will contain the window handle for the: // - Active window when run by hotkey // - Trigger target when run by a Trigger 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 TransparencySettingName = "DimMonitor_TransparentForm_TransparencyValue"; public static void Run(IntPtr windowHandle) { int transparency = BFS.ScriptSettings.ReadValueInt(TransparencySettingName) - 5; if(transparency < 0) transparency = 0; BFS.ScriptSettings.WriteValueInt(TransparencySettingName, transparency); } }
I hope this works for you!