Created
July 27, 2013 19:39
-
-
Save RavuAlHemio/6096027 to your computer and use it in GitHub Desktop.
Changes the resolution of a display on Windows. Useful for fixing the size of Wine's virtual desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Changes the resolution of a display on Windows. | |
* Useful for fixing the size of Wine's virtual desktop. | |
* | |
* Released into the public domain. | |
* http://creativecommons.org/publicdomain/zero/1.0/ | |
*/ | |
#include <stdio.h> | |
#include <wchar.h> | |
#include <windows.h> | |
const wchar_t *progname = L"winfixres"; | |
__attribute__((noreturn)) | |
static void usageQuit(void) | |
{ | |
fwprintf(stderr, | |
L"Usage: %ls -l\n" | |
L" %ls DEVICENUM WIDTH HEIGHT\n", | |
progname, progname | |
); | |
exit(1); | |
} | |
static size_t parseUIntOrQuit(const wchar_t *s) | |
{ | |
wchar_t *end; | |
size_t ret; | |
if (s == NULL) | |
{ | |
fwprintf(stderr, L"Expected number, got NULL string.\n"); | |
usageQuit(); | |
} | |
else if (s[0] == L'\0') | |
{ | |
fwprintf(stderr, L"Expected number, got zero-length string.\n"); | |
usageQuit(); | |
} | |
errno = 0; | |
ret = wcstoul(s, &end, 0); | |
if (errno != 0) | |
{ | |
fwprintf(stderr, L"Error parsing number '%ls'.\n", s); | |
usageQuit(); | |
} | |
else if (end[0] != L'\0') | |
{ | |
fwprintf(stderr, L"Found invalid character (%lc) in number '%ls'.\n", end[0], s); | |
usageQuit(); | |
} | |
return ret; | |
} | |
static void listDevices(void) | |
{ | |
DWORD i; | |
DISPLAY_DEVICEW ddev; | |
ddev.cb = sizeof(ddev); | |
for (i = 0; ; ++i) | |
{ | |
if (!EnumDisplayDevicesW(NULL, i, &ddev, 0)) | |
{ | |
/* failed; probably no more display devices */ | |
break; | |
} | |
wprintf(L"%3lu: %ls\n", i, ddev.DeviceString); | |
} | |
} | |
static int changeRes(size_t devnum, size_t w, size_t h) | |
{ | |
DISPLAY_DEVICEW ddev; | |
DEVMODEW dm; | |
LONG ret; | |
ddev.cb = sizeof(ddev); | |
dm.dmSize = sizeof(dm); | |
dm.dmDriverExtra = 0; | |
if (!EnumDisplayDevicesW(NULL, devnum, &ddev, 0)) | |
{ | |
fwprintf(stderr, L"Display #%lu doesn't exist.\n", devnum); | |
return 2; | |
} | |
if (!EnumDisplaySettingsExW( | |
ddev.DeviceName, | |
ENUM_CURRENT_SETTINGS, | |
&dm, | |
0 | |
)) | |
{ | |
fwprintf(stderr, L"Failed to fetch current display settings.\n"); | |
return 2; | |
} | |
dm.dmPelsWidth = w; | |
dm.dmPelsHeight = h; | |
dm.dmFields |= (DM_PELSWIDTH | DM_PELSHEIGHT); | |
ret = ChangeDisplaySettingsExW( | |
ddev.DeviceName, | |
&dm, | |
NULL, | |
0, | |
NULL | |
); | |
switch (ret) | |
{ | |
case DISP_CHANGE_SUCCESSFUL: | |
return 0; | |
case DISP_CHANGE_BADDUALVIEW: | |
fwprintf(stderr, L"Failed to change video mode: bad dual view.\n"); | |
return 2; | |
case DISP_CHANGE_BADFLAGS: | |
fwprintf(stderr, L"Failed to change video mode: bad flags.\n"); | |
return 2; | |
case DISP_CHANGE_BADMODE: | |
fwprintf(stderr, L"Failed to change video mode: unsupported mode.\n"); | |
return 2; | |
case DISP_CHANGE_BADPARAM: | |
fwprintf(stderr, L"Failed to change video mode: invalid parameter.\n"); | |
return 2; | |
case DISP_CHANGE_FAILED: | |
fwprintf(stderr, L"Failed to change video mode: driver failed the mode.\n"); | |
return 2; | |
case DISP_CHANGE_NOTUPDATED: | |
fwprintf(stderr, L"Warning: Failed to store video mode into registry.\n"); | |
return 0; | |
case DISP_CHANGE_RESTART: | |
fwprintf(stderr, L"Warning: The computer must be restarted for this mode to work.\n"); | |
return 0; | |
} | |
return 3; | |
} | |
int wmain(int argc, wchar_t **argv) | |
{ | |
if (argc > 0) | |
{ | |
progname = argv[0]; | |
} | |
if (argc == 2 && argv[1][0] == '-') | |
{ | |
if (wcscmp(argv[1], L"-l") == 0) | |
{ | |
listDevices(); | |
} | |
else | |
{ | |
usageQuit(); | |
} | |
} | |
else if (argc == 4) | |
{ | |
size_t devnum = parseUIntOrQuit(argv[1]); | |
size_t w = parseUIntOrQuit(argv[2]); | |
size_t h = parseUIntOrQuit(argv[3]); | |
return changeRes(devnum, w, h); | |
} | |
else | |
{ | |
usageQuit(); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment