Во-первых, вам нужно решить, на каком дисплее вы хотите его видеть.Это требует перечисления доступных дисплеев, которые дадут вам доступ к их свойствам.Исходя из этого, вы решаете, какой алгоритм вы хотите использовать для выбора дисплея: какой из них самый большой, какой поддерживает больше всего цветов, какой самый дальний слева на виртуальном экране и т. Д.
Перечисление доступных дисплеев просто с использованием функции 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
.Вы также можете легко заменить это логикой, чтобы использовать любую рабочую область монитора.