我正在编写一个应用程序,它有助于在双视图或克隆 Windows XP 桌面之间自动切换。该应用程序使用一个小的 wxWidgets 窗口作为 GUI。如果在 GUI 中有一个可以在双视图和克隆之间轻松切换的按钮,那就太好了。
是否有 ac/c++ 库可以访问控制双视图或克隆?
我正在编写一个应用程序,它有助于在双视图或克隆 Windows XP 桌面之间自动切换。该应用程序使用一个小的 wxWidgets 窗口作为 GUI。如果在 GUI 中有一个可以在双视图和克隆之间轻松切换的按钮,那就太好了。
是否有 ac/c++ 库可以访问控制双视图或克隆?
查看这个脚本,据我所知,它应该启用或禁用多视图。虽然它是用脚本语言编写的,但它确实利用了普通的 WinAPI 函数,因此您应该能够通过查看它们来找出正在发生的事情。
据我所知,似乎禁用第二台显示器是通过在第二台显示器上调用ChangeDisplaySettingsEx并提供宽度、高度、颜色深度和刷新率为 0 来完成的。要重新启用它,可以使用第二次调用 ChangeDisplaySettingsEx大概是有效的参数。
无论如何,最好尝试该脚本(解释器可在主页上免费获得)并查看它是否实现了您正在寻找的功能(请注意,该脚本是针对两个特定监视器进行硬编码的,您将不得不替换他们用你的显示器的名字让它工作)。
下面的代码排序的作品。它不会保持显示器的分辨率。
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
}