Code: Select all
#NoEnv
#Persistent
#SingleInstance force
SetWorkingDir %A_ScriptDir%
onexit, exitSub
/*
author : Chef
link : http://ahkscript.org/boards/viewtopic.php?f=6&t=894
date : 14 December 2013
description
save and restore window state and position, with a workaround to save snap on windows Vista+.
credit to Lexikos
known bugs
set non-snap size - snap to egde - maximize - minimize - exit ===> wont save snap position.
*/
iniRead,winPos,settings.ini,General,winPos, %a_space%
gui,main: +hWNDhMain +resize +alwaysOnTop
gui,main: color, gray
gui,main: add, text, w300 h200
gui,main: show,hide,win_pos
default_pos := win_placementGet( hMain )
pos := winPos = "" ? default_pos : winPos
win_placementSet( hMain, pos )
return
mainGuiClose:
ExitApp
mainGuiSize:
return
exitSub:
iniWrite, % win_placementGet( hMain ),settings.ini,General,winPos
exitapp
return
win_placementGet( hwnd, options:="saveSnap" )
{
/*
options
saveSnap
known issues
minimized window is restored and minimized again to get its size and position before it was minimized.
this is a necessary workaround as "GetWindowPlacement" can't detect snap to edge on Vista+.
*/
dhw := A_DetectHiddenWindows
DetectHiddenWindows, On
varSetCapacity( wp, 44, 0 )
numPut( 44,wp )
dllCall( "GetWindowPlacement", "uint", hwnd, "uint", &wp )
_x := NumGet( wp, 28, "int" )
_y := NumGet( wp, 32, "int" )
_w := NumGet( wp, 36, "int" ) - _x
_h := NumGet( wp, 40, "int" ) - _y
state := numGet( wp, 8, "UInt" )
if state in 2,3 ; minimized or maximized
{
if ( state = 3 ) ; maximized, state stays 3 ( maximized ), we use GetWindowPlacement dimentions and return.
x := _x, y := _y, w := _w, h := _h
else ; minimized
{
winRestore, ahk_id %hwnd% ; restore
WinGet, minMax, minMax, ahk_id %hwnd% ; get minMax again
ifequal,minMax,0,WinGetPos, x, y, w, h, ahk_id %hwnd% ; not maximized, state stays 1 ( normal ) and we get dimensions
else state := 3, x := _x, y := _y, w := _w, h := _h ; maximized, set state to 3 ( maximized ), we use GetWindowPlacement dimentions and return.
winMinimize, ahk_id %hwnd% ; minimize it again
}
}
else WinGetPos, x, y, w, h, ahk_id %hwnd% ; neither minimized nor maximized, get the size
WinGetPos tbx, tby, tbw, tbh, ahk_class Shell_TrayWnd ; if using winGetPos dimensions then exclude taskbar if its on the left of top.
taskbarPos := taskbarPos( )
x := taskbarPos = "left" && !( x=_x ) ? x-tbw : x
y := taskbarPos = "top" && !( y=_y ) ? y-tbh : y
if inStr( options, "saveSnap" )
{
mwa := monitorWorkingArea( )
snap := w = ( mwa.width//2 ) && h = mwa.height ? ( x = 0 ? " SnapLeft" : ( x = ( mwa.width//2 ) ? " SnapRight" : "" )) : "" ; detect snap to edge
}
DetectHiddenWindows := dhw
return x " " y " " w " " h " " state . snap
}
win_placementSet( hwnd, winPos, options:="noMin restoreSnap" )
{
/*
options
noMin
noMax
hide
restoreSnap if snap position was saved and the state is normal it will be used regardless of the size and position.
*/
dhw := A_DetectHiddenWindows
DetectHiddenWindows, On
stringSplit p, winPos, %a_space%
state := p5 = "" || p5 < 0 || p5 > 9 ? 1 : p5
state := inStr( options, "hide" ) ? 0 : (( p5 = 2 && inStr( options, "noMin" )) || ( p5 = 3 && inStr( options, "noMax" )) ? 1 : state )
if inStr( options, "restoreSnap" )
{
mwa := monitorWorkingArea( )
p1 := inStr( p6, "snapLeft" ) ? 0 : ( inStr( p6, "SnapRight" ) ? ( mwa.width//2 ) : p1 )
p3 := inStr( p6, "snapLeft" ) || inStr( p6, "SnapRight" ) ? mwa.width//2 : p3
p4 := inStr( p6, "snapLeft" ) || inStr( p6, "SnapRight" ) ? mwa.height : p4
}
varSetCapacity( wp, 44, 0 )
numPut( 44,wp )
numPut( p1 , wp , 28, "Int" )
numPut( p2 , wp , 32, "Int" )
numPut( p3+p1 , wp , 36, "Int" )
numPut( p4+p2 , wp , 40, "Int" )
numPut( state , wp , 8, "UInt" )
DetectHiddenWindows := dhw
return dllCall( "SetWindowPlacement", "uint", hwnd, "uint", &wp )
}
monitorWorkingArea( )
{
/*
author : Chef
link : http://ahkscript.org/boards/viewtopic.php?p=7194#p7194
date : 13 December 2013
description
an alternative function to get MonitorWorkingArea since Ahk "MonitorWorkArea command" is not reliable.
credit to SKAN and MilesAhead
*/
VarSetCapacity( APPBARDATA , 36, 0 )
if DllCall( "Shell32.dll\SHAppBarMessage", "UInt", 0x4, "uint", &APPBARDATA ) ; ABM_GETSTATE := 0x4
return {width:a_screenWidth, height:a_screenHeight}
WinGetPos,,,tbw, tbh, ahk_class Shell_TrayWnd
taskbarPos := tbw = a_screenWidth ? ( y <= 0 ? "top" : "bottom" ) : ( x <= 0 ? "left" : "right" )
return taskbarPos = "top" || taskbarPos = "bottom" ? {width:a_screenWidth, height:a_screenHeight-tbh}
: {width:a_screenWidth-tbw, height:a_screenHeight}
}