Processing Ajax...

Close Dialog


Close Dialog

Close Dialog

Swap Topmost Windows on Monitors 1 and 2

This script will swap the two topmost windows between monitors 1 and 2. You can edit the monitor ID numbers in the script if your IDs are different than 1 and 2, or if you have more than 2 monitors and want to swap between different ones.
Minimum Version
Created By
Thomas Malloch (BFS)
Date Created
Apr 28, 2015
Date Last Modified
Feb 23, 2022

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);
	const uint GW_HWNDNEXT = 2;

	public static void Run(IntPtr windowHandle)
		//the monitor ids that will contain the windows you want to swap
		//to change the two monitors that this script uses, change these values//
		uint firstMonitor = 1;
		uint secondMonitor = 2;

		//a collection to store our topmost windows
		Dictionary<uint, IntPtr> topMostWindowOnMonitor = new Dictionary<uint, IntPtr>();
		topMostWindowOnMonitor.Add(firstMonitor, IntPtr.Zero);
		topMostWindowOnMonitor.Add(secondMonitor, IntPtr.Zero);

		//store all visable windows in a HashSet for quick access
		// Old version used dictionary with empty value, and meligned the lafck of HashSets //
		HashSet<IntPtr> visableWindows = new HashSet<IntPtr>();
		foreach (IntPtr window in BFS.Window.GetVisibleWindowHandles())

		//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(); (topMostWindowOnMonitor[firstMonitor] == IntPtr.Zero) || (topMostWindowOnMonitor[secondMonitor] == IntPtr.Zero); window = GetWindow(window, GW_HWNDNEXT))
			//check to see if there are no windows left
			if (window == IntPtr.Zero) break;

			//if it isn't a visable window, continue
			if (!visableWindows.Contains(window)) continue ;

			//check if it's a displayfusion window. if so, skip it.
			//this will avoid adding titlebar buttons and other things
			if (BFS.Window.GetClass(window).StartsWith("DF", StringComparison.Ordinal)) 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 (!topMostWindowOnMonitor.ContainsKey(monitor)) continue ;

			//if we already found a top window for this monitor, continue
			if (topMostWindowOnMonitor[monitor] != IntPtr.Zero) continue ;

			//set the top window for this monitor
			topMostWindowOnMonitor[monitor] = window;

		//if we didn't find two topmost windows, do nothing
		if ((topMostWindowOnMonitor[firstMonitor] == IntPtr.Zero) || (topMostWindowOnMonitor[secondMonitor] == IntPtr.Zero)) return;

		//swap the windows
		BFS.Window.MoveToMonitor(firstMonitor, topMostWindowOnMonitor[secondMonitor]);
		BFS.Window.MoveToMonitor(secondMonitor, topMostWindowOnMonitor[firstMonitor]);