Processing Ajax...

Title
Close Dialog

Message

Confirm
Close Dialog

Confirm
Close Dialog

Swap All Windows Between Selected Monitors (Keey Z Order)

Description
Swap All Windows Between Selected Monitors (Keey Z Order)
Language
C#.net
Minimum Version
Created By
diceblue96915
Contributors
-
Date Created
Jul 14, 2020
Date Last Modified
Jul 14, 2020

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;
	
	public static void Run(IntPtr windowHandle)
	{          
        // Get the user to select the monitors we're going to be swapping to and from
        // If there are only two monitors, just use those
        uint monitor1 = 0;
        uint monitor2 = 1;
        uint[] ids = BFS.Monitor.GetMonitorIDs();
        if(ids.Length == 2)
        {
            monitor1 = ids[0];
            monitor2 = ids[1];
        }
        else
        {
            monitor1 = BFS.Monitor.ShowMonitorSelector();
            monitor2 = BFS.Monitor.ShowMonitorSelector();
        }
        
        // Get a list of each visible window on our monitors, and throw them in a HashSet
        HashSet<IntPtr> monitor1Windows = new HashSet<IntPtr>(BFS.Window.GetVisibleWindowHandlesByMonitor(monitor1));
        HashSet<IntPtr> monitor2Windows = new HashSet<IntPtr>(BFS.Window.GetVisibleWindowHandlesByMonitor(monitor2));
        
        // Make a stack so we can store the z-order of the windows   
        Stack<Tuple<IntPtr, uint>> windows = new Stack<Tuple<IntPtr, uint>>();
        
        // Enumerate through the monitors, starting with the focused window, and moving down
		for(IntPtr window = BFS.Window.GetFocusedWindow(); ; window = GetWindow(window, GW_HWNDNEXT))
		{
			// Check to see if there are any windows left
			if(window == IntPtr.Zero)
				break;
			
			// If it is a window we should ignore, ignore it
			if(IsDisplayFusionWindowOrHiddenExplorerWindow(window))
				continue;
			
			// Check to see if the window exists in either of our hashsets.
			// If it does, store it with the monitorid it should be moved to
			if(monitor1Windows.Contains(window))
                windows.Push(new Tuple<IntPtr, uint>(window, monitor2));
                
			if(monitor2Windows.Contains(window))
                windows.Push(new Tuple<IntPtr, uint>(window, monitor1));
		}
        
        // Loop through the stack (first in last out) and move the windows
        IntPtr lastWindow = IntPtr.Zero;
        foreach(var tuple in windows)
        {            
            BFS.Window.MoveToMonitor(tuple.Item2, tuple.Item1);
            lastWindow = tuple.Item1;
        }
        
        // Focus the last window. This should be the top of the z-order
        BFS.Window.Focus(lastWindow);
	}
	
	private static bool IsDisplayFusionWindowOrHiddenExplorerWindow(IntPtr window)
	{
        // Ignore any DisplayFusion windows (title bar buttons, etc.)
        // Ignore pesky hidden explorer.exe windows
        string windowClass = BFS.Window.GetClass(window);
        if((windowClass.StartsWith("DF", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("EdgeUiInputTopWndClass", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("EdgeUiInputWndClass", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("NativeHWNDHost", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("ModeInputWnd", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("MetroGhostWindow", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("ImmersiveLauncher", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("ApplicationManager_ImmersiveShellWindow", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("Shell_TrayWnd", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("WorkerW", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("Progman", StringComparison.OrdinalIgnoreCase)) ||
            (windowClass.Equals("SearchPane", StringComparison.OrdinalIgnoreCase)))
        {
            return true;
        }
        
        return false;
	}
}