Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

DockWin (Store/Recall window positions)


  • Please log in to reply
31 replies to this topic
Lauri Palokangas
  • Members
  • 2 posts
  • Last active: Feb 06 2015 06:30 AM
  • Joined: 08 Dec 2014

Hey, this is a great app! I wonder why Spotify client doesn't resize and align per configuration stored in WinPos?



ozzii
  • Members
  • 167 posts
  • Last active: Oct 30 2015 04:54 PM
  • Joined: 23 Mar 2011
Can someone change it for adding just the windows under the mouse? This will be much useful for me in that way.

Lauri Palokangas
  • Members
  • 2 posts
  • Last active: Feb 06 2015 06:30 AM
  • Joined: 08 Dec 2014

Hi guys, I thought you might like the tweak I did to the script to deal with maximized windows. Whenever positions are stored, information of their maximized status is saved along. When restoring window positions, windows in question are maximized to whatever display they reside. I didn't yet try hard enough to figure out a way to maximize them to their original screen.

;DockWin v0.3 - Save and Restore window positions when docking/undocking (using hotkeys)
; Paul Troiano, 6/2014
;
; Hotkeys: ^ = Control; ! = Alt; + = Shift; # = Windows key; * = Wildcard;
;          & = Combo keys; Others include ~, $, UP (see "Hotkeys" in Help)

;#InstallKeybdHook
#SingleInstance, Force
SetTitleMatchMode, 2		; 2: A window's title can contain WinTitle anywhere inside it to be a match. 
SetTitleMatchMode, Fast		;Fast is default
DetectHiddenWindows, off	;Off is default
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
CrLf=`r`n
FileName:="WinPos.txt"



;Win-0 (Restore window positions from file)
#0::
  WinGetActiveTitle, SavedActiveWindow
  ParmVals:="Title x y height width maximized"
  SectionToFind:= SectionHeader()
  SectionFound:= 0
 
  Loop, Read, %FileName%
  {
    if !SectionFound
    {
      ;Read through file until correction section found
      If (A_LoopReadLine<>SectionToFind) 
	Continue
    }	  

		;Exit if another section reached
		If ( SectionFound and SubStr(A_LoopReadLine,1,8)="SECTION:")
			Break

                SectionFound:=1
		Win_Title:="", Win_x:=0, Win_y:=0, Win_width:=0, Win_height:=0, Win_maximized:=0

		Loop, Parse, A_LoopReadLine, CSV 
		{
			EqualPos:=InStr(A_LoopField,"=")
			Var:=SubStr(A_LoopField,1,EqualPos-1)
			Val:=SubStr(A_LoopField,EqualPos+1)
			IfInString, ParmVals, %Var%
			{
				;Remove any surrounding double quotes (")
				If (SubStr(Val,1,1)=Chr(34)) 
				{
					StringMid, Val, Val, 2, StrLen(Val)-2
				}
				Win_%Var%:=Val  
			}
		}

		If ( (Win_maximized = 1) and WinExist(Win_Title) )
		{	
			WinRestore
			WinActivate
			WinMaximize, A
		} Else If ( (StrLen(Win_Title) > 0) and WinExist(Win_Title) )
		{	
			WinRestore
			WinActivate
			WinMove, A,,%Win_x%,%Win_y%,%Win_width%,%Win_height%
		}

  }

  if !SectionFound
  {
    msgbox,,Dock Windows, Section does not exist in %FileName% `nLooking for: %SectionToFind%`n`nTo save a new section, use Win-Shift-0 (zero key above letter P on keyboard)
  }

  ;Restore window that was active at beginning of script
  WinActivate, %SavedActiveWindow%
RETURN


;Win-Shift-0 (Save current windows to file)
#+0::

 MsgBox, 4,Dock Windows,Save window positions?
 IfMsgBox, NO, Return

 WinGetActiveTitle, SavedActiveWindow

 file := FileOpen(FileName, "a")
 if !IsObject(file)
 {
	MsgBox, Can't open "%FileName%" for writing.
	Return
 }

  line:= SectionHeader() . CrLf
  file.Write(line)

  ; Loop through all windows on the entire system
  WinGet, id, list,,, Program Manager
  Loop, %id%
  {
    this_id := id%A_Index%
    WinActivate, ahk_id %this_id%
    WinGetPos, x, y, Width, Height, A ;Wintitle
    WinGetClass, this_class, ahk_id %this_id%
    WinGetTitle, this_title, ahk_id %this_id%
    WinGet, Win_Maximized, minmax, %this_title%

	if ( (StrLen(this_title)>0) and (this_title<>"Start") )
	{
		line=Title="%this_title%"`,x=%x%`,y=%y%`,width=%width%`,height=%height%`,maximized=%Win_maximized%`r`n
		file.Write(line)
   	}
  }

  file.write(CrLf)  ;Add blank line after section
  file.Close()

  ;Restore active window
  WinActivate, %SavedActiveWindow%
