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 running to not running, and vice versa var forms = new List
(); if(IsTransparentWindowRunning()) { //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_TransparentForm_Running"; //this function toggles the script settings from running to not running private static void ToggleSetting() { if(BFS.ScriptSettings.ReadValue(SettingName).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() { return BFS.ScriptSettings.ReadValue(SettingName).Equals("running", StringComparison.Ordinal); } //extend the ApplicationContext class to support opening multiple forms private class MultipleFormApplicationContext : ApplicationContext { internal MultipleFormApplicationContext(List 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; //setup the form load event Load += Form_Load; ResumeLayout(false); } private void Form_Load(object sender, EventArgs e) { BFS.Window.SetAlwaysOnTop(Handle, true); BFS.Window.SetTransparency(Handle, this.Transparency); //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); //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 { Invoke((MethodInvoker) delegate { Close(); }); } catch { //something went wrong, ignore } break; } //sleep for a quarter of a second BFS.General.ThreadWait(250); } } } }