我正在编写一个应用程序,在双视图或克隆中自动切换Windows XP的桌面是有帮助的。该应用程序使用一个小的wxWidgets窗口用于GUI。在GUI中有一个可以在dualview和克隆之间轻松切换的按钮会很不错。
是否有c / c ++库可以访问控制双视图或克隆?
答案 0 :(得分:2)
查看this script,据我所知,应该启用或禁用多视图。虽然它是用脚本语言编写的,但它确实利用了正常的WinAPI函数,因此您应该能够通过查看它们来了解发生的情况。
据我所知,似乎禁用第二台显示器是通过在第二台显示器上调用ChangeDisplaySettingsEx并提供宽度,高度,颜色深度和刷新率为0来完成的。要重新启用它,一可能会使用有效参数第二次调用ChangeDisplaySettingsEx。
无论如何,尝试脚本可能是最好的(解释器可以在主页上免费获得)并查看它是否实现了您正在寻找的功能(请注意,脚本是针对两个特定显示器的硬编码,您将必须用监视器的名称替换它们才能使它工作。)
答案 1 :(得分:0)
以下代码的工作原理。它不会保持显示器分辨率。
void AppFrame::OnButtonModify(wxCommandEvent& event)
{
static bool bSwitch = false;
if (bSwitch)
{
ExtendExternalDisplay();
}
else
{
CloneExternalDisplay();
}
bSwitch = !bSwitch;
}
void AppFrame::ExtendExternalDisplay()
{
int nModeSwitch = NULL;
DEVMODE dmPrimary, dmSecondary, dmThird, savedmSecondary;
#define szPrimaryDisplay TEXT( "\\\\.\\DISPLAY1" )
#define szSecondaryDisplay TEXT( "\\\\.\\DISPLAY2" )
#define szThirdDisplay TEXT( "\\\\.\\DISPLAY3" )
ZeroMemory( &dmPrimary, sizeof(dmPrimary) );
dmPrimary.dmSize = sizeof(dmPrimary);
ZeroMemory( &dmSecondary, sizeof(dmSecondary) );
dmSecondary.dmSize = sizeof(dmSecondary);
ZeroMemory( &dmThird, sizeof(dmThird) );
dmThird.dmSize = sizeof(dmThird);
ZeroMemory( &dmThird, sizeof(dmThird) );
dmThird.dmSize = sizeof(dmThird);
BOOL result;
HDC handle;
DWORD iDevNum = 0;
DWORD dwFlags = 0;
DISPLAY_DEVICE lpDisplayDevice, lpDisplayDeviceOne, lpDisplayDeviceTwo;
ZeroMemory(&lpDisplayDevice, sizeof(lpDisplayDevice));
ZeroMemory(&lpDisplayDeviceOne, sizeof(lpDisplayDeviceOne));
ZeroMemory(&lpDisplayDeviceTwo, sizeof(lpDisplayDeviceTwo));
lpDisplayDevice.cb = sizeof(lpDisplayDevice);
lpDisplayDeviceOne.cb = sizeof(lpDisplayDeviceOne);
lpDisplayDeviceTwo.cb = sizeof(lpDisplayDeviceTwo);
// All this does is confirm the number of display devices the graphics board is capable of handling
while(EnumDisplayDevices(NULL, iDevNum, &lpDisplayDevice, dwFlags))
{
if (iDevNum == 0)
{
lpDisplayDeviceOne = lpDisplayDevice;
TRACE("DeviceName: '%s'\n", lpDisplayDeviceOne.DeviceName);
TRACE("DeviceString: '%s'\n", lpDisplayDeviceOne.DeviceString);
TRACE("Flags: %08X %s%s\n", lpDisplayDeviceOne.StateFlags,((lpDisplayDeviceOne.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) ? "Desktop " : ""), ((lpDisplayDeviceOne.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) ? "Primary" : ""));
}
if (iDevNum == 1)
{
lpDisplayDeviceTwo = lpDisplayDevice;
TRACE("DeviceName: '%s'\n", lpDisplayDeviceTwo.DeviceName);
TRACE("DeviceString: '%s'\n", lpDisplayDeviceTwo.DeviceString);
TRACE("Flags: %08X %s%s\n", lpDisplayDeviceTwo.StateFlags,((lpDisplayDeviceTwo.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) ? "Desktop " : ""), ((lpDisplayDeviceTwo.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) ? "Primary" : ""));
}
iDevNum ++;
}
// load DISPLAY1 monitor information // ENUM_CURRENT_SETTINGS
if (!EnumDisplaySettings(szPrimaryDisplay, ENUM_REGISTRY_SETTINGS, (DEVMODE*)&dmPrimary))
{
TRACE("EnumDisplaySettings unable to enumerate primary display\n");
return;
}
if (!EnumDisplaySettings(szSecondaryDisplay, ENUM_REGISTRY_SETTINGS, (DEVMODE*)&dmSecondary))
TRACE("EnumDisplaySettings unable to enumerate secondary display display\n");
// these don't enumerate in clone mode
if (!EnumDisplaySettings(szSecondaryDisplay, ENUM_CURRENT_SETTINGS, (DEVMODE*)&savedmSecondary))
TRACE("EnumDisplaySettings unable to enumerate secondary display using ENUM_CURRENT_SETTINGS settings\n");
// disable a display, doesn't work
// nModeSwitch = ChangeDisplaySettingsEx (szSecondaryDisplay, NULL, NULL, NULL, NULL);
// CDdx::ErrorDisplayDevice(nModeSwitch); // test and TRACE result
dmPrimary.dmFields = DM_POSITION;
dmPrimary.dmPosition.x = 0; // set DISPLAY1 as the primary display
dmPrimary.dmPosition.y = 0; // set DISPLAY1 as the primary display
// set DISPLAY1 as primary display (dmPosition.x = 0)
nModeSwitch = ChangeDisplaySettingsEx (szPrimaryDisplay, (DEVMODE*)&dmPrimary, NULL, (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
// CDdx::ErrorDisplayDevice(nModeSwitch); // test and TRACE result
// despite the other lines of code this next line is neccesary to wake the video projector
dmSecondary = dmPrimary;
dmSecondary.dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT;
dmSecondary.dmPosition.x = dmPrimary.dmPelsWidth + 1;
dmSecondary.dmPosition.y = 0;
dmSecondary.dmPelsWidth = dmPrimary.dmPelsWidth; // resize the primary display to match the secondary display
dmSecondary.dmPelsHeight = dmPrimary.dmPelsHeight; // resize the primary display to match the secondary display
nModeSwitch = ChangeDisplaySettingsEx (szSecondaryDisplay, (DEVMODE*)&dmSecondary, NULL, (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
// CDdx::ErrorDisplayDevice(nModeSwitch); // test and TRACE result
// load DISPLAY3 monitor information
if (!EnumDisplaySettings(szThirdDisplay, ENUM_CURRENT_SETTINGS, (DEVMODE*)&dmThird))
{
TRACE("EnumDisplaySettings unable to enumerate third display display\n");
}
else
{
dmThird.dmPelsWidth = dmSecondary.dmPelsWidth; // resize the primary display to match the secondary display
dmThird.dmPelsHeight = dmSecondary.dmPelsHeight; // resize the primary display to match the secondary display
dmThird.dmPosition.x = -dmThird.dmPelsWidth; // set DISPLAY3 as the third display
dmPrimary.dmPosition.y = 0; // set DISPLAY1 as the third display
// set DISPLAY3 as third display (-dmThird.dmPelsWidth)
nModeSwitch = ChangeDisplaySettingsEx (szThirdDisplay, (DEVMODE*)&dmThird, NULL, (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
// CDdx::ErrorDisplayDevice(nModeSwitch); // test and TRACE result
}
// really important line makes the whole thing happen
nModeSwitch = ChangeDisplaySettingsEx (NULL, NULL, NULL, 0, NULL);
// CDdx::ErrorDisplayDevice(nModeSwitch); // test and TRACE result
}
void AppFrame::CloneExternalDisplay()
{
int nModeSwitch = NULL;
DEVMODE dmPrimary, dmSecondary, dmThird;
#define szPrimaryDisplay TEXT( "\\\\.\\DISPLAY1" )
#define szSecondaryDisplay TEXT( "\\\\.\\DISPLAY2" )
#define szThirdDisplay TEXT( "\\\\.\\DISPLAY3" )
ZeroMemory( &dmPrimary, sizeof(dmPrimary) );
dmPrimary.dmSize = sizeof(dmPrimary);
ZeroMemory( &dmSecondary, sizeof(dmSecondary) );
dmSecondary.dmSize = sizeof(dmSecondary);
ZeroMemory( &dmThird, sizeof(dmThird) );
// load DISPLAY1 monitor information
if (!EnumDisplaySettings(szPrimaryDisplay, ENUM_CURRENT_SETTINGS, (DEVMODE*)&dmPrimary))
{
TRACE("EnumDisplaySettings unable to enumerate primary display\n");
return;
}
if (!EnumDisplaySettingsEx(szSecondaryDisplay, ENUM_REGISTRY_SETTINGS, (DEVMODE*)&dmSecondary, 0))
TRACE("EnumDisplaySettings unable to enumerate secondary display display\n");
dmPrimary.dmFields = DM_POSITION;
dmPrimary.dmPosition.x = 0; // set DISPLAY1 as the primary display
dmPrimary.dmPosition.y = 0; // set DISPLAY1 as the primary display
// set DISPLAY1 as primary display (dmPosition.x = 0)
nModeSwitch = ChangeDisplaySettingsEx (szPrimaryDisplay, (DEVMODE*)&dmPrimary, NULL, (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
// CDdx::ErrorDisplayDevice(nModeSwitch); // test and TRACE result
// this should disable display
dmSecondary.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT;
dmSecondary.dmPelsWidth = 0; //dmPrimary.dmPelsWidth; // resize the primary display to match the secondary display
dmSecondary.dmPelsHeight = 0;//dmPrimary.dmPelsHeight; // resize the primary display to match the secondary display
// this should clone the display
dmSecondary.dmFields |= DM_POSITION;
dmSecondary.dmPosition.x = 0; // set DISPLAY1 as the primary display
dmSecondary.dmPosition.y = 0; // set DISPLAY1 as the primary display
nModeSwitch = ChangeDisplaySettingsEx (szSecondaryDisplay, (DEVMODE*)&dmSecondary, NULL, (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
// CDdx::ErrorDisplayDevice(nModeSwitch); // test and TRACE result
nModeSwitch = ChangeDisplaySettingsEx (NULL, NULL, NULL, 0, NULL); // set DISPLAY1 as the primary display
// CDdx::ErrorDisplayDevice(nModeSwitch); // test and TRACE result
}