Processing Ajax...

Title
Close Dialog

Message

Confirm
Close Dialog

Confirm
Close Dialog

Confirm
Close Dialog

Swap Topmost Windows on Monitors 1 and 2

Description
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.
Language
C#.net
Minimum Version
Created By
Thomas Malloch (BFS)
Contributors
pl0x55036
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())
			visableWindows.Add(window);

		//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]);
	}
}