1

我正在编写一个应用程序,它有助于在双视图或克隆 Windows XP 桌面之间自动切换。该应用程序使用一个小的 wxWidgets 窗口作为 GUI。如果在 GUI 中有一个可以在双视图和克隆之间轻松切换的按钮,那就太好了。

是否有 ac/c++ 库可以访问控制双视图或克隆?

4

2 回答 2

2

查看这个脚本,据我所知,它应该启用或禁用多视图。虽然它是用脚本语言编写的,但它确实利用了普通的 WinAPI 函数,因此您应该能够通过查看它们来找出正在发生的事情。

据我所知,似乎禁用第二台显示器是通过在第二台显示器上调用ChangeDisplaySettingsEx并提供宽度、高度、颜色深度和刷新率为 0 来完成的。要重新启用它,可以使用第二次调用 ChangeDisplaySettingsEx大概是有效的参数。

无论如何,最好尝试该脚本(解释器可在主页上免费获得)并查看它是否实现了您正在寻找的功能(请注意,该脚本是针对两个特定监视器进行硬编码的,您将不得不替换他们用你的显示器的名字让它工作)。

于 2009-09-15T17:23:20.570 回答
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    

}
于 2010-05-14T17:54:19.323 回答