Расположите окно на большом мониторе - PullRequest
0 голосов
/ 03 февраля 2019

Я работаю на дополнительном 21-дюймовом мониторе с ноутбуками. Когда я нажимаю значок TightVNC viewer на панели задач, он обычно открывается на меньшем экране ноутбука. Затем мне придется перетащить его на монитор большего размера.на работу.

Я обнулен код, который мы можем изменить, чтобы автоматически переместить просмотрщик 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);
}

Полагаю, сначала мне нужно запросить общее количество дисплеев и найти самый большой дисплей, затем расположить окно в его центре. Кто-нибудь может подсказать мне ссылочный код, используя который я могу построить эту логику ?

1 Ответ

0 голосов
/ 05 февраля 2019

Во-первых, вам нужно решить, на каком дисплее вы хотите его видеть.Это требует перечисления доступных дисплеев, которые дадут вам доступ к их свойствам.Исходя из этого, вы решаете, какой алгоритм вы хотите использовать для выбора дисплея: какой из них самый большой, какой поддерживает больше всего цветов, какой самый дальний слева на виртуальном экране и т. Д.

Перечисление доступных дисплеев просто с использованием функции Windows API EnumDisplayMonitors, но требует значительного количества кода.Вот протестированная и полностью работающая реализация:

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;
}

Возвращает std::vector из MonitorInfo объектов.MonitorInfo объекты содержат прямоугольник, описывающий область отображения монитора, и дескриптор монитора (HMONITOR), который можно использовать для получения дополнительной информации.

Например, вы можете передать HMONITOR к функции GetMonitorInfo.Он заполнит структуру MONITORINFO или MONITORINFOEX.Это даст вам рабочую область в виде прямоугольника и укажет, является ли монитор основным монитором в системе.

В качестве примера, вот как я его использую:

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);

Это находится в функции OnInitDialog для диалогового окна, положение которого я хочу отрегулировать.В этом случае он заполняет всю область экрана монитора (а не только рабочую область, поэтому он будет, например, покрывать панель задач).Какой монитор использовать, настраивается пользователем в файле настроек и сохраняется в глобальной переменной g_App.m_settings.Screen.Вы также можете легко заменить это логикой, чтобы использовать любую рабочую область монитора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...