ahk v1.1+ ChangeDisplaySetting function for all OS and res

Get help with using AutoHotkey and its commands and hotkeys
Visioneer
Posts: 128
Joined: 07 Oct 2013, 18:51

ahk v1.1+ ChangeDisplaySetting function for all OS and res

15 Oct 2013, 18:03

Hi,

I have no interest or ability in learning how to program this, but
I need a function to change screen resolution once, and then be
able to change it back again shortly thereafter. It must work in
all windows OS, XP to W8, and in all the newest screen resolutions.
I actually need to change the resolution to 1024x768 and then
shortly there after change it back to the users normal resolution.
The users normal resolution will be obtained with A_ScreenWidth
and A_ScreenHeight. I am using AHK_L v1.1+ unicode

I have seen a number of these functions on the ahk forum and
some crash my PC on the return trip, and some, like this one below,
will set it once, but will not return it back to the original resolution.
I have seen some that can set 1024x768 to 800x600 or 640x480,
but don't work if starting out with 1280x800. This needs to work
for example on W8/7 with 1366x768, and XP with 1440x900, hopefully
all the various resolutions out there.

Right now I am using a freeware command line program called qres.exe.
It seems a shame I have to go outside ahk for this though. Unless someone
with the skill level of say. jethrow, can make this work with some certainty
I will probably stick with the freeware program.

Code: Select all

ChangeDisplaySettings( cD, sW, sH, rR )
{
  ;Calculate offset of DEVMODE fields:
  size := A_IsUnicode ? 220 : 156
  smSize := A_IsUnicode ? 68 : 36
  dmFields := dmSize + 4
  dmBitsPerPel := A_IsUnicode ? 168 : 104
  dmPelsWidth := dmBitsPerPel + 4
  dmPelsHeight := dmPelsWidth + 4
  dmDisplayFrequency := dmPelsHeight + 8
  
  VarSetCapacity(dM,size,0), NumPut(size,&dM,dmSize,"UShort")
  DllCall( "EnumDisplaySettings", UInt,0, UInt,-1, UInt,&dM )
  NumPut(0x5c0000,dM,dmFields,"UInt")
  NumPut(cD,dM,dmBitsPerPel,"UInt"),  NumPut(sW,dM,dmPelsWidth,"UInt")
  NumPut(sH,dM,dmPelsHeight,"UInt"),  NumPut(rR,dM,dmDisplayFrequency,"UInt")
  Return DllCall( "ChangeDisplaySettings", UInt,&dM, UInt,0 )
}
Thanks

ps: Please post the code without the line numbers, as I have IE9/7 and it always
picks up the numbers when I copy/paste the code, if there are line numbers.
lexikos
Posts: 7058
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: ahk v1.1+ ChangeDisplaySetting function for all OS and r

16 Oct 2013, 02:38

If you simply change the final 0 to a 4, the resolution will automatically reset when the script exits.

Code: Select all

Return DllCall( "ChangeDisplaySettings", UInt,&dM, UInt,4 )
CDS_FULLSCREEN (4)
The mode is temporary in nature.
Source: ChangeDisplaySettings function (Windows)
Visioneer
Posts: 128
Joined: 07 Oct 2013, 18:51

Re: ahk v1.1+ ChangeDisplaySetting function for all OS and r

17 Oct 2013, 08:40

Thanks lexikos,

That is great. Will it also let me change the resolution to lets say 1024x768 and then
change it back to the users original screen resolution, BEFORE I exit the program.
The temporary mode is a great failsafe in case of trouble, but I would need to do
the round trip while the script is running. IE: Toggle it.

I think it used to do that ok in ahk basic, but in ahkv1.1 unicode, it sets it OK but does not set it back within the script. I will try it now and let you know.

Thanks
Visioneer
Posts: 128
Joined: 07 Oct 2013, 18:51

Re: ahk v1.1+ ChangeDisplaySetting function for all OS and r

17 Oct 2013, 09:19

Hi Lexicos,

The change from 0 to 4 is great. I would even think that this option should be
incorporated into the script. I will use that as a failsafe in any case.
*[ChangeDisplaySettings( cD, sW, sH, rR, Temp="")]

Not restoring the screen res can really mess up ones desktop icons.