RETURN

; -------

;Create standardized section header for later retrieval
SectionHeader()
{
	SysGet, MonitorCount, MonitorCount
	SysGet, MonitorPrimary, MonitorPrimary
	line=SECTION: Monitors=%MonitorCount%,MonitorPrimary=%MonitorPrimary%

        WinGetPos, x, y, Width, Height, Program Manager
	line:= line . "; Desktop size:" . x . "," . y . "," . width . "," . height

	Return %line%
}

;<EOF>


Michael_A
  • Members
  • 1 posts
  • Last active: Mar 05 2015 12:28 AM
  • Joined: 11 Feb 2015

I just made a small extension to this, which supports multiple windows of the same type. The way it does this is by keeping a list of which windows have been moved already, so that each window is moved only once. This means windows should be listed from most specific to most general in WinPos.txt.  

 

Suppose I want to keep open three Chrome windows, one with a personal gmail, one with Evernote, and the other with a browser. All three will match "Google Chrome," but if I position the first two windows, they will be fixed in place.  My WinPos.txt file might contain the lines: 

 

Title="[email protected]",x=-3072,y=1728,width=1536,height=1728,maximized=0
Title="Calendar",x=-1536,y=1728,width=1536,height=1728,maximized=0
Title="Google Chrome",x=1920,y=0,width=3840,height=2088,maximized=0
 
;DockWin v0.4 - Save and Restore window positions when docking/undocking (using hotkeys)
; Paul Troiano, 6/2014
; Michael Abrahams, 2/2015
;
; Hotkeys: ^ = Control; ! = Alt; + = Shift; # = Windows key; * = Wildcard;
;          & = Combo keys; Others include ~, $, UP (see "Hotkeys" in Help)

;#InstallKeybdHook
;#SingleInstance, Force
SetTitleMatchMode, 2 ; 2: A window's title can contain WinTitle anywhere inside it to be a match. 
SetTitleMatchMode, Fast ;Fast is default
DetectHiddenWindows, off ;Off is default
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
CrLf=`r`n
FileName:="WinPos.txt"



;Win-0 (Restore window positions from file)
#0:: 
WinGetActiveTitle, SavedActiveWindow
ParmVals:="Title x y height width maximized"
SectionToFind:= SectionHeader()
SectionFound:= 0

;List currently open windows to prevent matching more than once
WinGet, handle_list, List,,,


Loop, Read, %FileName%
{
if !SectionFound
{
 ;Read through file until correction section found
 If (A_LoopReadLine<>SectionToFind) 
Continue
} 

;Exit if another section reached
If ( SectionFound and SubStr(A_LoopReadLine,1,8)="SECTION:")
Break


SectionFound:=1
Win_Title:="", Win_x:=0, Win_y:=0, Win_width:=0, Win_height:=0, Win_maximized:=0

;;Parse the elements in the CSV to extract recorded data
Loop, Parse, A_LoopReadLine, CSV 
{
EqualPos:=InStr(A_LoopField,"=")
Var:=SubStr(A_LoopField,1,EqualPos-1)
Val:=SubStr(A_LoopField,EqualPos+1)
IfInString, ParmVals, %Var%
{
;Remove any surrounding double quotes (")
If (SubStr(Val,1,1)=Chr(34)) 
{
StringMid, Val, Val, 2, StrLen(Val)-2
}
Win_%Var%:=Val  
}
}

;Seems to be an iteration problem...
if (Win_Title = "")
continue


;Make sure we're matching something new each time we move a window
WinGet, matches, list, %Win_Title%,,,
m_id := ""

Loop, %matches%
{
cid := matches%A_Index% 
Loop, %handle_list%
{
h := handle_list%A_Index%
if (h = cid)
{
m_id := cid
handle_list%A_Index% := 0
break 2
}
} 
}


If ((Win_maximized = 1) and (m_id not = ""))
{ 
WinRestore, ahk_id %m_id%
WinActivate, ahk_id %m_id%
WinMaximize, ahk_id %m_id%
WinGetTitle, t, ahk_id %m_id%
} Else If ( (StrLen(Win_Title) > 0) and (m_id not = "") )
{ 
WinRestore, ahk_id %m_id%
WinActivate, ahk_id %m_id%
WinGetTitle, t, ahk_id %m_id%
WinMove, A,,%Win_x%,%Win_y%,%Win_width%,%Win_height%
}

}

if !SectionFound
{
msgbox,,Dock Windows, Section does not exist in %FileName% `nLooking for: %SectionToFind%`n`nTo save a new section, use Win-Shift-0 (zero key above letter P on keyboard)
}

;Restore window that was active at beginning of script
WinActivate, %SavedActiveWindow%

RETURN


;Win-Shift-0 (Save current windows to file)
#+0::

 MsgBox, 4,Dock Windows,Save window positions?
 IfMsgBox, NO, Return

 WinGetActiveTitle, SavedActiveWindow

 file := FileOpen(FileName, "a")
 if !IsObject(file)
 {
MsgBox, Can't open "%FileName%" for writing.
Return
 }

  line:= SectionHeader() . CrLf
  file.Write(line)

  ; Loop through all windows on the entire system
  WinGet, id, list,,, Program Manager
  Loop, %id%
  {
    this_id := id%A_Index%
    WinActivate, ahk_id %this_id%
    WinGetPos, x, y, Width, Height, A ;Wintitle
    WinGetClass, this_class, ahk_id %this_id%
    WinGetTitle, this_title, ahk_id %this_id%
    WinGet, Win_Maximized, minmax, %this_title%

if ( (StrLen(this_title)>0) and (this_title<>"Start") )
{
line=Title="%this_title%"`,x=%x%`,y=%y%`,width=%width%`,height=%height%`,maximized=%Win_maximized%`r`n
file.Write(line)
    }
  }

  file.write(CrLf)  ;Add blank line after section
  file.Close()

  ;Restore active window
  WinActivate, %SavedActiveWindow%
