更改第二显示器显示设置为复制



我正试图以编程方式使第二个监视器具有重复显示。下面的函数应该将第二个显示器的显示更改为"重复显示",即使第二个显示器显示第一个/主显示器上的所有内容。

我的问题:当我运行我的函数时,它成功地找到了第二个监视器,它改变了监视器显示x坐标为0,即通过改变DEVMODE dmPosition的主监视器屏幕的左侧。x属性。我的两个显示器都自动刷新(它们变黑然后重新显示屏幕),但第二个显示器仍然有扩展显示而不是重复显示。

任何想法我可以让我的第二个显示器有一个重复的显示?

一些相关信息:
-我的第二个显示器是液晶电视,通过HDMI连接到我的笔记本电脑
-我的功能代码与此MSDN页面上的示例完全相同,该页面描述了如何在无需重新启动的情况下附加第二个监视器。不过我已经改了第30行。
-我知道我可以使用一个WinAPI函数调用来改变Windows 7上的显示,但我需要我的程序在Windows 2000及更高版本上工作。

// 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("1n");
            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: %dn"), 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: %un"), 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: %un"), 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;
}

Windows XP和更早的版本使用与Vista和更高版本(WDDM)不同的显示驱动模型(XPDM)。XPDM上的镜像在很大程度上取决于您的显卡供应商。一般的想法是,为了扩展桌面,你提供一个扩展驱动程序;要镜像桌面的一部分,您可以提供镜像驱动程序。

在大多数情况下,每个扩展驱动程序负责图形卡上的一个输出。假设您有双DVI卡,那么您应该在设备管理器中看到两个扩展驱动程序,每个扩展驱动程序负责一个DVI端口。当你想设置你的显示器扩展桌面,你启用扩展驱动程序,并给它一个合理的位置。

镜像更棘手。这就是不同卡供应商之间的行为可能有所不同的地方。从操作系统的角度来看,这就是正在发生的事情。与显卡端口关联的扩展驱动被禁用。如果尚未启用镜像驱动程序,则启用镜像驱动程序。然后,镜像驱动程序被放置在(0,0)。然后,在你的显卡/驱动程序中发生了一些欺骗,监视器显示镜像驱动程序的屏幕缓冲区内的内容。

为了在XPDM上将监视器设置为镜像模式,您需要找到当前显示内容的扩展驱动程序并禁用它。这可能就是你所要做的。有些供应商会自动为您完成其余的工作,并开始镜像主显示。一些供应商会做你的显示器在进入扩展模式之前最后做的任何事情。如果您发现监视器没有显示任何内容,您可以尝试启用镜像驱动程序。如果您设法找到镜像驱动程序并启用它,那么接下来会发生什么就无人知晓了。没有一种通用的方法将监视器连接到镜像驱动程序。

最新更新