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 uint[] MonitorsToDim = new uint[]
{
1,
3,
};
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 (uint monitor in BFS.Monitor.GetMonitorIDs()) {
foreach(uint monitorToDim in MonitorsToDim){
if(monitor != monitorToDim)
continue;
forms.Add(new TransparentForm(monitor, 30m));
break;
}
}
//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);
}
}
}
}