#NoEnv #SingleInstance Force #Persistent ; Try to retrieve user-set resolutions RegRead, ResolutionsString, HKEY_CURRENT_USER\Software\JohnAJ\DRM, Resolutions if (ErrorLevel != 1) goto Start ; Fall back on default resolutions ResolutionsString = 1600x1200|1024x768|800x600|640x480 ; 4:3 if (A_ScreenWidth/A_ScreenHeight = 1.6) ResolutionsString = 1920x1200|1680x1050|1440x900|1280x800 ; 16:10 if (Round(A_ScreenWidth/A_ScreenHeight, 2) = 1.77) ResolutionsString = 1920x1080|1366x768|1280x720|854x480 ; 16:9 RegWrite, REG_SZ, HKEY_CURRENT_USER\Software\JohnAJ\DRM, Resolutions, %ResolutionsString% ; Set up tray menu Start: Resolutions := StrSplit(ResolutionsString, "|") Menu, Tray, NoStandard Menu, Tray, Tip, Dynamic Resolution Manager for k, res in Resolutions Menu, Tray, Add, %res%, SelectMenuResolution Menu, Tray, Add Menu, Tray, Add, E&xit, ButtonExit return ButtonExit: ExitApp ; Select resolution from tray menu SelectMenuResolution(ItemName, ItemPos, MenuName) { ResArray := StrSplit(ItemName, "x") SwitchToResolutionFrom(ResArray[1], ResArray[2], A_ScreenWidth, A_ScreenHeight) } ; Save window positions, switch to given resolution, restore window positions SwitchToResolutionFrom(WidthNew, HeightNew, WidthOrig, HeightOrig) { Positions := {} Save(Positions) SetResolution(WidthNew, HeightNew) Sleep, 500 Restore(Positions) TrayTip, Resolution changed, % "Press Escape within 3 seconds to revert." KeyWait, Esc, D T3 TrayTip if (ErrorLevel = 1) ; user didn't press escape return SetResolution(%WidthOrig%, %HeightOrig%) Sleep, 500 Restore(Positions) } ; Set screen resolution SetResolution(Width, Height, ColorDepth := 32) { VarSetCapacity(DeviceMode, 156, 0) NumPut(156, DeviceMode, 36) DllCall("EnumDisplaySettingsA", UInt, 0, UInt, -1, UInt, &DeviceMode) NumPut(0x5c0000, DeviceMode, 40) NumPut(ColorDepth, DeviceMode, 104) NumPut(Width, DeviceMode, 108) NumPut(Height, DeviceMode, 112) DllCall("ChangeDisplaySettingsA", UInt, &DeviceMode, UInt, 0) } Save(ByRef Positions) { Positions := {} WinGet, id, list SysGet, WorkArea, MonitorWorkArea Width := WorkAreaRight - WorkAreaLeft Height := WorkAreaBottom - WorkAreaTop Loop, %id% { i := id%A_Index% WinReallyGetPos(i, x, y, w, h) Positions[i] := [x / Width, y / Height, w / Width, h / Height] } } Restore(Positions) { SysGet, WorkArea, MonitorWorkArea Width := WorkAreaRight - WorkAreaLeft Height := WorkAreaBottom - WorkAreaTop for i, props in Positions { x := props[1] y := props[2] w := props[3] h := props[4] WinReallyMove(i, x * Width, y * Height, w * Width, h * Height) } } ; Get position of any window, even a minimized one WinReallyGetPos(hwnd, ByRef x, ByRef y, ByRef w="", ByRef h="") { VarSetCapacity(wp, 44), 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 } ; Set position of any window, even a minimized one WinReallyMove(hwnd, x, y, w, h) { VarSetCapacity(wp, 44, 0), NumPut(44, wp, "uint") NumPut(5, wp, 8, "uint") NumPut(x, wp, 28, "int") NumPut(y, wp, 32, "int") NumPut(w + x, wp, 36, "int") NumPut(h + y, wp, 40, "int") DllCall("SetWindowPlacement", "ptr", hwnd, "ptr", &wp) }