May Oakes
May Oakes

Reputation: 4629

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;
}

Upvotes: 4

Views: 2763

Answers (1)

Barmak Shemirani
Barmak Shemirani

Reputation: 31599

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

Upvotes: 3

Related Questions