using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Collections.Generic;
// Fade all monitors except the primary monitor to black over a two second period
// Adjust
// Based entirely on Thomas Malloch's very brilliant Dim All Monitors Except Primary
// Hope he will forgive the change to K&R style and general clean-up to be more abbreviated
// 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 = "BlackenMonitors_Running";
public static void Run(IntPtr windowHandle) {
//toggle the setting from running to not running, and vice versa
ToggleSetting();
//if we are exiting, exit
if (!IsRunning())
return;
//add all but the primary monitor to the list of monitors that will be dimmed
List<Form> forms = new List<Form>();
uint primaryMonitorID = BFS.Monitor.GetPrimaryMonitorID();
foreach(uint id in BFS.Monitor.GetMonitorIDs()) {
if(id != primaryMonitorID)
forms.Add(new TransparentForm(id));
}
//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 IsRunning() {
return BFS.ScriptSettings.ReadValue(SettingName) == "running";
}
//this function toggles the script settings from running to not running
private static void ToggleSetting() {
BFS.ScriptSettings.WriteValue(SettingName, IsRunning() ? "not" : "running");
}
//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) {
this.MonitorId = monitorId;
this.Transparency = 0m;
const decimal FadeTime = 2.0m; // seconds
this.TransparentIncrement = 2m; // percent
this.FadeWait = (uint)(this.TransparentIncrement * 10m * FadeTime);
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) {
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(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
Rectangle bounds = BFS.Monitor.GetMonitorBoundsByID(this.MonitorId);
BFS.Window.SetSizeAndLocation(this.Handle, bounds.X, bounds.Y, bounds.Width, bounds.Height);
BFS.Window.SetAlwaysOnTop(this.Handle, true);
BFS.Window.SetTransparency(this.Handle, this.Transparency);
//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(IsRunning()) {
// Fade to Black
if (this.Transparency < 100m) {
this.Transparency += this.TransparentIncrement;
BFS.Window.SetTransparency(HandleTHREADSAFE, this.Transparency);
}
//sleep
BFS.General.ThreadWait((this.Transparency < 100m) ? this.FadeWait : 250u);
} else {
if (this.Transparency > 0m) {
// Fade back in
this.Transparency -= this.TransparentIncrement;
BFS.Window.SetTransparency(HandleTHREADSAFE, this.Transparency);
//sleep
BFS.General.ThreadWait((this.Transparency < 100m) ? this.FadeWait : 250u);
} else {
try {
this.Invoke((MethodInvoker) delegate {
this.Close();
});
} catch { //something went wrong, ignore
}
break;
}
}
}
}
catch { }
}
}
}