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!