Processing Ajax...

Title

Message

Confirm

Confirm

Confirm

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure you want to delete this item?

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;
	}
}