[Function] win_pos (save and restore)

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
Chef
Posts: 50
Joined: 14 Nov 2013, 13:01

[Function] win_pos (save and restore)

06 Dec 2013, 13:37

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}
}

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 78 guests