Jump to content

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

Change Display Mode


  • Please log in to reply
33 replies to this topic
shimanov
  • Members
  • 610 posts
  • Last active: Jul 18 2006 08:35 PM
  • Joined: 25 Sep 2005
Change the primary display mode parameters, including: resolution, color quality, and refresh rate.

The required API functions are available with all versions of Windows.

system_path = %A_WinDir%\system
if ( A_OSType != WIN32_WINDOWS )
	system_path = %system_path%32
	
id_image_list := IL_Create( 1, 0, 0 )
IL_Add( id_image_list, system_path "\shell32.dll", 131 )

Gui, Add, ListView, x5 y5 w280 h200 grid gChangeDisplayMode, |width|height|quality (bits)|frequency (Hz)
Gui, Show, x50 y50 w290 h210, Change Display Mode

LV_SetImageList( id_image_list, 1 )

Gui, +LastFound

struct_devicemode_size = 156
VarSetCapacity( device_mode, struct_devicemode_size, 0 )

EncodeInteger( struct_devicemode_size, 2, &device_mode, 36 )

; ENUM_CURRENT_SETTINGS
success := DllCall( "EnumDisplaySettings", "uint", 0, "uint", -1, "uint", &device_mode )

current?width := DecodeInteger( "uint4", &device_mode, 108, false )
current?height := DecodeInteger( "uint4", &device_mode, 112, false )
current?quality := DecodeInteger( "uint4", &device_mode, 104, false )
current?frequency := DecodeInteger( "uint4", &device_mode, 120, false )

loop,
{
	success := DllCall( "EnumDisplaySettings", "uint", 0, "uint", A_Index-1, "uint", &device_mode )
	if ( ErrorLevel or !success )
		break
		
	mode?width := DecodeInteger( "uint4", &device_mode, 108, false )
	mode?height := DecodeInteger( "uint4", &device_mode, 112, false )
	mode?quality := DecodeInteger( "uint4", &device_mode, 104, false )
	mode?frequency := DecodeInteger( "uint4", &device_mode, 120, false )
	
	if ( mode?width = current?width
			and mode?height = current?height
			and mode?quality = current?quality
			and mode?frequency = current?frequency )
		options = Focus Icon1 Select
	else
		options = Icon0
	
	LV_Add( options, "", mode?width, mode?height, mode?quality, mode?frequency )
}

loop, 5
	LV_ModifyCol( A_Index, "AutoHdr Integer" )

LV_ModifyCol( 2, "Sort" )

current?index := LV_GetNext()

; LVM_ENSUREVISIBLE
SendMessage, 0x1000+19, current?index-1, false, SysListView321
return

GuiClose:
ExitApp

ChangeDisplayMode:
	if ( A_GuiEvent != "DoubleClick" )
		return

	; DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY
	EncodeInteger( 0x00040000|0x00080000|0x00100000|0x00400000, 4, &device_mode, 40 )
	
	LV_GetText( value, A_EventInfo, 4 )
		EncodeInteger( value, 4, &device_mode, 104 )
	LV_GetText( value, A_EventInfo, 2 )
		EncodeInteger( value, 4, &device_mode, 108 )
	LV_GetText( value, A_EventInfo, 3 )
		EncodeInteger( value, 4, &device_mode, 112 )
	LV_GetText( value, A_EventInfo, 5 )
		EncodeInteger( value, 4, &device_mode, 120 )

	; 0 = change mode dynamically
	; 2 = test if mode is valid
	; 1 = 0+update user profile in registry
	result := DllCall( "ChangeDisplaySettings", "uint", &device_mode, "uint", 0 )
	if ( ErrorLevel )
		MsgBox, [ChangeDisplaySettings] failure: EL = %ErrorLevel%
	else
	{
		if ( result = 0 )
		{
			LV_Modify( current?index, "Icon0" )
			current?index := A_EventInfo
				LV_Modify( current?index, "Icon1" )
		
			result = DISP_CHANGE_SUCCESSFUL
		}
		else if ( result = 1 )
			result = DISP_CHANGE_RESTART
		else if ( result = -1 )
			result = DISP_CHANGE_FAILED
		else if ( result = -2 )
			result = DISP_CHANGE_BADMODE
		else if ( result = -3 )
			result = DISP_CHANGE_NOTUPDATED
		else if ( result = -4 )
			result = DISP_CHANGE_BADFLAGS
		else if ( result = -5 )
			result = DISP_CHANGE_BADPARAM
		else if ( result = -6 )
			result = DISP_CHANGE_BADDUALVIEW
		
		MsgBox, 0, Change Display Mode, %result%, 2
	}
return

DecodeInteger( p_type, p_address, p_offset, p_hex=true )
{
	old_FormatInteger := A_FormatInteger

	if ( p_hex )
		SetFormat, Integer, hex
	else
		SetFormat, Integer, dec

	sign := InStr( p_type, "u", false )^1

	StringRight, size, p_type, 1

	loop, %size%
		value += ( *( ( p_address+p_offset )+( A_Index-1 ) ) << ( 8*( A_Index-1 ) ) )

	if ( sign and size <= 4 and *( p_address+p_offset+( size-1 ) ) & 0x80 )
		value := -( ( ~value+1 ) & ( ( 2**( 8*size ) )-1 ) )

	SetFormat, Integer, %old_FormatInteger%

	return, value
}

