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?

Confirm

Are you sure?
Save up to 50% on our desktop apps during our Year End Sale!Save up to 50% on our desktop apps during our Year End Sale, including DisplayFusion, ClipboardFusion, FileSeek, LogFusion, TrayStatus, and VoiceBot!Save up to 50% on our desktop apps during our Year End Sale!

Restore Window Positions and Z-Order

Description
This script will restore the window positions with their Z-order that were saved using the "Save Window Positions and Z-Order" script. They are saved by window handle, so if a window was closed and re-opened, it's position will not be restored.
Language
C#.net
Minimum Version
Created By
Thomas Malloch (BFS)
Contributors
-
Date Created
22d ago
Date Last Modified
22d ago

Scripted Function (Macro) Code

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

// 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)]
	private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
	
    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool SetWindowPos(
        IntPtr hWnd,
        IntPtr hWndInsertAfter,
        int X,
        int Y,
        int cx,
        int cy,
        uint uFlags);
	
	//some constants
	const uint GW_HWNDNEXT = 2;
	private const int SWP_NOSIZE = 0x0001;
    private const int SWP_NOMOVE = 0x0002;
    private const int SWP_NOACTIVATE = 0x0010;
    private const int SWP_NOSENDCHANGING = 0x0400;
	
	public static void Run(IntPtr windowHandle)
	{   
		// Get the saved window info
		Dictionary<IntPtr, WindowInfo> savedWindowInfo = new Dictionary<IntPtr, WindowInfo>();
		foreach(WindowInfo info in System.Text.Json.JsonSerializer.Deserialize<List<WindowInfo>>(BFS.ScriptSettings.ReadValue("WindowInfoList")))
		{
			if(savedWindowInfo.ContainsKey(info.HandleAsPtr()))
				continue;
			
			savedWindowInfo.Add(info.HandleAsPtr(), info);
		}
		
		// A list to store the windows
		List<IntPtr> windows = new List<IntPtr>();
		
        // 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;
			
			// we don't care about windows we have no info about
			if(!savedWindowInfo.ContainsKey(window))
				continue;
			
			// Store the window with its info
            windows.Add(window);
		}
        
        // Bubble sort!
		bool swapped;
		for(int i = 0; i < windows.Count - 1; i++)
		{
			swapped = false;
			for(int j = 0; j < windows.Count - i - 1; j++)
			{
				WindowInfo a = savedWindowInfo[windows[j]];
				WindowInfo b = savedWindowInfo[windows[j+1]];
				if(a.ZOrder <= b.ZOrder)
					continue;
				
				swapped = true;
				SwapWindowZOrder(a.HandleAsPtr(), b.HandleAsPtr());
				windows[j] = b.HandleAsPtr();
				windows[j+1] = a.HandleAsPtr();
			}
			
			if(!swapped)
				break;
		}
		
		// Restore state and positions
		foreach(IntPtr window in windows)
		{
			WindowInfo saved = savedWindowInfo[window];
			WindowInfo current = new WindowInfo(window, 0); // we dont care about the zorder here
			if(saved.State != current.State)
			{
				if(saved.State == FormWindowState.Normal)
					BFS.Window.Restore(window);
				if(saved.State == FormWindowState.Minimized)
					BFS.Window.Minimize(window);
				if(saved.State == FormWindowState.Maximized)
					BFS.Window.Maximize(window);
			}
			
			if(saved.Bounds != current.Bounds)
				BFS.Window.SetSizeAndLocation(window, saved.Bounds.X, saved.Bounds.Y, saved.Bounds.Width, saved.Bounds.Height);
		}
	}
	
	// A method to swap two window z orders
	private static void SwapWindowZOrder(IntPtr a, IntPtr b)
	{
		SetWindowPos(a, b, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
		SetWindowPos(b, a, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
	}
	
	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;
	}
	
	public class WindowInfo
	{		
		public long Handle { get; set; }
		public FormWindowState State { get; set; }
		public Rectangle Bounds { get; set; }
		public int ZOrder { get; set; }
		
		// for json deseriealization
		public WindowInfo(){}
		
		public WindowInfo(IntPtr handle, int zOrder)
		{
			this.Handle = handle.ToInt64();
			if(BFS.Window.IsMinimized(handle))
				this.State = FormWindowState.Minimized;			
			else if(BFS.Window.IsMaximized(handle))
				this.State = FormWindowState.Maximized;
			else
				this.State = FormWindowState.Normal;
			
			this.Bounds = BFS.Window.GetBounds(handle);
			this.ZOrder = zOrder;
		}
		
		public IntPtr HandleAsPtr()
		{
			return new IntPtr(this.Handle);
		}
	}
}