Brynn Mahsman Brynn Mahsman - 3 months ago 14
C Question

ChangeDisplaySettings succeeds yet does nothing. How do I get it to work?

I am trying to use ChangeDisplaySettings to change the desktop resolution of the default display device. However, when I execute my function (

set_resolution
), ChangeDisplaySettings always succeeds despite making no apparent change to my desktop resolution (the return code is always DISP_CHANGE_SUCCESSFUL).

I have tried every value for dwFlags, yet for each value I get the same result. I have tried multiple resolutions that my display should support, yet I get the same result. My display is 16:9, native 1920x1080. I've tried, for example, 1280x720.

I have tried executing
set_resolution
at the same time as creating the window and also I have tried executing the function on every
WM_ACTIVATE
event.

LONG set_resolution(uint32_t width, uint32_t height)
{
DEVMODE dm;

dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
dm.dmBitsPerPel = 32;
dm.dmDisplayFrequency = 60;
dm.dmFields =
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_BITSPERPEL |
DM_DISPLAYFREQUENCY;

DWORD flags =
0;
//CDS_FULLSCREEN;
//CDS_GLOBAL;
//CDS_NORESET;
//CDS_RESET;
//CDS_SET_PRIMARY;
//CDS_TEST;
//CDS_UPDATEREGISTRY;

LONG code = ChangeDisplaySettings(&dm, flags);

if (code == DISP_CHANGE_SUCCESSFUL)
{
printf("Display change successful [%dx%d]: %d", width, height, flags);
}
else
{
printf("Display change failed [%dx%d]: %d", width, height, code);
}

return code;
}

Answer

Zero the memory first, then set dmSize. Call EnumDisplaySettings to initialize the other members.

It would be a good idea to have a routine to undo changes automatically in case the settings were incompatible and resulted in black screen...

DEVMODE dm;
memset(&dm, 0, sizeof(dm));
dm.dmSize = sizeof(dm);

if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
{
    int savew = dm.dmPelsWidth;
    int saveh = dm.dmPelsHeight;
    dm.dmPelsWidth = width;
    dm.dmPelsHeight = height;

    LONG result = ChangeDisplaySettings(&dm, 0);
    if (result == DISP_CHANGE_SUCCESSFUL)
    {
        printf("okay\n");

        //Add a dialog to ask the user to confirm.
        //The dialog should close automatically if user is unable to confirm
        //if (confirm()) return;
        Sleep(5000);

        dm.dmPelsWidth = savew;
        dm.dmPelsHeight = saveh;
        ChangeDisplaySettings(&dm, 0);
    }
    else
    {
        printf("error\n");
    }
}

Edit, fixed typo. I meant to say call EnumDisplaySettings to initialize DEVMODE's members

Comments