Change 2nd Monitor Display Setting to Duplicate

Started by
1 comment, last by gretty 11 years, 1 month ago

Hello

I am attempting to programatically make the 2nd Monitor have a duplicate display. My function below should change the 2nd monitors display to 'duplicate display', ie, make the 2nd monitor display everything that is on the 1st/Primary monitor.

My Problem: When I run my function it successfully finds the 2nd monitor and it changes that monitors display x coordinate to 0, ie, the left of the primary monitor screen by changing the DEVMODE dmPosition.x property. Both of my 2 monitors refresh themselves(they go black then reshow their screen) but the 2nd monitor still has the extended display instead of a duplicate display.

Any ideas how I can make my 2nd Monitor have a duplicate display?

Some relevant information:
- My 2nd monitor is a LCD TV and is connected to my laptop via HDMI
- My function code is exacty the same as the example on this MSDN Page that describes how to attach a 2nd monitor without having to restart. I have changed LINE 30 though.
- I am aware I can change the display on Windows 7 using one WinAPI function call but I need my program to work on Windows 2000 and up.


// From http://support.microsoft.com/kb/308216/en-gb Title: You must restart...
    BOOL TVManager::AddUnattachedDisplayDeviceToDesktop()
    {
        DWORD DispNum = 0;
        DISPLAY_DEVICE DisplayDevice;
        DEVMODE defaultMode;
        HDC hdc;
        int nWidth;
        BOOL bFoundSecondary = FALSE;

        hdc    = GetDC(0);
        nWidth = GetDeviceCaps(hdc, HORZRES);
        ReleaseDC(0, hdc);

        // Initialize DisplayDevice.
        ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
        DisplayDevice.cb = sizeof(DisplayDevice);

        // Get display devices.
        while ((EnumDisplayDevices(NULL, DispNum, &DisplayDevice, 0)) && (bFoundSecondary == FALSE))
        {
            ZeroMemory(&defaultMode, sizeof(DEVMODE));
            defaultMode.dmSize = sizeof(DEVMODE);
            if (!EnumDisplaySettings((LPTSTR)DisplayDevice.DeviceName, ENUM_REGISTRY_SETTINGS, &defaultMode)) {
                printf("1\n");
                return FALSE; // Store default failed
            }

            if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) {
                //Found the first secondary device.
                _tprintf(_T("Found the first secondary device: Name: %s, Pos: %d, Width: %d\n"), DisplayDevice.DeviceName, defaultMode.dmPosition.x, nWidth);
                bFoundSecondary              = TRUE;
                defaultMode.dmPosition.x = 0; // LINE CHANGED: ONLY CHANGE FROM MSDN'S CODE
                defaultMode.dmFields      = DM_POSITION;
                ChangeDisplaySettingsEx((LPTSTR)DisplayDevice.DeviceName, &defaultMode, NULL, CDS_NORESET|CDS_UPDATEREGISTRY, NULL);
                _tprintf(_T("Check for error: %u\n"), GetLastError()); // prints "Check for error: 0" which means no error occurred

                // A second call to ChangeDisplaySettings updates the monitor.
                ChangeDisplaySettings(NULL, 0);
                _tprintf(_T("Check for error: %u\n"), GetLastError()); // prints "Check for error: 0" which means no error occurred
            }

            // Reinitialize DisplayDevice.
            ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
            DisplayDevice.cb = sizeof(DisplayDevice);
            DispNum++;
        } // End while the display devices.

        return TRUE;
    }
 

Advertisement

Well, i've been playing around with your code in VMWare using 2 monitors, and made some progress, but could't make it work either.

First of all, this line

defaultMode.dmFields = DM_POSITION;

should be

defaultMode.dmFields |= DM_POSITION;

Now ChangeDisplaySettingsEx return DISP_CHANGE_SUCCESSFUL instead of DISP_CHANGE_BADMODE.

I tryed 2-3 different flags combinaison and tryed it, but to no avail. At least you're a little closer now.

Yes, even MS make bugs.smile.png

Edit: Or im wrong and this isn't supported...

Edit2: Just realized that i can't find a way to do this in wmware normally, but i recall being able to do it via nvidia control panel, might be why it dosent work. I really have no idea, sorry. lol, at least i tried...

Thanks.

According to this answer it appears I need to focus on enabling/disabling Display Drivers to toggle duplicate / extend display.

This topic is closed to new replies.

Advertisement