RETURN

; -------

;Create standardized section header for later retrieval
SectionHeader()
{
SysGet, MonitorCount, MonitorCount
SysGet, MonitorPrimary, MonitorPrimary
line=SECTION: Monitors=%MonitorCount%,MonitorPrimary=%MonitorPrimary%

        WinGetPos, x, y, Width, Height, Program Manager
line:= line . "; Desktop size:" . x . "," . y . "," . width . "," . height

Return %line%
}

;<EOF>


AutoPaul
  • Members
  • 10 posts
  • Last active: Feb 26 2015 09:36 PM
  • Joined: 05 Jul 2014

Thanks guys. Lauri, wouldn't the original code put any window back into place where it was when it was recorded even if it was maximized? As long as it is the same size and in the same place, I didn't care if it was maximized or not. Clearly you have a different preference here.

 

 

I just made a small extension to this, which supports multiple windows of the same type. The way it does this is by keeping a list of which windows have been moved already, so that each window is moved only once. This means windows should be listed from most specific to most general in WinPos.txt.  

 

 

At almost the same time I did something similar. My approach was to add 'ExcludeText' to the WinExist row of the code. You just need to manually edit WinPos.txt and add the "ExcludeText" to any line where you want it. I'm assuming your approach is working fine and so I won't bother posting my code. If some one wants it, just let me know and I can post it.

 

Here's an example of what the new version of WinPos.txt looks like using the version that uses ExcludeText:

SECTION: Monitors=2,MonitorPrimary=1; Desktop size:-1920,0,3840,1080
Title="Calendar - Paul",x=-1921,y=0,width=871,height=1080
Title="[email protected]",x=-1056,y=0,width=1055,height=1080,ExcludeTitle="Calendar"

The first will resize my Outlook calendar window, and then the second will resize my Outlook mailbox (no matter which folder is current active - like Inbox or Deleted Items for example).



neodata686
  • Members
  • 2 posts
  • Last active: Mar 18 2015 07:59 PM
  • Joined: 02 Mar 2015

Great script! I can't seem to get the windows to maximize though. Whenever the script is run it sets all the windows slightly larger than what they would be maximized so they overlap to the next monitor. I have to manually hit the maximize button on each maximized window each time I run the script. Kind of defeats the purpose if I have to click on each window anyway. Saving the maximized state doesn't seem to correct this issue. Any ideas? 



ebeffel
  • Members
  • 1 posts
  • Last active: Mar 11 2015 02:02 AM
  • Joined: 11 Mar 2015

Newbe question: Has anyone modified this script to open windows that aren't open, before positioning them? Is there a good way to create a script that automatically opens and positions five windows of three programs (Word, Acrobat, Outlook)?



bear1231
  • Members
  • 2 posts
  • Last active: Mar 25 2015 01:21 PM
  • Joined: 11 Mar 2015

