Jump to content

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

Detect full screen applications (screen saver, games...)


  • Please log in to reply
7 replies to this topic
Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Put these two lines in the beginning of your script:
ScWidth  = %A_ScreenWidth%
ScHeight = %A_ScreenHeight%
They determine the size of the screen, BEFORE the full screen application runs, which could change the resolution.

Later, where you need to know if the active window is full screen, you only have to compare the window size to the screen or see if the window size changed:
WinGetClass Class, A
WinGetPos,,,W,H, A
If ( Class <> "Progman" and Class <> "WorkerW" )
  If ( A_ScreenWidth <> ScWidth  or  A_ScreenHeight <> ScHeight
  or ( W > ScWidth - 9  and  H > ScHeight- 9) )
   ; ... put here the code to be executed for full screen applications
Edit 2005.11.08:
- Program Manager is not considered full screen
- Allow [-8]-to-infinity pixel errors in Windows calculating the native screen resolution.
Edit 2005.11.09:
- Class WorkerW is not considered full screen either
- If AHK sees a different screen size, we are in a full screen window

shimanov
  • Members
  • 610 posts
  • Last active: Jul 18 2006 08:35 PM
  • Joined: 25 Sep 2005
I tested your code with "3D Pinball for Windows - Space Cadet" with the following results:

A_ScreenWidth = 640, A_ScreenHeight = 480
[WinGetPos] width = 1601, height = 1201


Try the following experiment:

* run pinball in full screen mode
* press F10 to capture information
* exit full screen mode
* press F12 to display the results and exit the script

F10::
	WinGetPos,,, w_w, w_h, A

	text =
		( Join
			A_ScreenWidth = %A_ScreenWidth%, A_ScreenHeight = %A_ScreenHeight%
			`n[WinGetPos] width = %w_w%, height = %w_h%
		)
return

F12::
	MsgBox, %text%
ExitApp


evl
  • Members
  • 1237 posts
  • Last active: Oct 20 2010 11:41 AM
  • Joined: 24 Aug 2005
I tried running shimanov's code and I'm a bit puzzled with the outcome - maybe it's a bug in WinGetPos:

(Running windows xp and version 1.0.40.05)

Just testing on any program with a maximized window (not a full-screen game), with the taskbar set to auto-hide, I get:

A_ScreenWidth = 1024, A_ScreenHeight = 768
[WinGetPos] width = 1032, height = 776

...and with the taskbar visible, the only difference is height = 748.

What's going on with window sizes bigger than the screen??

shimanov
  • Members
  • 610 posts
  • Last active: Jul 18 2006 08:35 PM
  • Joined: 25 Sep 2005

Just testing on any program with a maximized window (not a full-screen game), with the taskbar set to auto-hide, I get:

A_ScreenWidth = 1024, A_ScreenHeight = 768
[WinGetPos] width = 1032, height = 776

...and with the taskbar visible, the only difference is height = 748.

What's going on with window sizes bigger than the screen??


Notice that a full screen game, such as pinball, operates in a different video mode. This is different from maximizing a window.

Try the following experiment:

I think it demonstrates that the window size returned is a Windows "bug" (or feature?). In any case, the returned size is unreliable when the window is maximized.

F10::
	WinGet, hw_active, ID, A
	WinGetPos,,, w_w, w_h, ahk_id %hw_active%
	WinGetClass, class, ahk_id %hw_active%
	WinGetTitle, title, ahk_id %hw_active%
	
	text :=
		( Join
			"A_ScreenWidth = " A_ScreenWidth ", A_ScreenHeight = " A_ScreenHeight
			"`n[WinGetPos] width = " w_w ",  height = " w_h
			"`n`nclass = " class
			"`ntitle = " title
		)
		
	VarSetCapacity( rect, 16 )
	status := DllCall( "GetWindowRect", "uint", hw_active, "uint", &rect )

	if ( ! status )
		text = %text%`n`n[GetWindowRect] failed!
	else
	{
		x1 := ReadInteger( "int4", &rect, 0, false )
		y1 := ReadInteger( "int4", &rect, 4, false )
		x2 := ReadInteger( "int4", &rect, 8, false )
		y2 := ReadInteger( "int4", &rect, 12, false )

		text :=
			( Join
				text "`n`n[GetWindowRect]"
				"`nx1 = " x1 ", y1 = " y1 ", x2 = " x2 ", y2 = " y2
				"`nwidth = " x2-x1 ", height = " y2-y1
				"`n`nIsZoomed = " DllCall( "IsZoomed", "uint", hw_active )
			) 
	}
