Что нового

Создание GUI с учетом установленного масштабирования

musicstashall

Знающий
Сообщения
322
Репутация
7
Всем привет.

Столкнулся с такой задачкой. Если в системе Windows 10 установлено масштабирование отличное от 100%, в разделе настроек «массштаб и разметка», то все, создаваемые скриптом окна игнорируют этот параметр, остаются мелкими, в сравнении с общим интерфейсом, а вот текст в окнах создается с учетом этого массштаба, а потому ломает весь дизайн окна. Можете себе представить это? Текст просто не вмещается в элементы окна. Есть ли способ это решить как-то? Может кто-то сталкивался с подобным...


Такая проблема не на всех компьютерах возникает. Наверное видеодрайвер, в паре с монитором, за это отвечают.
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Код:
; сообщаем системе, что мы умеем масштабировать интерфейс
DllCall("User32.dll", "bool", "SetProcessDPIAware")

; рассчитываем коэффициент масштабирования
$Zoom = RegRead("HKCU\Control Panel\Desktop\WindowMetrics", "AppliedDPI") / 96
If @error Or $Zoom < 1 Then $Zoom = 1

; учитываем масштаб в GUI
GUICreate("Zoom", 230 * $Zoom, 100 * $Zoom)
GUICtrlCreateButton("Текст кнопки", 10 * $Zoom, 10 * $Zoom, 80 * $Zoom, 30 * $Zoom)
GUICtrlCreateInput("  Текст в поле ввода", 100 * $Zoom, 10 * $Zoom, 120 * $Zoom, 20 * $Zoom)
GUISetState()
Do
Until GUIGetMsg() = -3
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Это всё замечательно, не думал даже, что есть решение. Но как быть в тех случаях, когда окна сами создаются с учетом масштабирования? Если мы принудительно к этому зададим коэффициент, то у нас другая крайность возникнет. Вот, на ноутбуке у меня окна создаются с правильным массштабом, а на ПК массштаб игнорируется — там маленькие окна получаются. Как этот момент учитывать?
Или этот вызов
Код:
DllCall("User32.dll", "bool", "SetProcessDPIAware")
как раз и сообщает системе, что мы сами будем масштабировать?
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Тема масштабирования в Windows обширна, сложна и запутана. Изучайте теорию, проверяйте её на практике и побольше экспериментируйте. Если, конечно, оно вам надо.
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Alofa [?]
полезно к прочтению
Это только начало. Дальше - страшнее: PROCESS_DPI_AWARENESS.
Если что, аналогом вызова SetProcessDPIAware является установка PROCESS_SYSTEM_DPI_AWARE.

Кстати, в последних версиях полной SciTE есть директива Wrapper'а
Код:
#AutoIt3Wrapper_Res_HiDpi=Y
которая при компиляции прописывает в манифест поддержку DPIAware (обычную, системную, не многомониторную).
 

Norm

Продвинутый
Сообщения
278
Репутация
74
Код:
; сообщаем системе, что мы умеем масштабировать интерфейс
DllCall("User32.dll", "bool", "SetProcessDPIAware")

; рассчитываем коэффициент масштабирования
$Zoom = RegRead("HKCU\Control Panel\Desktop\WindowMetrics", "AppliedDPI") / 96
If @error Or $Zoom < 1 Then $Zoom = 1

; учитываем масштаб в GUI
GUICreate("Zoom", 230 * $Zoom, 100 * $Zoom)
GUICtrlCreateButton("Текст кнопки", 10 * $Zoom, 10 * $Zoom, 80 * $Zoom, 30 * $Zoom)
GUICtrlCreateInput("  Текст в поле ввода", 100 * $Zoom, 10 * $Zoom, 120 * $Zoom, 20 * $Zoom)
GUISetState()
Do
Until GUIGetMsg() = -3
Проверил этот пример
Изменил на своём масштабирование со 100% на 120%, 150%
Размер шрифтов увеличелся, а размер контролов так и не изменился, $Zoom остался тот-же = 1.

Эта функция определает масштабирование у меня правильно
Код:
MsgBox(0, "Scaling", _GetDPI_Ratio())

Func _GetDPI_Ratio()
    Local $hWnd = 0
    Local $hDC = DllCall("user32.dll", "long", "GetDC", "long", $hWnd)
    Local $aRet = DllCall("gdi32.dll", "long", "GetDeviceCaps", "long", $hDC[0], "long", 10)  ; = reported vert height (not logical, which is param=90)
    Local $bRet = DllCall("gdi32.dll", "long", "GetDeviceCaps", "long", $hDC[0], "long", 117) ; = true vert pixels of desktop
    $hDC = DllCall("user32.dll", "long", "ReleaseDC", "long", $hWnd, "long", $hDC)
    Return $bRet[0] / $aRet[0]
EndFunc

Эта библиотека похоже с этим тоже справляется
 

Вложения

  • GUIScaling.rar
    8.2 КБ · Просмотры: 1
Последнее редактирование:

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
$Zoom остался тот-же = 1
В примере текущее масштабирование читается из реестра. А сохраняется в реестр при выходе из системы. Эта технология применялась до Win8 включительно, но и на новых системах поддерживается. Обычно юзер не меняет масштабирование "на лету" - один раз выставил, перелогинился и забыл. Поэтому решение вполне рабочее.

Начиная с Win8.1 появилась технология масштабирования отдельно по каждому монитору. Были добавлены соответствующие функции и уведомления. Указанная вами UDF, вероятно, с ними и работает, если меняет размер контролов сразу при изменении масштаба.
 
Верх