Swap all Windows between Monitors - Windows 10 Bug

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
masgo
Posts: 2
Joined: 25 Sep 2019, 15:51

Swap all Windows between Monitors - Windows 10 Bug

25 Sep 2019, 16:01

I am using two (identical) monitors in a physical setup where one "main" monitor is right in front of me and an "auxiliary" monitor to the side. Sometimes it would be useful to swap the contents of both monitors. I found a script in the old forum called MonSwap from Alan Henager and xenrik which does exactly this.

My problem is, that this script also moves the Windows 10 taskbar from my auxiliary monitor to the main monitor (while keeping the main monitors taskbar where it is). Does anyone know how to make it not touch the taskbar?

Here is the script:

Code: Select all

; MonSwap - Swaps all the application windows from one monitor to another.
; v1.0.1
; Author: Alan Henager
;
; v1.0.1 - xenrik - Updated to use relative screen size when swapping

SetWinDelay, 0 ; This switching should be instant

; Set this key combination to whatever.
^#Numpad0::
SwapAll:
{
  DetectHiddenWindows, Off ; I think this is default, but just for safety's sake...
  WinGet, WinArray, List ; , , , Sharp
  ; Enable the above commented out portion if you are running SharpE

  i := WinArray
  Loop, %i% {
     WinID := WinArray%A_Index%
     WinGetTitle, CurWin, ahk_id %WinID%
     If (CurWin = ) ; For some reason, CurWin <> didn't seem to work.
     {}
     else
     {
        WinGet, IsMin, MinMax, ahk_id %WinID% ; The window will re-locate even if it's minimized
        If (IsMin = -1) {
           WinRestore, ahk_id %WinID%
           SwapMon(WinID)
           WinMinimize, ahk_id %WinID%
        } else {
           SwapMon(WinID)
        }
     }
  }
  return
}

SwapMon(WinID) ; Swaps window with and ID of WinID onto the other monitor
{
  SysGet, Mon1, Monitor, 1
  Mon1Width := Mon1Right - Mon1Left
  Mon1Height := Mon1Bottom - Mon1Top

  SysGet, Mon2, Monitor, 2
  Mon2Width := Mon2Right - Mon2Left
  Mon2Height := Mon2Bottom - Mon2Top

  WinGetPos, WinX, WinY, WinWidth, WinHeight, ahk_id %WinID%
  WinCenter := WinX + (WinWidth / 2)
  if (WinCenter >= Mon1Left and WinCenter <= Mon1Right) {
    
	NewX := (WinX - Mon1Left) / Mon1Width
    NewX := Mon2Left + (Mon2Width * NewX)

    NewWidth := WinWidth / Mon1Width
    NewWidth := Mon2Width * NewWidth

    NewY := (WinY - Mon1Top) / Mon1Height
    NewY := Mon2Top + (Mon2Height * NewY)

    NewHeight := WinHeight / Mon1Height
    NewHeight := Mon2Height * NewHeight
 
 } else {
    NewX := (WinX - Mon2Left) / Mon2Width
    NewX := Mon1Left + (Mon1Width * NewX)

    NewWidth := WinWidth / Mon2Width
    NewWidth := Mon1Width * NewWidth

    NewY := (WinY - Mon2Top) / Mon2Height
    NewY := Mon1Top + (Mon1Height * NewY)

    NewHeight := WinHeight / Mon2Height
    NewHeight := Mon1Height * NewHeight
  }

  WinMove, ahk_id %WinID%, , %NewX%, %NewY%, %NewWidth%, %NewHeight%
  return
}
User avatar
boiler
Posts: 17387
Joined: 21 Dec 2014, 02:44

Re: Swap all Windows between Monitors - Windows 10 Bug

25 Sep 2019, 16:22

Try it with adding these lines right after the WinID := WinArray%A_Index% line:

Code: Select all

	 WinGetClass, ThisClass, ahk_id %WinID%
	 if (ThisClass = "Shell_TrayWnd")
	 	continue
(untested)
masgo
Posts: 2
Joined: 25 Sep 2019, 15:51

Re: Swap all Windows between Monitors - Windows 10 Bug

25 Sep 2019, 17:41

Hey, thanks! While, your code did not work, it was so close that it allowed me (who never did any AHK skripting) to find the right one using WindowSpy. Turns out the taskbar on the second monitor is actually called Shell_SecondaryTrayWnd.