return

F11::
	MsgBox, %text%
return

F12::
ExitApp

TwosComplement( p_value, p_size )
{
	return, ( p_value^( 2**( p_size*8 )-1 ) )+1
}

ReadInteger( p_type, p_address, p_offset, p_hex=true )
{
	old_FormatInteger := a_FormatInteger

	if ( p_hex )
		SetFormat, integer, hex
	else
		SetFormat, integer, dec
		
	if ( InStr( p_type, "u", false ) = 1 )
		sign := false
	else
		sign := true
	
	StringRight, size, p_type, 1

	value = 0
	loop, %size%
		value := value+( *( ( p_address+p_offset )+( a_Index-1 ) ) << ( 8*( a_Index-1 ) ) )
	    
	if ( sign )
	{
		sign := ( *( p_address+p_offset+( size-1 ) ) ) >> 7
		
		if ( sign )
			value := -1*TwosComplement( value, size )
	}
	    
	SetFormat, integer, %old_FormatInteger%

	return, value
}


Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
There is a problem, if the screen resolution changes. Windows calculates the actual width and height of the current window in the original (native) resolution, which could have rounding errors. This is why we need to establish the screen resolution beforehand. Because of the rounding errors I changed the tests in the script, allowing an error of 2 pixels. It works in my laptop, but please tell me your experiments with external monitors. Here is a test script:
#Persistent

SysGet Monitor, Monitor
SCWidth  := MonitorRight - MonitorLeft
SCHeight := MonitorBottom - MonitorTop

SysGet WorkArea, MonitorWorkArea
WkWidth  := WorkAreaRight - WorkAreaLeft
WkHeight := WorkAreaBottom - WorkAreaTop

SetTimer Clock
Return
Clock:
   WinGetPos,,,W,H, A
   ToolTip [%SCWidth%/%A_ScreenWidth%/%WkWidth%/%W%] x [%SCHeight%/%A_ScreenHeight%/%WkHeight%/%H%]
Return
It shows a tooltip with the screen and window size information. This way no key press is needed, so we can test screen savers, too.

There is another problem: the desktop looks also like a full screen application. To avoid it, we could test if the active window is Program Manager.

evl
  • Members
  • 1237 posts
  • Last active: Oct 20 2010 11:41 AM
  • Joined: 24 Aug 2005

Notice that a full screen game, such as pinball, operates in a different video mode. This is different from maximizing a window.

Try the following experiment:

I think it demonstrates that the window size returned is a Windows "bug" (or feature?). In any case, the returned size is unreliable when the window is maximized.


Yes, I realise it wasn't the same about the fullscreen app and a maximized window, I just wondered how reliable the information was at all :wink:

I'm certainly curious what these extra pixels are, if they actually exist - queue Microsoft conspiracy theories... hehe

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
(I think because of rounding errors) on some systems the size of the active window can look 8 pixels off (maybe more), when the screen resolution changed, but resolution can only change if an application runs in full screen. This allows us to further improve the tests: if AHK sees a different screen size, we must be in a full screen window. I updated the original post accordingly.

Tekl
  • Members
  • 814 posts
  • Last active: May 03 2009 03:28 PM
  • Joined: 24 Sep 2004
Hi,

laszlos way does not work, because if auto-hide of the taskbar is on, then the monitorare is the same like the workingarea.

There must be a better way.
Tekl