2

我正在尝试以编程方式使第二个监视器具有重复显示。我下面的功能应该将第二台显示器的显示更改为“重复显示”,即让第二台显示器显示第一台/主显示器上的所有内容。

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

有什么想法可以让我的第二台显示器重复显示吗?

一些相关信息:
- 我的第二台显示器是液晶电视,并通过 HDMI 连接到我的笔记本电脑- 我的功能代码与此MSDN 页面
上的示例完全相同,该页面描述了如何连接第二台显示器而无需重新启动。不过,我已经更改了 LINE 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("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;
}
4

1 回答 1

4

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

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

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

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.

于 2013-03-01T16:11:53.937 回答