But alas the res won't toggle. It stays the same until I exit the script.
I am using a toshiba laptop W7 with initial screen resolution of 1280x800.
I am using ahk v1.1.13.00 (AHK_L) unicode.

Here is a simple test to demonstrate. Notice the the res does not return to
original until I exit the script.

Code: Select all

MsgBox, 4096,, It will be users original res now.`nA_ScreenWidth is: %A_ScreenWidth%`nA_ScreenHeight is %A_ScreenHeight%

ChangeDisplaySettings("", 1024, 768, "")

MsgBox, 4096,, It should be 1024x768 res now.`nA_ScreenWidth is: %A_ScreenWidth%`nA_ScreenHeight is %A_ScreenHeight%

sleep, 1000   

ChangeDisplaySettings("", 1280, 800, "")

MsgBox, 4096,, It should be returned to 1280x800 now. But is NOT!`nA_ScreenWidth is: %A_ScreenWidth%`nA_ScreenHeight is %A_ScreenHeight%

MsgBox, 4096,, We will now exit the script. Notice that the res will only now return to our original res.

ExitApp
just me
Posts: 7228
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ahk v1.1+ ChangeDisplaySetting function for all OS and r

17 Oct 2013, 10:58

Code: Select all

ChangeDisplaySettings(cD, sW, sH, rR)
{
   Static DM := {BITSPERPEL: 0x040000, PELSWIDTH: 0x080000, PELSHEIGHT: 0x100000, DISPLAYFREQUENCY: 0x400000}
   ;Calculate offset of DEVMODE fields:
   Static size := A_IsUnicode ? 220 : 156
   Static dmSize := A_IsUnicode ? 68 : 36 ; <<< has to be dmSize, not smSize
   Static dmFields := dmSize + 4
   Static dmBitsPerPel := A_IsUnicode ? 168 : 104
   Static dmPelsWidth := dmBitsPerPel + 4
   Static dmPelsHeight := dmPelsWidth + 4
   Static dmDisplayFrequency := dmPelsHeight + 8

   dmAddr := 0
   VarSetCapacity(DEVMODE, size, 0)
   NumPut(size, DEVMODE, dmSize, "UShort")
   fields := 0
   If (cD <> "") {
      NumPut(cD, DEVMODE, dmBitsPerPel, "UInt")
      fields |= DM.BITSPERPEL
   }
   If (sW <> "") {
      NumPut(sW, DEVMODE, dmPelsWidth, "UInt")
      fields |= DM.PELSWIDTH
   }
   If (sH <> "") {
      NumPut(sH, DEVMODE, dmPelsHeight, "UInt")
      fields |= DM.PELSHEIGHT
   }
   If (rR <> "") {
      NumPut(rR, DEVMODE, dmDisplayFrequency, "UInt")
      fields |= DM.DISPLAYFREQUENCY
   }
   If (fields > 0) {
      NumPut(fields, DEVMODE, dmFields, "UInt")
      dmAddr := &DEVMODE
   }
   Return DllCall("User32.dll\ChangeDisplaySettings", "Ptr", dmAddr, "UInt", 0, "Int")
}
?
Visioneer
Posts: 128
Joined: 07 Oct 2013, 18:51

Re: ahk v1.1+ ChangeDisplaySetting function for all OS and r

17 Oct 2013, 13:21

Thanks, just me!

That works! I also changed to last 0 to 4, and it restores the users resolution on ExitApp.

I will add that option and repost your script shortly if that is ok with you. Please
review it and tell me if it is OK.

I think I will default it to temporary as that is safer for end users anyway.

So do you think this will work for all windows OS and any screen resolution?

Many Thanks!
Visioneer
Posts: 128
Joined: 07 Oct 2013, 18:51

Re: ahk v1.1+ ChangeDisplaySetting function for all OS and r

17 Oct 2013, 16:57

Hi, just me and lexicos,

I have tried to add the 5th parameter to default to temporary. As the price
of script failure is so high with the desktop icons thing, I feel it should default
to temporary. You might also want to make the Cd and rH be temporary also.
I would not know how to do that in a million years however. I could have probably
made the 0 and 4 a variable, but I think this way makes it more clear what is going on,
which is how I roll. Please see if you think this should work on all Windows OS and screen
resolutions out there. (Especially W8)

