Моя структура пользовательского интерфейса использует двойные значения для координат пикселей, что дает мне хорошие дробные виртуальные координаты на дисплеях Retina. Для этого я получаю координаты мыши из Windows в единицах HIMETRIC. Однако я столкнулся с ошибкой, которую не могу понять.
У меня есть Surface Book 2 (3000x2000 @ 225%), подключенный к док-станции с двумя внешними мониторами (1920x1080 @ 100%). Если я вхожу в Windows с подключенной док-станцией (и внешний монитор @ 100% установлен в качестве основного), я получаю правильные координаты HIMETRIC, которые работают как на внешнем дисплее, так и на дисплее сетчатки.
Однако, если я войду в Windows, когда док-станция отключена, так что есть только монитор Retina, затем подключу док-станцию, затем запущу свое приложение — теперь оно получает координаты HIMETRIC, масштабированные по коэффициент масштабирования дисплея, который был основным при входе в Windows.
Я установил осведомленность о DPI моего приложения на PerMonitorV2, поэтому я нахожу настолько странным, что настройка масштаба DPI для каждой системы даже имеет отношение к моему приложению.
Это функция, которую я использую для преобразования из HIMETRIC:
double fromHimetric(uint i)
{
return (double)i / 2540 * Monitor::DefaultDPI;
}
Monitor::DefaultDPI
— константа, равная 96.
Я что-то пропустил? Нужно ли добавлять в формулу коэффициент масштабирования системы? В таком случае, как я могу узнать, какой монитор был основным при входе в Windows? Потому что это, кажется, остается постоянным независимо от того, на какой монитор я перемещаю свое окно, поскольку я получаю значения HIMETRIC, которые, по-видимому, масштабируются значением из прошлого.
Редактировать: поскольку работу с несколькими мониторами сложно описать в Интернете, я снял небольшое видео, показывающее, как эта ошибка проявляется у меня. https://www.youtube.com/watch?v=pTZiTZFXsc0
Редактировать 2: чтобы еще больше уточнить, мое приложение полностью учитывает DPI для каждого монитора, весь мой пользовательский интерфейс векторен, поэтому он правильно масштабируется, я обрабатываю WM_DISPLAYCHANGE
и WM_DPICHANGED
и все такое прочее. Координаты пера и касания работают нормально во всех случаях.
Единственное, что ломается, если я изначально запускаю свой компьютер без пристыковки, это то, что координаты HIMETRIC, которые я получаю для мыши от GetPointerInfo()
, масштабируются по масштабу дисплея монитора, который был основным при запуске компьютера.
Я много работал, чтобы убедиться, что я ХОРОШО справляюсь с ситуациями с несколькими мониторами и несколькими DPI. Я буду чувствовать себя очень глупо, если я проглядел простую вещь, которая ломает все.
Изменить 3. Посмотрите, насколько велики полосы прокрутки в Chrome. https://imgur.com/a/F3dFHAj
Или студия OBS: https://imgur.com/a/11aG5Kw
Кажется, они страдают от подобных ошибок. Не знаю, имеют ли они какое-либо отношение к HIMETRIC, но эти элементы отображаются по-разному в зависимости от того, как я запускаю компьютер.
Определяет ли Win32 что-то вроде монитора запуска?
Редактировать 4: Причина, по которой я не использую AtlHiMetricToPixel()
и PhysicalToLogicalPoint()
, заключается в том, что они возвращают целочисленные логические координаты, и мне особенно нужны двойники в логическом пространстве, поскольку весь мой пользовательский интерфейс основан на векторах. Я делаю все масштабирование самостоятельно, и, похоже, все работает нормально, за исключением одного случая. :(