Problems with ChangeDisplaySettingsEx [SOLVED]

Started by
2 comments, last by joanusdmentia 17 years, 6 months ago
I've recently starting modifying my fullscreen mode switching code to support multiple monitors (since I recently acquired a second monitor myself [grin]). I was previously using ChangeDisplaySettings(), which was working fine except for the fact that it only works on the primary display. I've changed over to using ChangeDisplaySettingsEx() so that I can specify which display to perform the mode switch on (namely, the same display as the window is on), but it's been giving all sorts of grief. This is what's happenning when I use ChangeDisplaySettingsEx(): * Icons are rearranged as though I wasn't specifying CDS_FULLSCREEN (which I am) * If the background is changed before running the program, it gets reset to the previous image * Every now and then I'll find an order of operations that will give me a BSOD I'm running WinXP SP2 with a GeForce 6600GT card and have tried both the latest and a slightly older (84.25) version of the nVidia drivers without any luck. The instant I swap back to using ChangeDisplaySettings() everything works as expected, but I can only use the primary display. For those who feel like looking at some code, here's the relevant bits:

    bool Window::EnableFullscreen(std::size_t w, std::size_t h, std::size_t bpp)
    {
        // Find out the name of the device this window
        // is on (this is for multi-monitor setups)
        HMONITOR hMonitor = MonitorFromWindow(m_handle->hWnd, MONITOR_DEFAULTTOPRIMARY);
        MONITORINFOEX monInfo;
        memset(&monInfo, 0, sizeof(MONITORINFOEX));
        monInfo.cbSize = sizeof(MONITORINFOEX);
        GetMonitorInfo(hMonitor, &monInfo);

        // Find the requested device mode
        DEVMODE dmode;
        bool foundMode = false;
        memset(&dmode, 0, sizeof(DEVMODE));
        dmode.dmSize = sizeof(DEVMODE);
        for(int i=0 ; EnumDisplaySettings(monInfo.szDevice, i, &dmode) && !foundMode ; ++i)
        {
            foundMode = (dmode.dmPelsWidth==(DWORD)w) &&
                        (dmode.dmPelsHeight==(DWORD)h) &&
                        (dmode.dmBitsPerPel==(DWORD)bpp);
        }
        if(!foundMode) return false;
        dmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

        // If we're switching from a windowed mode to this fullscreen
        // mode, save some information about the window so that it can
        // be restored when switching back to windowed mode
        DWORD style=0, exstyle=0;
        if(!m_fullscreen)
        {
            // Save the current window position/size
            RECT rect;
            GetWindowRect(m_handle->hWnd, &rect);
            m_windowedX = rect.left;
            m_windowedY = rect.top;
            m_windowedWidth = rect.right - rect.left;
            m_windowedHeight = rect.bottom - rect.top;

            // Save the window style and set it for fullscreen mode
            style = GetWindowLongPtr(m_handle->hWnd, GWL_STYLE);
            exstyle = GetWindowLongPtr(m_handle->hWnd, GWL_EXSTYLE);
            SetWindowLongPtr(m_handle->hWnd, GWL_STYLE, style & (~WS_OVERLAPPEDWINDOW));
            SetWindowLongPtr(m_handle->hWnd, GWL_EXSTYLE, exstyle | WS_EX_APPWINDOW | WS_EX_TOPMOST);
        }

        // Attempt to change the resolution
        LONG ret = ChangeDisplaySettingsEx(monInfo.szDevice, &dmode, NULL, CDS_FULLSCREEN, NULL);
        //LONG ret = ChangeDisplaySettings(&dmode, CDS_FULLSCREEN);
        bool ok = (ret == DISP_CHANGE_SUCCESSFUL);
        if(ok) m_fullscreen = true;

        // If all was good resize & reposition the window
        // to match the new resolution on the correct monitor
        if(ok)
        {
            // We need to call GetMonitorInfo() again becase
            // details may have changed with the resolution
            GetMonitorInfo(hMonitor, &monInfo);

            // Set the window's size and position so
            // that it covers the entire screen
            SetWindowPos(m_handle->hWnd, NULL, monInfo.rcMonitor.left, monInfo.rcMonitor.top, (int)w, (int)h,
                         SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREPOSITION | SWP_NOZORDER);
        }

        // If the attempt failed and we weren't already
        // in fullscreen mode, restore the window styles
        else if(!m_fullscreen)
        {
            SetWindowLongPtr(m_handle->hWnd, GWL_STYLE, style);
            SetWindowLongPtr(m_handle->hWnd, GWL_EXSTYLE, exstyle);
        }

        return ok;
    }

    void Window::DisableFullscreen()
    {
        if(m_fullscreen)
        {
            // Find out the name of the device this window
            // is on (this is for multi-monitor setups)
            HMONITOR hMonitor = MonitorFromWindow(m_handle->hWnd, MONITOR_DEFAULTTOPRIMARY);
            MONITORINFOEX monInfo;
            memset(&monInfo, 0, sizeof(MONITORINFOEX));
            monInfo.cbSize = sizeof(MONITORINFOEX);
            GetMonitorInfo(hMonitor, &monInfo);

            // Restore the display resolution
            ChangeDisplaySettingsEx(monInfo.szDevice, NULL, NULL, 0, NULL);
            //ChangeDisplaySettings(NULL, 0);
            m_fullscreen = false;

            // Restore the window styles
            DWORD style = GetWindowLongPtr(m_handle->hWnd, GWL_STYLE);
            DWORD exstyle = GetWindowLongPtr(m_handle->hWnd, GWL_EXSTYLE);
            SetWindowLongPtr(m_handle->hWnd, GWL_STYLE, style | WS_OVERLAPPEDWINDOW);
            SetWindowLongPtr(m_handle->hWnd, GWL_EXSTYLE, exstyle & (~(WS_EX_APPWINDOW | WS_EX_TOPMOST)));

            // Restore the window size/position
            SetPosition(m_windowedX, m_windowedY);
            SetSize(m_windowedWidth, m_windowedHeight);
        }
    }


[Edited by - joanusdmentia on October 8, 2006 5:00:50 AM]
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V
Advertisement
SOLVED IT!!!! For anyone else who runs into this problem, disable nVidia's nView utility. It seems they hook into ChangeDisplaySettings() correctly but not ChangeDisplaySettingsEx().
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V
seems like something you will have to report to their driver dev. team.

Projects: Top Down City: http://mathpudding.com/

Yep, will be throwing together a minimal code example that reproduces the bug and send that off to them.
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V

This topic is closed to new replies.

Advertisement