I find this beyond frustrating.
I have two extra screens on my laptop at work. I take my laptop and go home, with no extra screens connected. I come back, dock the laptop, and the windows need to be rearranged again.
Is there a way to get windows (or a utility) to keep track of the overall screen configuration (#, size, resolution), and remember where windows were placed, so when the screen configuration matches again, it puts applications BACK where they were?
19 Answers
DISCLAIMER: I'm the creator of this tool.
I've created a little tool to rearrange windows on a traybar icon click. You may compile it from source or ask to have a (portable) binary through the issues link.
It is hosted at Github:
I would be glad to hear from you if you have suggestions.
EDIT: 2018/11/22
It is fully automated now.
7I'm currently using DisplayFusion Pro for window location (not only). I don't know how this works when you disconnect and connect your monitor - I have three always.
I think, that you must close and reopen your apps to be re-arranged.
Edit: This is feature is available only in Pro version. - Information from comments.
homepage of DisplayFusion
3Here is a console application to save and restore window locations and states on a Windows Desktop. To save windows locations run:
winLayout saveto restore windows positions run:
winLayout restorePut these commands into a Desktop shortcut and pin to the Taskbar for convenience.
Disclaimer: I wrote this utility because the other tools on this page didn't work for me.
Caveat: It works for applications, but not explorer windows (at present)
The problem is that Windows applications don't really see multiple monitors. The window manager keeps track of window positions in reference to the Top-Left corner or your main display. I'm not aware of any commercial applications that do, but you could write an application in C# or even VB.NET that could write these values to a file and restore them later, but there would be no "trigger" for it. You'd have to tell the program when to store and retrieve the data manually.
Try this script, written for Excel. It stores the window positions in a sheet and restores them from there. You may have buttons on one of the sheets to run the store and restore macros, or shortcuts to VBS scripts that run the Excel macros, maybe with shortcut keys assigned. That way the Excel workbook can remain minimized. Of course something similar may be written in a compiled program.
Public Declare PtrSafe Function GetWindowPlacement Lib "user32" (ByVal hwnd As LongPtr, lpwndpl As WINDOWPLACEMENT) As Long Public Declare PtrSafe Function SetWindowPlacement Lib "user32" (ByVal hwnd As LongPtr, lpwndpl As WINDOWPLACEMENT) As Long Public Declare PtrSafe Function GetWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal wCmd As Long) As Long Public Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long Public Declare PtrSafe Function IsWindowVisible Lib "user32.dll" (ByVal hwnd As Long) As Boolean Public Declare PtrSafe Function GetParent Lib "user32.dll" (ByVal hwnd As Long) As Long Public Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As LongPtr, ByVal lpString As String, ByVal cch As LongPtr) As Long Public Type POINTAPI X As Long Y As Long End Type Public Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type Public Type WINDOWPLACEMENT Length As Long flags As Long showCmd As Long MinPosition As POINTAPI MaxPosition As POINTAPI rcNormalPosition As RECT End Type Global Const gw_hwndnext = 2 Global Const fwp_startswith = 0 Global Const fwp_contains = 1 Global title As String Global Visible As Boolean Global RowCount Public prog As String Public Sub StoreActiveWindows() Dim hwndapp As Long Dim hwndmax As Long Dim nret As Long Dim WinFrm As WINDOWPLACEMENT Dim RectFrm As RECT PleaseWait.Show vbModeless DoEvents RowCount = 1 hwndmax = findwindow(0&, 0&) Do Until hwndmax = 0 hwndapp = findthiswindow(hwndmax) If hwndapp Then If title <> "CURRENT WINDOWS OPEN" And Visible Then rtn = GetWindowPlacement(hwndapp, WinFrm) RectFrm = WinFrm.rcNormalPosition FrmTop = RectFrm.Top FrmRight = RectFrm.Right FrmLeft = RectFrm.Left FrmBottom = RectFrm.Bottom Workbooks(Filename).Activate Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 1) = title Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 2) = hwndapp Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 3) = FrmTop Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 4) = FrmRight Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 5) = FrmLeft Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 6) = FrmBottom Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 7) = WinFrm.MaxPosition.X Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 8) = WinFrm.MaxPosition.Y Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 9) = WinFrm.MinPosition.X Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 10) = WinFrm.MinPosition.Y Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 11) = WinFrm.showCmd Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 12) = WinFrm.flags Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 13) = WinFrm.Length RowCount = RowCount + 1 End If End If hwndmax = GetWindow(hwndmax, gw_hwndnext) Loop Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 1) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 2) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 3) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 4) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 5) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 6) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 7) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 8) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 9) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 10) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 11) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 12) = "" Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 13) = "" Unload PleaseWait End Sub Public Function findthiswindow(ByVal hwndtopmost As Long) As Long Dim hwndtmp As Long Dim nret As Long Dim titletmp As String 'Get the first window hwndtmp = hwndtopmost If GetParent(hwndtmp) = 0 Then 'Set its visibility If IsWindowVisible(hwndtmp) Then Visible = True Else Visible = False End If 'Get its title titletmp = Space(256) nret = GetWindowText(hwndtmp, titletmp, Len(titletmp)) If nret Then findthiswindow = hwndtmp End If End If If Visible Then title = titletmp & " - Visible" Else title = titletmp & " - Invisible" End If title = titletmp If titletmp <> "" Then 'If title = "SETTINGS" Then HasNoOWner = Not (GetWindow(hwndtmp, 4)) n = 1 'End If If (UCase(Left(title, 15)) = "PROGRAM MANAGER" Or UCase(title) = "SETTINGS") Then n = 1 title = "" findthiswindow = 0 End If End If End Function Sub RestoreWindowsLocations() Dim WinFrm As WINDOWPLACEMENT Dim RectFrm As RECT PleaseWait.Show vbModeless DoEvents Workbooks(Filename).Activate RowCount = 1 Do Until Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 1) = "" hwndapp = Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 2) ' rtn = GetWindowPlacement(hwndapp, WinFrm) WinFrm.rcNormalPosition.Top = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 3)) WinFrm.rcNormalPosition.Right = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 4)) WinFrm.rcNormalPosition.Left = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 5)) WinFrm.rcNormalPosition.Bottom = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 6)) WinFrm.MaxPosition.X = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 7)) WinFrm.MaxPosition.Y = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 8)) WinFrm.MinPosition.X = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 9)) WinFrm.MinPosition.Y = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 10)) WinFrm.showCmd = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 11)) WinFrm.flags = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 12)) WinFrm.Length = CLng(Workbooks(Filename).Sheets("Active Windows").Cells(RowCount, 13)) rtn = SetWindowPlacement(hwndapp, WinFrm) rtn = SetWindowPlacement(hwndapp, WinFrm) RowCount = RowCount + 1 Loop Unload PleaseWait End Sub 3 Alot of windows users had this issue, an application was developed and shared within the windows 7 forums as shown here:
There are instructions on the site which help and it should fix your issue.
2This one was looking promising:
Unfortunately in my case, when saving the layout on 3x 24" 1920x1200 monitors, changing to one laptop 1920x1080, and then going back to three and trying to restore layout, windows didn't really move to other monitors. But maybe for someone else on other setup it will work.
3I fixed the problem with Window Manager from desksoft.com (there is a free trial period (the current price is $10)).
You configure two profiles (docked and undocked) and add a rule for each of the windows you want to place specifically. The profiles can be switched automatically via a "Screen Trigger".
I have a VNC session running full screen on one of two monitors but when I undock the laptop (e.g. to go to a meeting) I want to hide the VNC session without minimizing it. This can be done by moving it to a secondary Windows desktop.
I am not associated with DeskSoft in any way.
I've used Stardock’s Fences before in a similar scenario:
1Fences helps you organize your PC by automatically placing your shortcuts and icons into resizable shaded areas on your desktop called fences. Its many customization features are what make Fences the world's most popular Windows desktop enhancement.