Reputation: 775
I'd like to use nim to resize the default display resolution on a machine (windows 10 only), I want to basically do it via a command line call like setDisplay 1280 1024
I've seen and used the python example Resize display resolution using python with cross platform support which I can follow, but just can't translate. I just don't get how to fill in EnumDisplaySettings
import winim/lean
import strformat
var
cxScreen = GetSystemMetrics(SM_CXSCREEN)
cyScreen = GetSystemMetrics(SM_CYSCREEN)
msg = fmt"The screen is {cxScreen} pixels wide by {cyScreen} pixels high."
EnumDisplaySettings(Null,0, 0) #total type mismatch
MessageBox(0, msg, "Winim Example Screen Size", 0)
Tried checking stuff like https://cpp.hotexamples.com/fr/examples/-/-/EnumDisplaySettings/cpp-enumdisplaysettings-function-examples.html but wasn't much help, same for https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-changedisplaysettingsa
Upvotes: 2
Views: 258
Reputation: 775
I wrote about 2% of this answer myself, and the rest came from pointystick on discord - thanks to them! The solution is a bit lazy, but it's so fast that for most that won't matter. With no cmd line args it will just set the display to the default recommendation, else with 2 cmd line args it can reset your display if it finds a match
import winim/lean
import os
import strutils
var modeToFind = (width: 1920, height: 1080, bitsPerPixel: 32,
refreshRate: 60)
var reset = 0
type ModeNotFoundError = object of CatchableError
proc getDisplayMode(): DEVMODEW =
## Finds the wanted screen resolution or raises a ModeNotFoundError.
var
nextMode: DWORD = 0
mode: DEVMODEW
while EnumDisplaySettings(nil, nextMode, mode) != 0:
echo $mode.dmPelsWidth & " x " & $mode.dmPelsHeight &
" x " & $mode.dmBitsPerPel &
" - " & $mode.dmDisplayFrequency
inc nextMode
if (mode.dmPelsWidth == modeToFind.width) and
(mode.dmPelsHeight == modeToFind.height):
echo "Found it!"
return mode
if(reset==1):
return mode
raise newException(ModeNotFoundError, "Cannot find wanted screen mode")
proc changeResolution(): bool =
## Actually changes the resolution. The return value indicates if it worked.
result = false
try:
let wantedMode = getDisplayMode()
result = ChangeDisplaySettings(wantedMode.unsafeAddr, 0.DWORD) == DISP_CHANGE_SUCCESSFUL
except ModeNotFoundError: discard
when isMainModule:
var
cxScreen:int32 = 0 #= GetSystemMetrics(SM_CXSCREEN)
cyScreen:int32 = 0 # = GetSystemMetrics(SM_CYSCREEN)
try:
cxScreen = (int32) parseInt(paramStr(1))
cyScreen = (int32) parseInt(paramStr(2))
modeToFind.width = cxScreen
modeToFind.height = cyScreen
except:
reset = 1
if not changeResolution():
echo "Change Resolution Failed"
Upvotes: 2