Change 2nd Monitor Display Setting to Duplicate

只愿长相守 提交于 2019-12-22 12:14:12

问题


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

回答1:


Windows XP and earlier uses a different display driver model (XPDM) from Vista and later (WDDM). Mirroring on XPDM depends very much on your graphics card vendor. The general idea is that for extending the desktop, you provide an extend driver; for mirroring a portion of the desktop, you provide a mirror driver.

In most cases, each extend driver is responsible for one output on your graphics card. Let's say that you have a dual DVI card, then you should see two extend drivers in your Device Manager, each is responsible for one of the DVI port. When you want to set your monitor to extend the desktop, you enable the extend driver and give it a sensible location.

Mirroring is trickier. This is where the behaviour can vary a bit between the different card vendors. From the perspective of the OS, this is what's happening. The extend driver associated with the graphics card port is disabled. The mirror driver is enabled if it was not enabled already. The mirror driver is then placed at (0, 0). Then some trickery happens inside your graphics card/driver and the monitor is showing what's inside the mirror driver's screen buffer.

In order to set a monitor into mirror mode on XPDM, you need find the extend driver it's currently showing stuff from and disable it. This may be all you have to do. Some of the vendors will automatically do the rest for you and start mirroring the primary display. Some vendors will do whatever your monitor was doing last before it was put into extend mode. If you find your monitor not showing anything, you can try to enable the mirror driver. If you manage to find the mirror driver and enable it, what happens after is anyone's guess. There isn't a universal way to wire up a monitor to a mirror driver.



来源:https://stackoverflow.com/questions/15154542/change-2nd-monitor-display-setting-to-duplicate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!