I have a Laptop docked to 2 external screens which is undocked often and I´ve been searching for a tool like this a long time.

Thanks for this awesome, compact script, it perfectly fits my needs.

 

But I have one question: Is there a way to handle Windows folder windows?

As for Win7 the WinPos.txt only contains the current folder name as a title.

So there´s currently no way of using it in general for folder windows (explorer, right?



neodata686
  • Members
  • 2 posts
  • Last active: Mar 18 2015 07:59 PM
  • Joined: 02 Mar 2015

So no answers to my question? Currently none of these scripts maximize the screens in Windows 8.1. They bring the window roughly back to where it was but they overlap onto each monitor. So not usable for me yet until we can truly maximize the windows...



Skrell
  • Members
  • 384 posts
  • Last active: Jul 07 2016 05:03 PM
  • Joined: 23 Aug 2011

So no answers to my question? Currently none of these scripts maximize the screens in Windows 8.1. They bring the window roughly back to where it was but they overlap onto each monitor. So not usable for me yet until we can truly maximize the windows...

So you're saying that the code WinMaximize, A doesn't work in 8.1?  Or are you using 2 displays and the problem is with 2 displays NONE of the windows will restore to a maximized state to the CORRECT monitor?  You tried Lauri Palokangas's version right?



bear1231
  • Members
  • 2 posts
  • Last active: Mar 25 2015 01:21 PM
  • Joined: 11 Mar 2015

WinMaximize works for me (also using Win 8.1).
 
In Lauri Palokangas version, the window will maximize on the screen it is currently on.
You have to add the move command in the "if maximized=1" branch:
 

 
Old:

If ((Win_maximized = 1) and (m_id not = ""))
{ 
   WinRestore, ahk_id %m_id%
   WinActivate, ahk_id %m_id%
   WinMaximize, ahk_id %m_id%
   WinGetTitle, t, ahk_id %m_id%
} Else If ( (StrLen(Win_Title) > 0) and (m_id not = "") )
{ 
   WinRestore, ahk_id %m_id%
   WinActivate, ahk_id %m_id%
   WinGetTitle, t, ahk_id %m_id%
   WinMove, A,,%Win_x%,%Win_y%,%Win_width%,%Win_height%
}

 
Changed:

If ((Win_maximized = 1) and (m_id not = ""))
{ 
   WinRestore, ahk_id %m_id%
   WinActivate, ahk_id %m_id%
   WinMove, A,,%Win_x%,%Win_y%,%Win_width%,%Win_height%
   WinMaximize, ahk_id %m_id%
   WinGetTitle, t, ahk_id %m_id%
} Else If ( (StrLen(Win_Title) > 0) and (m_id not = "") )
{ 
   WinRestore, ahk_id %m_id%
   WinActivate, ahk_id %m_id%
   WinGetTitle, t, ahk_id %m_id%
   WinMove, A,,%Win_x%,%Win_y%,%Win_width%,%Win_height%
}

 
or:

If ( (StrLen(Win_Title) > 0) and (m_id not = "") ){ 
   WinRestore, ahk_id %m_id%
   WinActivate, ahk_id %m_id%
   WinMove, A,,%Win_x%,%Win_y%,%Win_width%,%Win_height%

   If (Win_maximized = 1){ 
      WinMaximize, ahk_id %m_id%
   }
   WinGetTitle, t, ahk_id %m_id%
}


Skrell
  • Members
  • 384 posts
  • Last active: Jul 07 2016 05:03 PM
  • Joined: 23 Aug 2011

bear1231, why did you post 2 versions of a solution ?  Would either of your solutions go in the same place as the "old" code?  



tmoffett
  • Members
  • 1 posts
  • Last active: Apr 08 2015 02:44 PM
  • Joined: 31 Mar 2015

This is great stuff.  Thanks guys.



Muhd
  • Members
  • 1 posts
  • Last active: Dec 09 2015 04:39 AM
  • Joined: 03 Jun 2015

This script messes up my desktop by restoring all my minimized windows. Is there a way to modify it to ignore minimized windows?



xneuromancer
  • Members
  • 1 posts
  • Last active: Jun 19 2015 04:28 PM
  • Joined: 16 Jun 2015

First of all, thanks so much for this script.  This is going to be incredibly helpful.

 

This script messes up my desktop by restoring all my minimized windows. Is there a way to modify it to ignore minimized windows?

 

I also wanted to raise the question around minimized windows.  Is there a method to update the script to save window positions of minimized windows and upon restore, keep the windows minimized?