Skip to content

Instantly share code, notes, and snippets.

@RavuAlHemio
Created July 27, 2013 19:39
Show Gist options
  • Save RavuAlHemio/6096027 to your computer and use it in GitHub Desktop.
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.
/**
* 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