using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
public static class DisplayFusionFunction
{
public static void Run(IntPtr windowHandle)
{
// Get the user to select the monitors we're going to be swapping to and from
uint monitor1 = 0; // If 0 show monitor selector
uint monitor2 = 0;
// monitor1 = 1; // <--------- Uncomment line and edit to swap only selected monitors
// monitor2 = 3; // <---/
// If any strings below is contained in window name it won't be swaped
string[] windowsToSkip = {}; // { "Sticky Notes", "Other windows to skip" }; // <--- Don't swap list
uint[] ids = BFS.Monitor.GetMonitorIDs(); // If there are only two monitors, just use those
if(ids.Length == 2)
{
monitor1 = ids[0];
monitor2 = ids[1];
}
else if (monitor1 == 0 || monitor2 == 0)
{
int mouseX = BFS.Input.GetMousePositionX(); // Get mouse position to reset it for second monitor select
int mouseY = BFS.Input.GetMousePositionY();
monitor1 = BFS.Monitor.ShowMonitorSelector();
BFS.Input.SetMousePosition(mouseX, mouseY);
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>>();
// Get all visible window handles
IntPtr[] allVisibleWindows = BFS.Window.GetVisibleWindowHandles();
foreach (IntPtr window in allVisibleWindows)
{
if (!IsDisplayFusionWindowOrHiddenExplorerWindow(window, windowsToSkip))
{
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, string[] windowsToSkip)
{
// Ignore any DisplayFusion windows (title bar buttons, etc.)
// Ignore pesky hidden explorer.exe windows
// This improves swap speed
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; // True to skip
}
// Don't move specified windows
foreach (string winName in windowsToSkip)
{
if (BFS.Window.GetText(window).Contains(winName))
{
return true; // True to skip
}
}
return false; // Frue to not skip
}
}