Processing Ajax...

Title
Close Dialog

Message

Confirm
Close Dialog

Confirm
Close Dialog

Minimize Topmost Windows on Non-Current Monitors

Description
This function will minimize the topmost windows on all monitors except the monitor that the mouse cursor is currently on.
Language
C#.net
Minimum Version
Created By
Thomas Malloch (BFS)
Contributors
-
Date Created
Apr 20, 2018
Date Last Modified
May 8, 2018

Scripted Function (Macro) Code

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;

// 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
{
	[DllImport("user32.dll", SetLastError = true)]
	static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
	
	//some constants
	const uint GW_HWNDNEXT = 2;
    private static readonly string ToggleTopmostWindowProperty = "ToggleTopmostWindowMinimized_Property";
    private static readonly string ToggleTopmostWindowMode = "ToggleTopmostWindowMinimized_Setting";

	public static void Run(IntPtr windowHandle)
	{
        //check to see if we've run this script before. if we have, restore the windows
        if(BFS.ScriptSettings.ReadValueBool(ToggleTopmostWindowMode))
        {
            //loop through each window, restore the ones we minimized before, and remove the property from them
            foreach(IntPtr window in BFS.Window.GetAllWindowHandles())
            {
                IntPtr property = BFS.Window.GetWindowProperty(window, ToggleTopmostWindowProperty);
                if(property == IntPtr.Zero)
                    continue;
                    
                BFS.Window.Restore(window);
                BFS.Window.RemoveWindowProperty(window, ToggleTopmostWindowProperty);
            }
            
            //set the script setting so our next run will minimize the windows
            BFS.ScriptSettings.WriteValueBool(ToggleTopmostWindowMode, false);
        }
        else //minimize topmost windows mode
        {
            //get the monitor that the mouse is on
            uint mouseMonitorId = BFS.Monitor.GetMonitorIDByXY(BFS.Input.GetMousePositionX(), BFS.Input.GetMousePositionY());
            
            //loop through all of the monitors
            foreach(uint id in BFS.Monitor.GetMonitorIDs())
            {
                //skip the monitor that the mouse is on
                if(id == mouseMonitorId)
                    continue;
                    
                //get the topmost window on that monitor
                IntPtr topmost = GetTopmostWindowOnMonitor(id);
                if(topmost == IntPtr.Zero)
                    continue;
                    
                //minimize the window
                BFS.Window.Minimize(topmost);
                
                //set a property so we know which window to restore after
                BFS.Window.SetWindowProperty(topmost, ToggleTopmostWindowProperty, new IntPtr(1));   
            }
            
            //set the script setting so our next run will restore the windows
            BFS.ScriptSettings.WriteValueBool(ToggleTopmostWindowMode, true);
		}
	}
	
	private static IntPtr GetTopmostWindowOnMonitor(uint id)
	{
        //get the visible window handles for that monitor
        HashSet<IntPtr> visibleWindows = new HashSet<IntPtr>( BFS.Window.GetVisibleWindowHandlesByMonitor(id) );
	
        //enumerate through the monitors, starting with the focused window, and moving down
		//only enumerate if we havn't found the windows yet
		for(IntPtr window = BFS.Window.GetFocusedWindow(); ; window = GetWindow(window, GW_HWNDNEXT))
		{
			//check to see if there are no windows left
			if(window == IntPtr.Zero)
				break;
				
            //check to see if the window is visible. if it's not, ignore it
			if(!visibleWindows.Contains(window))
                continue;
				
			//if it is a window we should ignore, ignore it
			if(IsDisplayFusionWindowOrHiddenExplorerWindow(window))
				continue;
			
			//get the monitor this window is in
			uint monitor = BFS.Monitor.GetMonitorIDByWindow(window);
			
			//if the monitor isn't in our collection, get the next window
			if(id != monitor)
				continue;
				
			return window;
		}
	
        //return IntPtr.Zero if we didn't find anything
        return IntPtr.Zero;
	}
	
	private static bool IsDisplayFusionWindowOrHiddenExplorerWindow(IntPtr window)
	{
        //ignore any DisplayFusion windows (title bar buttons, etc.)
        //ignore pesky hidden explorer.exe windows
        if((BFS.Window.GetClass(window).StartsWith("DF", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("EdgeUiInputTopWndClass", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("EdgeUiInputWndClass", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("NativeHWNDHost", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("ModeInputWnd", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("MetroGhostWindow", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("ImmersiveLauncher", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("ApplicationManager_ImmersiveShellWindow", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("Shell_TrayWnd", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("WorkerW", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("Progman", StringComparison.OrdinalIgnoreCase)) ||
            (BFS.Window.GetClass(window).Equals("SearchPane", StringComparison.OrdinalIgnoreCase)))
        {
            return true;
        }
        
        return false;
	}
}