Code: Select all

;Use 1 for Perm parameter to make the screen resolution change permanent so it stays after ExitApp.
;Otherwise the screen resolution will revert back when the program exits. The dafault.
ChangeDisplaySettings(cD, sW, sH, rR, Perm="")  
{
;By "just me" and "lexicos".

   Static DM := {BITSPERPEL: 0x040000, PELSWIDTH: 0x080000, PELSHEIGHT: 0x100000, DISPLAYFREQUENCY: 0x400000}
   ;Calculate offset of DEVMODE fields:
   Static size := A_IsUnicode ? 220 : 156
   Static dmSize := A_IsUnicode ? 68 : 36 ; <<< has to be dmSize, not smSize
   Static dmFields := dmSize + 4
   Static dmBitsPerPel := A_IsUnicode ? 168 : 104
   Static dmPelsWidth := dmBitsPerPel + 4
   Static dmPelsHeight := dmPelsWidth + 4
   Static dmDisplayFrequency := dmPelsHeight + 8

   dmAddr := 0
   VarSetCapacity(DEVMODE, size, 0)
   NumPut(size, DEVMODE, dmSize, "UShort")
   fields := 0
   If (cD <> "") {
      NumPut(cD, DEVMODE, dmBitsPerPel, "UInt")
      fields |= DM.BITSPERPEL
   }
   If (sW <> "") {
      NumPut(sW, DEVMODE, dmPelsWidth, "UInt")
      fields |= DM.PELSWIDTH
   }
   If (sH <> "") {
      NumPut(sH, DEVMODE, dmPelsHeight, "UInt")
      fields |= DM.PELSHEIGHT
   }
   If (rR <> "") {
      NumPut(rR, DEVMODE, dmDisplayFrequency, "UInt")
      fields |= DM.DISPLAYFREQUENCY
   }
   If (fields > 0) {
      NumPut(fields, DEVMODE, dmFields, "UInt")
      dmAddr := &DEVMODE
   }
   
   If Perm = 1 ;Resolution change will continue after exiting program.
   Return DllCall("User32.dll\ChangeDisplaySettings", "Ptr", dmAddr, "UInt", 0, "Int")
   else ;Resolution change will revert to original after exiting program. 
   Return DllCall("User32.dll\ChangeDisplaySettings", "Ptr", dmAddr, "UInt", 4, "Int")
}
Many Thanks
Visioneer
Posts: 128
Joined: 07 Oct 2013, 18:51

Re: ahk v1.1+ ChangeDisplaySetting function for all OS and r

17 Oct 2013, 18:34

Hi just me and lexicos,

There is a little problem. While it does change to resolution to say, 1024x768
from 1280x800, the webpage form does not resettle itself if I use the 4 instead of 0
at the end.

Normally when I change resolution with qres.exe it sometimes takes a second or two for
the webpage resettle and show the forms input box in the center like it normally
would be at the new screen resolution. This function is not allowing this resettling
to occur however when I use the 4 for temporary. It does work OK when I use your
original 0 though. I would have liked the temporary thing in case the program ever
quits prematurely. it would return to the users default screen resolution.

Thanks
just me
Posts: 7228
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ahk v1.1+ ChangeDisplaySetting function for all OS and r

18 Oct 2013, 00:04

Hi,

to reset to the default settings (stored in the registry), just pass empty values ("") for all parameters. You might call the function like this in an OnExit label, to make sure that changes will be resetted.

I never used the CDS_FULLSCREEN mode, so I don't know how it works.

For more informations see ChangeDisplaySettings().
Visioneer
Posts: 128
Joined: 07 Oct 2013, 18:51

Re: ahk v1.1+ ChangeDisplaySetting function for all OS and r

18 Oct 2013, 02:45

Thanks just me.

I guess I will have to live without the 4 and try the OnExit you recommend.

Hey lexicos, you see how to apply the 0 to 4 CDS_FULLSCREEN thing to just me's
function. At least it allows me to toggle switch resolution within the program.
I am not applyng the 4 properly in his function, no doubt, so it causes other trouble
in his function.

Thanks

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot] and 48 guests