{ "name": "Fade Unfocused Monitors with Overrides", "language": 0, "code": "using System;\r\nusing System.Drawing;\r\nusing System.Windows.Forms;\r\nusing System.Threading;\r\nusing System.Collections.Generic;\r\nusing System.Runtime.InteropServices;\r\nusing System.Linq;\r\n\r\n// The 'windowHandle' parameter will contain the window handle for the:\r\n// - Active window when run by hotkey\r\n// - Window Location target when run by a Window Location rule\r\n// - TitleBar Button owner when run by a TitleBar Button\r\n// - Jump List owner when run from a Taskbar Jump List\r\n// - Currently focused window if none of these match\r\npublic static class DisplayFusionFunction\r\n{\r\n\t[DllImport(\"user32.dll\", SetLastError = true)]\r\n\tstatic extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);\r\n\t\r\n\t// some constants\r\n\tconst uint GW_HWNDFIRST = 0;\r\n\tconst uint GW_HWNDLAST = 1;\r\n\tconst uint GW_HWNDNEXT = 2;\r\n\tconst uint GW_HWNDPREV = 3;\r\n\t\r\n private static readonly string SettingName = \"ActivlyDimUnfocusedMonitorsWhileWindowIsRunning_TransparentForm_Running\";\r\n \r\n private const int TransparencyPercent = 90; // 40% transparency\r\n private const decimal FadeTimeMS = 500; // 1 second\r\n\t\r\n\t// Modify this list with any window text to override the monitor fading\r\n\tprivate static readonly List MonitorFadeWindowTextOverrides = new List()\r\n\t{\r\n\t\t\"BinaryFortress\",\r\n\t\t\"Binary Fortress\",\r\n\t};\r\n\t\r\n\t// Modify this list with any programs to override the monitor fading\r\n\tprivate static readonly List MonitorFadeProgramOverrides = new List()\r\n\t{\r\n\t\t\"chrome.exe\",\r\n\t};\r\n\t\r\n\tpublic static void Run(IntPtr windowHandle)\r\n\t{\r\n\t\t//toggle the setting from running to not running, and vice versa\r\n\t\tToggleSetting();\r\n\t\t\r\n\t\t//check to see if we should exit\r\n\t\tbool isExiting = !IsTransparentWindowRunning();\r\n\t\t\t\t\r\n\t\t//if we are exiting, exit\r\n\t\tif(isExiting)\r\n\t\t\treturn;\r\n\t\t\t\r\n\t\t//add forms for each monitor except the used one\r\n\t\tList forms = new List();\r\n\t\tforeach(uint id in BFS.Monitor.GetMonitorIDs())\r\n\t\t\tforms.Add(new TransparentForm(TransparencyPercent, FadeTimeMS, id));\r\n\t\t\t\t\r\n\t\ttry\r\n {\r\n //this will open the forms we added to the list by using our custom application context\r\n Application.Run(new MultipleFormApplicationContext(windowHandle, forms));\r\n }\r\n catch (Exception ex)\r\n {\r\n BFS.Dialog.ShowMessageError(ex.Message);\r\n }\r\n\t}\r\n\t\r\n\t//this function toggles the script settings from running to not running\r\n\tprivate static void ToggleSetting()\r\n\t{\r\n\t\tstring status = BFS.ScriptSettings.ReadValue(SettingName);\r\n\t\tif(status.Equals(\"running\", StringComparison.Ordinal))\r\n\t\t\tBFS.ScriptSettings.WriteValue(SettingName, \"not\");\r\n\t\telse\r\n\t\t\tBFS.ScriptSettings.WriteValue(SettingName, \"running\");\r\n\t}\r\n\t\r\n\t//this function allows us to see the currect state of the script\r\n\tprivate static bool IsTransparentWindowRunning()\r\n\t{\r\n\t\tstring status = BFS.ScriptSettings.ReadValue(SettingName);\r\n\t\treturn status.Equals(\"running\", StringComparison.Ordinal);\r\n\t}\r\n\t\r\n\t//extend the ApplicationContext class to support opening multiple forms\r\n\t//this class will also listen for active window changes, and play with the form transparency\r\n\tprivate class MultipleFormApplicationContext : ApplicationContext \r\n\t{\r\n //this is the function signature for the hook callback\r\n private delegate void WinEventProcDelegate(IntPtr hWinEventHook, uint e, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);\r\n\r\n //this function will let us listen to windows events\r\n [DllImport(\"User32.dll\")]\r\n private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventProcDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwflags);\r\n \r\n //this function will let us stop listening to windows events\r\n [DllImport(\"User32.dll\")]\r\n private static extern bool UnhookWinEvent(IntPtr hWinEventHook);\r\n\t\r\n private IntPtr WindowChangedHookHandle;\r\n private WinEventProcDelegate HookDelegateReference;\r\n private List Forms;\r\n private readonly IntPtr SelectedWindow;\r\n private IntPtr CurrentlyFocusedWindow = IntPtr.Zero;\r\n private System.Windows.Forms.Timer WindowFocusPollTimer;\r\n \r\n private const uint EVENT_SYSTEM_FOREGROUND = 0x0003;\r\n\t\tprivate const uint EVENT_SYSTEM_MOVESIZEEND = 0x000B;\r\n\t\t\r\n\t\tinternal MultipleFormApplicationContext(IntPtr selectedWindow, List forms)\r\n\t\t{\r\n this.Forms = forms;\r\n this.SelectedWindow = selectedWindow;\r\n\t\t\r\n //store the reference to the function so .NET doesn't feel like disposing it\r\n this.HookDelegateReference = this.WindowChanged;\r\n \r\n //start the window hook\r\n this.WindowChangedHookHandle = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_MOVESIZEEND, IntPtr.Zero, this.HookDelegateReference, 0, 0, 0);\r\n \r\n\t\t\t//open each of the forms, and add our closing event to them\t\t\r\n\t\t\tforeach(TransparentForm form in forms)\r\n\t\t\t{\r\n\t\t\t\tform.FormClosed += this.OnFormClosed;\r\n\t\t\t\tform.Show();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tBFS.Window.Focus(this.SelectedWindow);\r\n\t\t\tthis.SetFormsTransparency(this.SelectedWindow);\r\n\t\t\t\r\n\t\t\tthis.WindowFocusPollTimer = new System.Windows.Forms.Timer();\r\n\t\t\tthis.WindowFocusPollTimer.Interval = 500;\r\n\t\t\tthis.WindowFocusPollTimer.Tick += this.WindowFocusPollTimer_Tick;\r\n\t\t\tthis.WindowFocusPollTimer.Enabled = true;\r\n\t\t}\r\n\t\t\r\n private void WindowFocusPollTimer_Tick(object sender, EventArgs e)\r\n {\r\n try\r\n {\r\n IntPtr focusedWindow = BFS.Window.GetFocusedWindow();\r\n if(focusedWindow == this.CurrentlyFocusedWindow)\r\n return;\r\n \r\n this.CurrentlyFocusedWindow = focusedWindow;\r\n this.SetFormsTransparency(this.CurrentlyFocusedWindow);\r\n }\r\n catch(Exception ex)\r\n { \r\n }\r\n }\r\n\t\t\r\n\t\t//when all the forms close, make sure to exit the application\r\n\t\tprivate void OnFormClosed(object sender, EventArgs e)\r\n\t\t{\r\n try\r\n {\r\n if(Application.OpenForms.Count != 0)\r\n return;\r\n \r\n //release the window hooks and exit the application\r\n if(this.WindowChangedHookHandle != IntPtr.Zero)\r\n UnhookWinEvent(this.WindowChangedHookHandle);\r\n \r\n this.HookDelegateReference = null;\r\n this.WindowFocusPollTimer.Enabled = false;\r\n this.WindowFocusPollTimer.Dispose();\r\n this.WindowFocusPollTimer = null;\r\n this.ExitThread();\r\n }\r\n catch //ignore any errors\r\n {\r\n }\r\n\t\t}\r\n\t\t\r\n\t\tprivate void SetFormsTransparency(IntPtr focusedWindow)\r\n\t\t{\r\n try\r\n { \r\n\t\t\t\tuint focusedWindowMonitorId = BFS.Monitor.GetMonitorIDByWindow(focusedWindow);\r\n\t\t\t\tvar topmostWindows = GetTopmostWindows();\r\n\t\t\t\t\r\n //loop through each form and toggle the visibility\r\n foreach(TransparentForm form in this.Forms)\r\n {\r\n\t\t\t\t\t// if it's the selected window/monitor, fade in\r\n\t\t\t\t\tif(focusedWindowMonitorId == form.MonitorId)\r\n\t\t\t\t\t{\r\n form.FadeOut();\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t// check our overrides\r\n\t\t\t\t\tif(!topmostWindows.TryGetValue(form.MonitorId, out IntPtr topmostWindow))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tform.FadeIn();\r\n\t\t\t\t\t\tcontinue;\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tstring windowText = BFS.Window.GetText(topmostWindow);\t\t\t\t\t\r\n\t\t\t\t\tif(MonitorFadeWindowTextOverrides.Any(s => windowText.IndexOf(s, StringComparison.OrdinalIgnoreCase) != -1))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tform.FadeOut();\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tstring exe = BFS.Application.GetMainFileByWindow(topmostWindow);\r\n\t\t\t\t\tif(MonitorFadeProgramOverrides.Any(s => exe.IndexOf(s, StringComparison.OrdinalIgnoreCase) != -1))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tform.FadeOut();\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n form.FadeIn();\r\n }\r\n }\r\n catch //ignore any errors\r\n {\r\n }\r\n\t\t}\r\n\t\t\r\n\t\tprivate void WindowChanged(IntPtr hWinEventHook, uint e, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)\r\n\t\t{\r\n try\r\n {\r\n\t\t\t\tif((e != EVENT_SYSTEM_FOREGROUND) && (e != EVENT_SYSTEM_MOVESIZEEND))\r\n\t\t\t\t\treturn;\r\n\t\t\t\t\r\n this.CurrentlyFocusedWindow = hwnd;\r\n this.SetFormsTransparency(hwnd);\r\n }\r\n catch //ignore any errors\r\n {\r\n }\r\n\t\t}\r\n\t\t\r\n\t\tprivate static Dictionary GetTopmostWindows()\r\n\t\t{\r\n\t\t\t// set up the Dictionary to keep the topmost windows\r\n\t\t\tDictionary topmostWindows = new Dictionary();\r\n\t\t\t\r\n\t //get the visible window handles for that monitor\r\n\t HashSet visibleWindows = new HashSet( BFS.Window.GetVisibleWindowHandles() );\r\n\t\t\r\n\t //enumerate through the monitors, starting with the focused window, and moving down\r\n\t\t\t//only enumerate if we havn't found the windows yet\r\n\t\t\tfor(IntPtr window = GetWindow(BFS.Window.GetFocusedWindow(), GW_HWNDLAST); ; window = GetWindow(window, GW_HWNDPREV))\r\n\t\t\t{\r\n\t\t\t\t//check to see if there are no windows left\r\n\t\t\t\tif(window == IntPtr.Zero)\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\t\r\n\t //check to see if the window is visible. if it's not, ignore it\r\n\t\t\t\tif(!visibleWindows.Contains(window))\r\n\t continue;\r\n\t\t\t\t\t\r\n\t\t\t\t//if it is a window we should ignore, ignore it\r\n\t\t\t\tif(IsDisplayFusionWindowOrHiddenExplorerWindow(window))\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t\r\n\t\t\t\t//get the monitor this window is in\r\n\t\t\t\tuint monitorId = BFS.Monitor.GetMonitorIDByWindow(window);\r\n\t\t\t\tif(topmostWindows.ContainsKey(monitorId))\r\n\t\t\t\t\ttopmostWindows[monitorId] = window;\r\n\t\t\t\telse\r\n\t\t\t\t\ttopmostWindows.Add(monitorId, window);\r\n\t\t\t}\r\n\t\t\r\n\t return topmostWindows;\r\n\t\t}\r\n\t\r\n\t\tprivate static bool IsDisplayFusionWindowOrHiddenExplorerWindow(IntPtr window)\r\n\t\t{\r\n\t //ignore any DisplayFusion windows (title bar buttons, etc.)\r\n\t //ignore pesky hidden explorer.exe windows\r\n\t if((BFS.Window.GetClass(window).StartsWith(\"DF\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"EdgeUiInputTopWndClass\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"EdgeUiInputWndClass\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"NativeHWNDHost\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"ModeInputWnd\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"MetroGhostWindow\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"ImmersiveLauncher\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"ApplicationManager_ImmersiveShellWindow\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"Shell_TrayWnd\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"WorkerW\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"Progman\", StringComparison.OrdinalIgnoreCase)) ||\r\n\t (BFS.Window.GetClass(window).Equals(\"SearchPane\", StringComparison.OrdinalIgnoreCase)))\r\n\t {\r\n\t return true;\r\n\t }\r\n\t \r\n\t return false;\r\n\t\t}\r\n\t}\r\n\t\r\n\t//extend the Form class to get the behavior we want\r\n\tprivate class TransparentForm : Form \r\n\t{\r\n\t\t//this will tell us what transparency to use\r\n\t\tprivate readonly decimal Transparency;\r\n\t\t\t\t\r\n\t\t//variables for fading\r\n\t\tprivate const int TimerTickMS = 25;\r\n\t\tprivate decimal FadeRate;\r\n private decimal TargetTransparency;\r\n private readonly decimal FadeTimeMS;\r\n \r\n\t\tprivate System.Windows.Forms.Timer FadeTimer;\r\n\t\t\r\n\t\t//a variable to store the monitor id this form is on\r\n\t\tpublic uint MonitorId { get; private set; }\r\n\t\t\r\n\t\t//the contructor for our class\r\n\t\tpublic TransparentForm(decimal transparency, decimal fadeTimeMS, uint id)\r\n\t\t{\t\t\r\n\t\t\tthis.Transparency = transparency;\r\n\t\t\tthis.FadeTimeMS = fadeTimeMS;\r\n\t\t\tthis.MonitorId = id;\r\n\t\t\t\r\n\t\t\tthis.SuspendLayout();\r\n\t\t\t\r\n\t\t\t//setup the layout of this form\r\n\t\t\tthis.BackColor = Color.Black;\r\n\t\t\tthis.FormBorderStyle = FormBorderStyle.None;\r\n\t\t\tthis.ShowInTaskbar = false;\r\n\t\t\t\r\n\t\t\tthis.FadeTimer = new System.Windows.Forms.Timer();\r\n\t\t\tthis.FadeTimer.Interval = TimerTickMS;\r\n\t\t\tthis.FadeTimer.Tick += this.FadeTimer_Tick;\r\n\t\t\tthis.FadeTimer.Enabled = false;\r\n\t\t\t\r\n\t\t\t//setup the form load event\r\n\t\t\tthis.Load += Form_Load;\t\t\t\t\t\t\r\n\t\t\t\r\n\t\t\tthis.ResumeLayout(false);\r\n\t\t}\r\n\t\t\r\n\t\tprotected override void Dispose(bool disposing)\r\n\t\t{\r\n this.FadeTimer.Enabled = false;\r\n this.FadeTimer.Dispose();\r\n this.FadeTimer = null;\r\n base.Dispose(disposing);\r\n\t\t}\r\n\t\t\r\n\t\tprivate void Form_Load(object sender, EventArgs e)\r\n\t\t{\r\n\t\t\t//add a windows style to the current style that will\r\n\t\t\t//tell this window to ignore user input\r\n\t\t\tuint style = (uint)BFS.Window.GetWindowStyleEx(this.Handle);\r\n\t\t\tBFS.Window.SetWindowStyleEx((BFS.WindowEnum.WindowStyleEx)(style | (uint)BFS.WindowEnum.WindowStyleEx.WS_EX_TRANSPARENT | (uint)BFS.WindowEnum.WindowStyleEx.WS_EX_LAYERED), this.Handle);\r\n\t\t\tBFS.Window.SetTransparency(this.Handle, 0);\r\n\t\t\t\r\n\t\t\t//set the form's bounds to the monitor\r\n\t\t\tthis.Bounds = BFS.Monitor.GetMonitorBoundsByID(this.MonitorId);\r\n\t\t\t\r\n\t\t\t//set topmost\r\n\t\t\tBFS.Window.SetAlwaysOnTop(this.Handle, true);\r\n\t\t\t\r\n\t\t\t//start up a thread to listen for an exit event\r\n\t\t\tnew Thread(new ThreadStart(ExitListener)).Start();\r\n\t\t}\r\n\t\t\r\n\t\tpublic void FadeIn()\r\n\t\t{\r\n this.FadeTimer.Enabled = false;\r\n\t\t\tthis.FadeRate = this.Transparency * TimerTickMS / this.FadeTimeMS;\r\n\t\t\tif(this.FadeRate < 1)\r\n this.FadeRate = 1;\r\n\t\t\t\r\n\t\t\tthis.FadeTimer.Enabled = true;\r\n\t\t}\r\n\t\t\r\n\t\tpublic void FadeOut()\r\n\t\t{\r\n this.FadeTimer.Enabled = false;\r\n\t\t\tthis.FadeRate = this.Transparency * TimerTickMS / this.FadeTimeMS * -1;\r\n\t\t\tif(this.FadeRate > -1)\r\n this.FadeRate = -1;\r\n\t\t\t\r\n\t\t\tthis.FadeTimer.Enabled = true;\r\n\t\t}\r\n\t\t\r\n\t\tprivate void FadeTimer_Tick(object sender, EventArgs e)\r\n\t\t{\r\n try\r\n {\r\n bool isStoppingTimer = false;\r\n decimal transparency = BFS.Window.GetTransparency(this.Handle);\r\n transparency += this.FadeRate;\r\n if((this.FadeRate > 0) && (transparency >= this.Transparency))\r\n {\r\n transparency = this.Transparency;\r\n isStoppingTimer = true;\r\n }\r\n \r\n if((this.FadeRate < 0) && (transparency <= 0))\r\n {\r\n transparency = 0;\r\n isStoppingTimer = true;\r\n }\r\n \r\n BFS.Window.SetTransparency(this.Handle, transparency);\r\n if(isStoppingTimer)\r\n this.FadeTimer.Enabled = false;\r\n }\r\n catch(Exception ex)\r\n { \r\n }\r\n\t\t}\r\n\t\t\r\n\t\tprivate void ExitListener()\r\n\t\t{\r\n try\r\n {\r\n while(true)\r\n {\r\n //if we should close, tell the main thread to close the form\r\n if(!IsTransparentWindowRunning())\r\n {\r\n try\r\n {\r\n this.Invoke((MethodInvoker) delegate\r\n {\r\n this.Close();\r\n });\r\n }\r\n catch //something went wrong, ignore\r\n {\r\n }\r\n \r\n break;\r\n }\r\n \r\n //sleep for a quarter of a second\r\n BFS.General.ThreadWait(500);\r\n }\r\n\t\t\t}\r\n catch //ignore errors\r\n {\r\n }\r\n\t\t}\r\n\t}\r\n}", "description": "", "references": "Microsoft.VisualBasic.Core.dll|Microsoft.Win32.Primitives.dll|Microsoft.Win32.Registry.dll|netstandard.dll|Newtonsoft.Json.dll|System.Collections.Concurrent.dll|System.Collections.dll|System.Collections.Immutable.dll|System.Collections.NonGeneric.dll|System.Collections.Specialized.dll|System.ComponentModel.Primitives.dll|System.ComponentModel.TypeConverter.dll|System.Console.dll|System.Core.dll|System.Data.dll|System.Diagnostics.Process.dll|System.dll|System.Drawing.Common.dll|System.Drawing.dll|System.Drawing.Primitives.dll|System.IO.Compression.dll|System.IO.dll|System.IO.FileSystem.Watcher.dll|System.Linq.dll|System.Linq.Expressions.dll|System.Linq.Parallel.dll|System.Linq.Queryable.dll|System.Management.dll|System.Net.dll|System.Net.Primitives.dll|System.Net.Requests.dll|System.Net.WebClient.dll|System.Net.WebHeaderCollection.dll|System.Private.CoreLib.dll|System.Private.Uri.dll|System.Private.Xml.dll|System.Runtime.dll|System.Runtime.InteropServices.dll|System.Runtime.Serialization.Formatters.dll|System.Security.Cryptography.Algorithms.dll|System.Security.Cryptography.Csp.dll|System.Security.Cryptography.dll|System.Security.Cryptography.Primitives.dll|System.Text.Json.dll|System.Text.RegularExpressions.dll|System.Threading.dll|System.Threading.Tasks.dll|System.Threading.Tasks.Parallel.dll|System.Web.dll|System.Web.HttpUtility.dll|System.Windows.Extensions.dll|System.Windows.Forms.dll|System.Windows.Forms.Primitives.dll|System.Xml.dll" }