Visual c++ 将窗口放置在较大的显示器上

Visual c++ 将窗口放置在较大的显示器上,visual-c++,mfc,Visual C++,Mfc,我在笔记本电脑上使用额外的21英寸显示器。当我点击任务栏上的图标时,它通常会在较小的笔记本电脑屏幕上打开。然后我必须将它拖到较大的显示器上才能工作 我已经把重点放在了代码上,我们可以将代码更改为自动将TightVNC查看器移动到更大的屏幕上(如果可用) 现行守则: void CentreWindow(HWND hwnd) { RECT winrect, workrect; // Find how large the desktop work area is System

我在笔记本电脑上使用额外的21英寸显示器。当我点击任务栏上的图标时,它通常会在较小的笔记本电脑屏幕上打开。然后我必须将它拖到较大的显示器上才能工作

我已经把重点放在了代码上,我们可以将代码更改为自动将TightVNC查看器移动到更大的屏幕上(如果可用)

现行守则:

void CentreWindow(HWND hwnd)
{
    RECT winrect, workrect;

    // Find how large the desktop work area is
    SystemParametersInfo(SPI_GETWORKAREA, 0, &workrect, 0);
    int workwidth = workrect.right -  workrect.left;
    int workheight = workrect.bottom - workrect.top;

    // And how big the window is
    GetWindowRect(hwnd, &winrect);
    int winwidth = winrect.right - winrect.left;
    int winheight = winrect.bottom - winrect.top;
    // Make sure it's not bigger than the work area
    winwidth = min(winwidth, workwidth);
    winheight = min(winheight, workheight);

    // Now centre it
    SetWindowPos(hwnd, 
        HWND_TOP,
        workrect.left + (workwidth-winwidth) / 2,
        workrect.top + (workheight-winheight) / 2,
        winwidth, winheight, 
        SWP_SHOWWINDOW);  
    SetForegroundWindow(hwnd);
}
我想,首先我需要查询总显示,找到最大的显示,然后将窗口定位在它的中心。
有人能告诉我构建此逻辑所使用的参考代码吗?

首先,您需要决定要在哪个显示器上显示。这需要枚举可用的显示器,这将使您能够访问其属性。从中,您可以决定要用什么算法来选择最大的显示器h一个支持最多的颜色,哪一种颜色最左边,等等

使用Windows API函数枚举可用的显示非常简单,但确实需要大量代码。下面是一个经过测试且完全正常工作的实现:

struct MonitorInfo
{
   HMONITOR hMonitor;
   RECT     rcMonitor;

   MonitorInfo(HMONITOR hMonitor, RECT rcMonitor)
      : hMonitor (hMonitor)
      , rcMonitor(rcMonitor)
   { }
};

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor,
                              HDC   /* hdcMonitor */,
                              RECT*    prcMonitor,
                              LPARAM   dwData)
{
   ASSERT(hMonitor   != NULL);
   ASSERT(prcMonitor != nullptr);
   ASSERT(dwData     != NULL);

   MONITORINFO mi;
   mi.cbSize = sizeof(mi);
   VERIFY(::GetMonitorInfo(hMonitor, &mi));

   if ((mi.dwFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == DISPLAY_DEVICE_MIRRORING_DRIVER)
   {
      // Skip mirroring drivers that do not correspond to display screens.
      return TRUE;
   }
   else
   {
      auto* const pInfo = reinterpret_cast<std::vector<MonitorInfo>*>(dwData);
      ASSERT(pInfo != nullptr);

      pInfo->emplace_back(hMonitor, *prcMonitor);

      return TRUE;
   }
}

std::vector<MonitorInfo> GetInfoForAllMonitors()
{
   const int cMonitors = ::GetSystemMetrics(SM_CMONITORS);

   std::vector<MonitorInfo> result;
   result.reserve(cMonitors);

   ::EnumDisplayMonitors(nullptr,
                         nullptr,
                         MonitorEnumProc,
                         reinterpret_cast<LPARAM>(&result));

   ASSERT(result.size() > 0);
   ASSERT(result.size() == cMonitors);

   return result;
}

它位于我要调整其位置的对话框的
OnInitDialog
功能中。在这种情况下,它会填充整个显示器的屏幕区域(而不仅仅是工作区域,因此,例如,它会覆盖任务栏)。要使用的监视器由用户在首选项文件中配置,并存储在全局变量
g_App.m_settings.Screen
。您可以轻松地用逻辑替换该监视器,以使用哪个监视器的工作区域最大。

确保您的程序支持DPI。在MFC中,您可以使用
wnd->CenterWindow()
,这也将处理多监视器设置。如果这不是MFC问题,请添加
WinAPI
标记。
const auto  monitors = GetInfoForAllMonitors();
const auto rcMonitor = monitors[g_App.m_settings.Screen].rcMonitor;
this->SetWindowPos(nullptr,
                   rcMonitor.left, rcMonitor.top,
                   rcMonitor.Width(), rcMonitor.Height(),
                   SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);