Я работаю над тем, чтобы приложение MFC правильно отображалось в средах с несколькими мониторами с разным масштабированием DPI. Есть одна проблема, которую я не могу объяснить, которая возникает, когда основной и дополнительный мониторы работают с разными DPI, а приложение находится на дополнительном мониторе.
Если основной монитор имеет масштабирование 100% DPI (96), а дополнительный монитор имеет такое же масштабирование 100% DPI, все в порядке.
Если основной монитор имеет масштабирование 100% DPI (96), а дополнительный монитор имеет масштабирование 125% (120 DPI) или масштабирование 150% (144 DPI) или любое другое более высокое значение, когда дочерние окна развернуты, часть дочерней оконной системы полоса видна, как показано здесь:
Если присмотреться, то 7 пикселей для 125% и 14 для 150%. Учитывая, что системная полоса составляет 29 пикселей при масштабировании 100 %, 36 и 125 % и 43 пикселя при масштабировании 150 %, эти 7 и 14 пикселей представляют собой разницу в высоте между размером полосы при масштабе 125 % и 150 % соответственно по сравнению со 100 % базовый уровень.
Таким образом, создается впечатление, что положение и размер полосы вычисляются системой при запуске на основном мониторе.
Когда вы разворачиваете дочернее окно, окну отправляется серия сообщений Windows: WM_GETMINMAXINFO
› WM_WINDOWPOSCHANGING
› WM_GETMINMAXINFO
› WM_NCCALSIZE
› WM_WINDOWSPOSCHANGED
› WM_MOVE
› WM_SIZE
. WM_GETMINMAXINFO
отправляется, когда размер или положение окна вот-вот изменится, чтобы приложение могло переопределить, например, максимальный размер и положение окна по умолчанию. По этому поводу есть примечание:
Для систем с несколькими мониторами элементы ptMaxSize и ptMaxPosition описывают максимальный размер и положение окна на основном мониторе, даже если окно в конечном итоге разворачивается на дополнительный монитор. В этом случае оконный менеджер корректирует эти значения, чтобы компенсировать разницу между основным монитором и монитором, на котором отображается окно. Таким образом, если пользователь оставляет ptMaxSize нетронутым, окно на мониторе, большем, чем основной монитор, максимизируется до размера большего монитора.
Существует статья Рэймонда Чана, объясняющая это: Как настраивается оконный менеджер ptMaxSize и ptMaxPosition для нескольких мониторов?.
Таким образом, ptMaxSize
должен быть заполнен размерами основного монитора. Мой основной монитор 2560x1440 пикселей, а размер дополнительного монитора 1920x1200. Однако значение размера, которое я получаю здесь, составляет 1757x1023 и 1761x1027 (при последовательных вызовах). Это не размер основного или дополнительного монитора.
Я попытался сделать грязный трюк и обработал сообщение WM_NCCALCSIZE
и установил позицию (слева, сверху) на 0 (относительно родителя).
void CMyMDIChildWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
CMDIChildWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
if (condition)
{
lpncsp->rgrc[0].left = 0;
lpncsp->rgrc[0].top = 0;
}
}
Работает нормально, пока дочернее окно имеет фокус. Если я нажимаю на другое окно, и оно теряет фокус, полоса перерисовывается и отображается в предыдущей позиции. Этот трюк говорит только о том, где начинается клиентская область, поэтому, когда неклиентская область перерисовывается, я возвращаюсь к исходной проблеме.
Мой вопрос в том, что может быть корнем этой проблемы и как я могу попытаться это исправить?
WM_NCPAINT
, ни другое неклиентское сообщение (ниWM_PAINT
, ниWM_ERASEBKGND
в этом отношении). Там не так много всего происходит. - person Marius Bancila   schedule 29.04.2021