Here is the full code if anyone wants to use it. The hotkey is currently set to Ctrl+Win+Numpad0. This fits great together with AdvancedWindowSnap which uses Ctrl+Win+Numpad+Numpad to resize a window.

Code: Select all

; MonSwap - Swaps all the application windows from one monitor to another.
; v1.0.2
; Author: Alan Henager
;
; v1.0.1 - xenrik - Updated to use relative screen size when swapping
; v1.0.2 - boiler, masgo - exclude Windows 10 secondary monitor taskbar from being swapped

SetWinDelay, 0 ; This switching should be instant

; Set this key combination to whatever.
^#Numpad0::
SwapAll:
{
  DetectHiddenWindows, Off ; I think this is default, but just for safety's sake...
  WinGet, WinArray, List ; , , , Sharp
  ; Enable the above commented out portion if you are running SharpE

  i := WinArray
  Loop, %i% {
     WinID := WinArray%A_Index%
	 WinGetClass, ThisClass, ahk_id %WinID%
	 if (ThisClass = "Shell_SecondaryTrayWnd") ; do not swap the secondary monitor taskbar
	 	continue
     WinGetTitle, CurWin, ahk_id %WinID%
     If (CurWin = ) ; For some reason, CurWin <> didn't seem to work.
     {}
     else
     {
        WinGet, IsMin, MinMax, ahk_id %WinID% ; The window will re-locate even if it's minimized
        If (IsMin = -1) {
           WinRestore, ahk_id %WinID%
           SwapMon(WinID)
           WinMinimize, ahk_id %WinID%
        } else {
           SwapMon(WinID)
        }
     }
  }
  return
}

SwapMon(WinID) ; Swaps window with and ID of WinID onto the other monitor
{
  SysGet, Mon1, Monitor, 1
  Mon1Width := Mon1Right - Mon1Left
  Mon1Height := Mon1Bottom - Mon1Top

  SysGet, Mon2, Monitor, 2
  Mon2Width := Mon2Right - Mon2Left
  Mon2Height := Mon2Bottom - Mon2Top

  WinGetPos, WinX, WinY, WinWidth, WinHeight, ahk_id %WinID%
  WinCenter := WinX + (WinWidth / 2)
  if (WinCenter >= Mon1Left and WinCenter <= Mon1Right) {
    
	NewX := (WinX - Mon1Left) / Mon1Width
    NewX := Mon2Left + (Mon2Width * NewX)

    NewWidth := WinWidth / Mon1Width
    NewWidth := Mon2Width * NewWidth

    NewY := (WinY - Mon1Top) / Mon1Height
    NewY := Mon2Top + (Mon2Height * NewY)

    NewHeight := WinHeight / Mon1Height
    NewHeight := Mon2Height * NewHeight
 
 } else {
    NewX := (WinX - Mon2Left) / Mon2Width
    NewX := Mon1Left + (Mon1Width * NewX)

    NewWidth := WinWidth / Mon2Width
    NewWidth := Mon1Width * NewWidth

    NewY := (WinY - Mon2Top) / Mon2Height
    NewY := Mon1Top + (Mon1Height * NewY)

    NewHeight := WinHeight / Mon2Height
    NewHeight := Mon1Height * NewHeight
  }

  WinMove, ahk_id %WinID%, , %NewX%, %NewY%, %NewWidth%, %NewHeight%
  return
}
AntoineBK
Posts: 27
Joined: 12 Feb 2022, 10:48

Re: Swap all Windows between Monitors - Windows 10 Bug

19 Oct 2022, 08:02

I could not use this script on Windows 11 : It fails to swap some windows only when they are maximized (no problem for windows that are not fullscreen). For example, it does not work with Adobe Acrobat, notepad, Firefox, file explorer when they are maximized. It works fine with a lot of other softwares.

Found a workaround here, which may interest Windows 11 users.
basie
Posts: 1
Joined: 01 Apr 2024, 10:41

Re: Swap all Windows between Monitors - Windows 10 Bug

01 Apr 2024, 10:44

Hello, I have been searching high and low for what I'd assumed was a simple tool to swap windows between my dual monitor set up (they're vertically stacked so a hotkey to quickly swap these windows would be really handy). Evidently it's not as simple as i'd thought! I've seen various AHK requests here but no scripts seem to work for me and this thread seems to be the most recent/relevant. With this script not working (not sure if a Windows update has broken it), does any have any solution (even a non AHK option) that may help me with this? Thanks.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 275 guests