EncodeInteger( p_value, p_size, p_address, p_offset )
{
	loop, %p_size%
		DllCall( "RtlFillMemory"
			, "uint", p_address+p_offset+A_Index-1
			, "uint", 1
			, "uchar", ( p_value >> ( 8*( A_Index-1 ) ) ) & 0xFF )
}


Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Very useful. Given the number of requests over the past two years, I know this is going to be a popular one!

shimanov
  • Members
  • 610 posts
  • Last active: Jul 18 2006 08:35 PM
  • Joined: 25 Sep 2005
One more example of AHk's immediate usefulness, in its current form, and with its current function. All in all, a very capable development platform.

  • Guests
  • Last active:
  • Joined: --

One more example of AHk's immediate usefulness


I need that and thanks you.
Bat cant understand what is command for fix resolution
Example 1200x1024

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

I need that and thanks you.


Sure.

Bat cant understand what is command for fix resolution
Example 1200x1024


You will need all four parameters to specify a video mode. Check for valid modes with the original script.

struct_devicemode_size = 156
VarSetCapacity( device_mode, 156, 0 )

EncodeInteger( struct_devicemode_size, 2, &device_mode, 36 )

success := DllCall( "EnumDisplaySettings", "uint", 0, "uint", -1, "uint", &device_mode )

; DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY
EncodeInteger( 0x00040000|0x00080000|0x00100000|0x00400000, 4, &device_mode, 40 )

EncodeInteger( 32, 4, &device_mode, 104 )										; quality (i.e., color depth)
EncodeInteger( 1600, 4, &device_mode, 108 )										; width
EncodeInteger( 1200, 4, &device_mode, 112 )										; height
EncodeInteger( 60, 4, &device_mode, 120 )										; frequency (i.e., refresh rate)

DllCall( "ChangeDisplaySettings", "uint", &device_mode, "uint", 0 )


Invalid User
  • Members
  • 447 posts
  • Last active: Mar 27 2012 01:04 PM
  • Joined: 14 Feb 2005
This is great work! I want to add this to the function lib I have as a sticky, but as I attempted to lose the gui part, I broke it miserably. Will you please create a fucntion to change the disp settings that will allow changes on multi monitor systems and also add error levels for attempts to apply settings that cannot be handled such as too high res attempted to be set.

Thanks very much, keep up the great work.

  • Guests
  • Last active:
  • Joined: --
@shimanov
I steel not understand what is what parameters
do you writed code what is work whit 1200x124,32,60Hz?
thanks

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
You were lost by the code at start, missing the helpful comments at the end:

EncodeInteger( 32, 4, &device_mode, 104 ) ; quality (i.e., color depth)
EncodeInteger( 1600, 4, &device_mode, 108 ) ; width
EncodeInteger( 1200, 4, &device_mode, 112 ) ; height
EncodeInteger( 60, 4, &device_mode, 120 ) ; frequency (i.e., refresh rate)

You can use the code given by shimanov as is, changing only the first parameter of these function calls: replace 1600 by 1200 (or 1280?), 1200 by 1024 (not 124 I suppose...) and you are done.
Oh well, to restructure a bit this code (untested):
; ChangeDisplaySettings.ahk
; by shimanov
; http://www.autohotkey.com/forum/viewtopic.php?t=8355

colorDepth = 32 ; bits (quality)
screenWidth = 1600 ; pixels
screenHeight = 1200 ; pixels
refreshRate = 60 ; Hz (frequency)
; Don't change anything below!

struct_devicemode_size = 156
VarSetCapacity(device_mode, struct_devicemode_size, 0)

EncodeInteger(struct_devicemode_size, 2, &device_mode, 36)

success := DllCall("EnumDisplaySettings", "uint", 0, "uint", -1, "uint", &device_mode)

; DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY
EncodeInteger(0x00040000|0x00080000|0x00100000|0x00400000, 4, &device_mode, 40)

EncodeInteger(colorDepth, 4, &device_mode, 104)
EncodeInteger(screenWidth, 4, &device_mode, 108)
EncodeInteger(screenHeight, 4, &device_mode, 112)
EncodeInteger(refreshRate, 4, &device_mode, 120)

DllCall("ChangeDisplaySettings", "uint", &device_mode, "uint", 0)


  • Guests
  • Last active:
  • Joined: --
EncodeInteger(struct_devicemode_size, 2, &device_mode, 36)

Here is problem. Stop in this line.

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
You need the EncodeInteger function given by shimanov in the first version of the script:
EncodeInteger( p_value, p_size, p_address, p_offset )
{
   loop, %p_size%
      DllCall( "RtlFillMemory"
         , "uint", p_address+p_offset+A_Index-1
         , "uint", 1
         , "uchar", ( p_value >> ( 8*( A_Index-1 ) ) ) & 0xFF )
}


  • Guests
  • Last active:
  • Joined: --
Thanks PhiLho & shimanov for help

  • Guests
  • Last active:
  • Joined: --
Can anyone verify that this code still works with the latest version of AHK?
(ahk ver 1.0.46. 06)

All seems to work for me, except all the entries in thefrequency
column are all "0".

Thanks

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
Works for me (1.0.46.06) out of the box. Hey, I can switch to 320x200, great! :-D

  • Guests
  • Last active:
  • Joined: --

Works for me (1.0.46.06) out of the box. Hey, I can switch to 320x200, great! :-D


Thanks for the test. I guess this is just one of those "win98SE" problems.
I tried it on two computers with the same results: it does successfully change display modes, but always displays "0" in the frequency column. :cry:

BoBo
  • Guests
  • Last active:
  • Joined: --
@Guest
please use a nick (you don't have to register for it). Thx. 8)