I think this question has been asked (more than) a few times, but I'm still curious about it.
Is there a way to change the display resolution programmatically (I.e., via a WB script) other than by driving the "desk.cpl" UI? E.g., by setting something in the registry or maybe via WMI?
Inquiring minds...
Your in luck the code is already the tech database: http://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/tsleft.web+WinBatch/Samples~from~Users+Change~Screen~Resolution.txt
Thanks. I'll let you know if I am able to get it to work.
(Note: Going by the comments and by the length of the file, it looks like the program does a whole lot more than just setting the resolution. Somebody (presumably me) needs to go in and prune it back...)
Hi SnowSnowSnow,
If you've pruned this back, would you be willing to share?
Regards,
Jeff
Quote from: mcjathan on November 18, 2013, 09:37:52 AM
Hi SnowSnowSnow,
If you've pruned this back, would you be willing to share?
Regards,
Jeff
Jeff,
Based on the provided code sample in the tech database....Here is a totally UNDEBUGGED attempt at creating two User Defined Functions to handle: listing the resolution options then setting the resolution:
#DefineFunction udfEnumDisplaySettings()
;Enumerate current and supported display settings
UserDll=StrCat(DirWindows(1),"USER32.DLL")
TDEVICEMODEA=BinaryAlloc(156) ;DEVMODE structure
;Size of TDEVICEMODEA record: 156 Bytes
;Field offsets and sizes are:
offdmDeviceName = 0 ;32
offdmSpecVersion = 32 ;2
offdmDriverVersion = 34 ;2
offdmSize = 36 ;2
offdmDriverExtra = 38 ;2
offdmFields = 40 ;4
offdmOrientation = 44 ;2
offdmPaperSize = 46 ;2
offdmPaperLength = 48 ;2
offdmPaperWidth = 50 ;2
offdmScale = 52 ;2
offdmCopies = 54 ;2
offdmDefaultSource = 56 ;2
offdmPrintQuality = 58 ;2
offdmColor = 60 ;2
offdmDuplex = 62 ;2
offdmYResolution = 64 ;2
offdmTTOption = 66 ;2
offdmCollate = 68 ;2
offdmFormName = 70 ;32
offdmLogPixels = 102 ;2
offdmBitsPerPel = 104 ;4
offdmPelsWidth = 108 ;4
offdmPelsHeight = 112 ;4
offdmDisplayFlags = 116 ;4
offdmDisplayFrequency = 120 ;4
offdmICMMethod = 124 ;4
offdmICMIntent = 128 ;4
offdmMediaType = 132 ;4
offdmDitherType = 136 ;4
offdmICCManufacturer = 140 ;4
offdmICCModel = 144 ;4
offdmPanningWidth = 148 ;4
offdmPanningHeight = 152 ;4
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;Bool EnumDisplaySettingsA (String:lpszDeviceName,Integer:iModeNum,Pointer:lpDevMode)
; lpszDeviceName is a pointer to the target display adapter. Null specifies default adapter.
; iModeNum specifies whether to query the display adapter or the registry settings for the adapter.
; lpDevMode is a pointer to a DevMode structure to store info about the specified graphics mode.
ModeIndex=-1 ;Value of -1 returns current settings
Selection=""
While 1
ReturnValue=DllCall(UserDll,long:"EnumDisplaySettingsA",lpnull,long:ModeIndex,lpbinary:TDEVICEMODEA )
If ReturnValue==0 Then Break
; Get info on relevant display settings
dmPelsWidth = BinaryPeek4(TDEVICEMODEA,offdmPelsWidth) ;Horizontal resolution
dmPelsHeight = BinaryPeek4(TDEVICEMODEA,offdmPelsHeight) ;Vertical resolution
dmBitsPerPel = BinaryPeek4(TDEVICEMODEA,offdmBitsPerPel) ;Color depth
dmDisplayFrequency = BinaryPeek4(TDEVICEMODEA,offdmDisplayFrequency) ;Refresh Rate
dmDisplayFlags = BinaryPeek4(TDEVICEMODEA,offdmDisplayFlags) ;Only used if monitor is greyscale or interlaced
If ModeIndex<0 ;Index of -1 returns current settings
DispProb=""
CurRes=StrCat (dmPelsWidth,"x",dmPelsHeight) ;Extract current resolution
CurBPP=StrCat (dmBitsPerPel,"-bit") ;Extract current color depth
CurRef=StrCat (dmDisplayFrequency,"Hz") ;Extract current refresh rate
If dmPelsWidth<800 Then DispProb=StrCat (DispProb,"Resolution",@TAB)
If dmBitsPerPel<16 Then DispProb=StrCat (DispProb,"Color depth",@TAB)
If dmDisplayFrequency<75 Then DispProb=StrCat (DispProb,"Refresh rate")
If ItemCount (DispProb,@TAB)>1 Then DispProb=StrReplace (DispProb,@TAB,", ")
If DispProb=="" ;Everything checks out
DispProb="None" ;Make it readable
EndIf
EndIf
Line=StrCat(dmPelsWidth,"x",dmPelsHeight,"x",dmBitsPerPel,",",dmDisplayFrequency,"Hz");Format for list
;Don't add modes with less that 640x480 resolution or 60Hz refresh to Mode list
If (dmPelsWidth>639 && dmDisplayFrequency>59 && ModeIndex>=0) Then Selection=StrCat(Selection,Line,@TAB)
ModeIndex=ModeIndex + 1 ;Index of 0 or greater returns supported modes
EndWhile
BinaryFree(TDEVICEMODEA)
Return Selection
#EndFunction
#DefineFunction udfChangeDisplaySettingsA(NewSetting); in the format ;1920x1080x32,60hz
;Expected format: {PelsWidth}x{PelsHeight}x{BitsPerPel},{DisplayFrequency}hz
UserDll=StrCat(DirWindows(1),"USER32.DLL")
;Parse selected settings
dmPelsWidth = ItemExtract(1,NewSetting,"x")
dmPelsHeight = ItemExtract(2,NewSetting,"x")
dmBitsPerPel = ItemExtract(1,ItemExtract(3,NewSetting,"x"),",")
dmDisplayFrequency = ItemExtract(2,NewSetting,",")
dmDisplayFrequency = StrSub( dmDisplayFrequency, 1, StrLen(dmDisplayFrequency)-2 )
dmDisplayFlags = 0
If dmPelsWidth=="" || dmPelsHeight=="" || dmBitsPerPel=="" || dmDisplayFrequency=="" || dmDisplayFlags==""
Pause('udfChangeDisplaySettingsA','Invalid parameter.')
Return 0
Endif
TDEVICEMODEA=BinaryAlloc(156) ;DEVMODE structure
;Size of TDEVICEMODEA record: 156 Bytes
;Field offsets and sizes are:
offdmDeviceName = 0 ;32
offdmSpecVersion = 32 ;2
offdmDriverVersion = 34 ;2
offdmSize = 36 ;2
offdmDriverExtra = 38 ;2
offdmFields = 40 ;4
offdmOrientation = 44 ;2
offdmPaperSize = 46 ;2
offdmPaperLength = 48 ;2
offdmPaperWidth = 50 ;2
offdmScale = 52 ;2
offdmCopies = 54 ;2
offdmDefaultSource = 56 ;2
offdmPrintQuality = 58 ;2
offdmColor = 60 ;2
offdmDuplex = 62 ;2
offdmYResolution = 64 ;2
offdmTTOption = 66 ;2
offdmCollate = 68 ;2
offdmFormName = 70 ;32
offdmLogPixels = 102 ;2
offdmBitsPerPel = 104 ;4
offdmPelsWidth = 108 ;4
offdmPelsHeight = 112 ;4
offdmDisplayFlags = 116 ;4
offdmDisplayFrequency = 120 ;4
offdmICMMethod = 124 ;4
offdmICMIntent = 128 ;4
offdmMediaType = 132 ;4
offdmDitherType = 136 ;4
offdmICCManufacturer = 140 ;4
offdmICCModel = 144 ;4
offdmPanningWidth = 148 ;4
offdmPanningHeight = 152 ;4
;Poke Settings into DEVMODE structure
BinaryPoke4 (TDEVICEMODEA,offdmBitsPerPel ,dmBitsPerPel)
BinaryPoke4 (TDEVICEMODEA,offdmPelsWidth ,dmPelsWidth)
BinaryPoke4 (TDEVICEMODEA,offdmPelsHeight ,dmPelsHeight)
BinaryPoke4 (TDEVICEMODEA,offdmDisplayFrequency,dmDisplayFrequency)
BinaryPoke4 (TDEVICEMODEA,offdmDisplayFlags ,dmDisplayFlags)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;Begin NT Fix;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Find selected buffer again (for NT)
ModeIndex = 0
Selection=""
While 1
ReturnValue=DllCall(UserDll,long:"EnumDisplaySettingsA",lpnull,long:ModeIndex,lpbinary:TDEVICEMODEA)
If ReturnValue==0
Message("Res Change","Strange error occurred")
Exit
EndIf
dmPelsWidth2 = BinaryPeek4(TDEVICEMODEA,offdmPelsWidth) ;Horizontal resolution
dmPelsHeight2 = BinaryPeek4(TDEVICEMODEA,offdmPelsHeight) ;Vertical resolution
dmBitsPerPel2 = BinaryPeek4(TDEVICEMODEA,offdmBitsPerPel) ;Color depth
dmDisplayFrequency2 = BinaryPeek4(TDEVICEMODEA,offdmDisplayFrequency) ;Refresh Rate
dmDisplayFlags2 = BinaryPeek4(TDEVICEMODEA,offdmDisplayFlags) ;Only used if monitor is greyscale or interlaced
If (dmBitsPerPel==dmBitsPerPel2 && dmPelsWidth==dmPelsWidth2 && dmPelsHeight==dmPelsHeight2 && dmDisplayFlags==dmDisplayFlags2 && dmDisplayFrequency==dmDisplayFrequency2)
; we found our setting...
Break
EndIf
ModeIndex=ModeIndex+1
EndWhile
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;End NT Fix;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set the field mask to determine fields to use for setting the display mode
DM_BITSPERPEL = 262144 ; 0x40000
DM_PELSWIDTH = 524288 ; 0x80000
DM_PELSHEIGHT = 1048576 ; 0x100000
DM_DISPLAYFLAGS = 2097152 ; 0x200000
DM_DISPLAYFREQUENCY = 4194304 ; 0x400000
dmFields = (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY) ; 0x7C0000 = 8126464 decimal
BinaryPoke4 (TDEVICEMODEA,offdmFields,dmFields)
CDS_DYNAMICONLY = 0 ; Change current session only
CDS_UPDATEREGISTRY = 1 ; Change and update registry
CDS_TEST = 2 ; Test only
ChangeMode = CDS_UPDATEREGISTRY
ReturnValue = DllCall(UserDll,long:"ChangeDisplaySettingsA",lpbinary:TDEVICEMODEA,long:ChangeMode )
DISP_CHANGE_SUCCESSFUL= 0 ;The settings change was successful.
DISP_CHANGE_RESTART = 1 ;The computer must be restarted in order for the graphics mode to work.
DISP_CHANGE_FAILED = -1 ;The display driver failed the specified graphics mode.
DISP_CHANGE_BADMODE = -2 ;The graphics mode is not supported.
DISP_CHANGE_NOTUPDATED= -3 ;Unable to write settings to the registry.
DISP_CHANGE_BADFLAGS = -4 ;An invalid set of flags was passed in.
DISP_CHANGE_BADPARAM = -5 ;Bad parameters
Switch ReturnValue
Case 1
Line="The computer must be restarted in order for the graphics mode to work."
Break
Case 0
Line="The settings change was successful."
Break
Case -1
Line="The display driver failed the specified graphics mode."
Break
Case -2
Line="The graphics mode is not supported."
Break
Case -3
Line="Unable to write settings to the registry."
Break
Case -4
Line="An invalid set of flags was passed in."
Break
Case -5
Line="Bad parameters"
Break
Case ReturnValue
Line="Unknown return code %ReturnValue%"
Break
EndSwitch
If ReturnValue==1
If ChangeMode!=CDS_UPDATEREGISTRY
Line=StrCat (Line,@CRLF,"Because the Update Registry option was not in effect, no changes will be made")
Message("Resolution Change",Line)
Exit
Else
Pause ("Reboot machine",Line)
IntControl (67,0,0,0,0)
EndIf
Else
Display (3,"Resolution Change",Line)
EndIf
BinaryFree(TDEVICEMODEA)
Return 1
#EndFunction
;Set Screen resolution
;
ret = udfChangeDisplaySettingsA("1920x1080x32,60hz")
Pause("Set Resolution",ret)
Exit
;*OR*
;List options then set resolution
list = udfEnumDisplaySettings() ;1920x1080x32,60hz
NewSetting = AskItemList("udfEnumDisplaySettings", list, @tab, @unsorted, @single )
ret = udfChangeDisplaySettingsA(NewSetting)
Pause("done",ret)
Exit
Quote from: Deana on November 18, 2013, 10:26:21 AM
Jeff,
Based on the provided code sample in the tech database....Here is a totally UNDEBUGGED attempt at creating two User Defined Functions to handle: listing the resolution options then setting the resolution:
Thank you, Deana. So far, it seems to be working great.