我试图以编程方式使第二台显示器重复显示。我的下面的功能应该将第二个显示器显示更改为“重复显示”,即使第二个显示器显示第一个/主显示器上的所有内容。
我的问题:当我运行我的功能时,它成功找到第二个监视器并通过更改DEVMODE dmPosition将监视器显示x坐标更改为0,即主监视器屏幕的左侧。 x属性。我的两个显示器都自我刷新(它们变黑然后重新显示它们的屏幕)但第二个显示器仍然具有扩展显示而不是重复显示。
任何想法如何让我的第二台显示器重复显示?
一些相关信息:
- 我的第二台显示器是液晶电视,通过HDMI连接到我的笔记本电脑
- 我的功能代码与此MSDN Page上的示例完全相同,该示例描述了如何在不重新启动的情况下连接第二个监视器。我已经改变了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;
}
答案 0 :(得分:3)
Windows XP及更早版本使用Vista及更高版本(WDDM)的不同显示驱动程序模型(XPDM)。镜像XPDM在很大程度上取决于您的显卡供应商。一般的想法是,为了扩展桌面,你提供了一个扩展驱动程序;为了镜像桌面的一部分,你提供了一个镜像驱动程序。
在大多数情况下,每个扩展驱动程序负责显卡上的一个输出。假设你有一个双DVI卡,那么你应该在你的设备管理器中看到两个扩展驱动程序,每个驱动程序都负责一个DVI端口。如果要将显示器设置为扩展桌面,可以启用扩展驱动程序并为其提供合理的位置。
镜像比较棘手。这是不同卡供应商之间行为可能有所不同的地方。从操作系统的角度来看,这就是正在发生的事情。与显卡端口关联的扩展驱动程序被禁用。如果镜像驱动程序尚未启用,则会启用它。然后将镜像驱动器置于(0,0)。然后在你的显卡/驱动程序中发生了一些技巧,显示器正在显示镜像驱动程序屏幕缓冲区内的内容。
为了在XPDM上将监视器设置为镜像模式,您需要找到它当前显示内容的扩展驱动程序并禁用它。这可能是你所要做的。一些供应商会自动为您完成剩下的工作并开始镜像主显示器。有些供应商在进入扩展模式之前会做你的显示器最后做的任何事情。如果发现显示器没有显示任何内容,可以尝试启用镜像驱动程序。如果您设法找到镜像驱动程序并启用它,那么任何人猜测之后会发生什么。没有通用的方法将显示器连接到镜像驱动程序。