8 ответов:
правка: по состоянию на .Объем 4.7, формы Windows и улучшена поддержка для высокого DPI. подробнее об этом читайте дальше docs.microsoft.com это работает только для Win 10 Creators Update и выше, хотя, так что это может быть нецелесообразно использовать это еще в зависимости от вашей пользовательской базы.
сложно, но не невозможно. Конечно, ваш лучший вариант-перейти на WPF, но это может быть невозможно.
Я провел много времени с этой проблемой. Вот некоторые правила/рекомендации чтобы сделать его правильно работать без управления flowlayoutpanel и tablelayoutpanel с:
- всегда редактируйте / создавайте свои приложения по умолчанию 96 DPI (100%). Если вы проектируете в 120DPI (125% f.ex), это будет очень плохо, когда вы вернетесь к 96 DPI, чтобы работать с ним позже.
- я использовал AutoScaleMode.Шрифт с успехом, я не пробовал AutoScaleMode.DPI много.
- убедитесь, что вы используете размер шрифта по умолчанию для всех ваших контейнеров (форм, панелей, вкладок, usercontrols и т. д.). 8,25 ПХ. Предпочтительно он не должен быть установлен в поле .Дизайнер.файл CS все для всех контейнеров, так что он использует шрифт по умолчанию из класса контейнера.
- все контейнеры должны используйте то же самое AutoScaleMode
- убедитесь, что все контейнеры имеют нижеприведенную строку, установленную в конструкторе.cs файл:
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); // for design in 96 DPI
- Если вам нужно установить различные размеры шрифта на этикетках/текстовые поля и т. д. вместо этого установите их для каждого элемента управления установки шрифта в классе контейнера, поскольку winforms использует параметр шрифта containers для масштабирования его содержимого и имеет F.ex панель с другим размером шрифта, чем содержащая форма, гарантированно создает проблемы. Это может сработать, если форма и все контейнеры в форме используют один и тот же размер шрифта, но я не пробовал.
- используйте другую машину или виртуальную установку windows (VMware, Virtual PC, VirtualBox) с более высоким значением DPI для немедленного тестирования вашего дизайна. Просто запустите скомпилированный .exe-файл из папки /bin/Debug на компьютере разработчика.
Я гарантирую, что если вы будете следовать этим рекомендациям, вы будете в порядке, даже если вы разместили элементы управления с определенными якорями и не используете flowpanel. У нас есть приложение, построенное таким образом, развернутое на сотнях машин с различными настройками DPI, и у нас больше нет никаких жалоб. Все формы/контейнеры/сетки/кнопки/текстовые поля и т. д. размеры масштабируются правильно, как и шрифт. Изображения тоже работают, но они имеют тенденцию получить немного пиксельной при высоком разрешении.
EDIT: эта ссылка имеет много хорошей информации, особенно если вы решили использовать AutoScaleMode.DPI:ссылка на соответствующий вопрос stackoverflow
Я наконец нашел решение проблемы как ориентации экрана, так и обработки DPI.
Microsoft уже предоставила документ, объясняющий это, но с небольшим недостатком, который полностью убьет обработку DPI. Просто следуйте решению, представленному в документе ниже в разделе " Создание отдельного кода макета для каждой ориентации" http://msdn.microsoft.com/en-us/library/ms838174.aspxтогда важная часть! Внутри кода для ландшафтных() и портретных () методов в в самом конце каждого добавьте следующие строки:
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;Итак, код для этих 2 методов, таких как:
protected void Portrait() { this.SuspendLayout(); this.crawlTime.Location = new System.Drawing.Point(88, 216); this.crawlTime.Size = new System.Drawing.Size(136, 16); this.crawlTimeLabel.Location = new System.Drawing.Point(10, 216); this.crawlTimeLabel.Size = new System.Drawing.Size(64, 16); this.crawlStartTime.Location = new System.Drawing.Point(88, 200); this.crawlStartTime.Size = new System.Drawing.Size(136, 16); this.crawlStartedLabel.Location = new System.Drawing.Point(10, 200); this.crawlStartedLabel.Size = new System.Drawing.Size(64, 16); this.light1.Location = new System.Drawing.Point(208, 66); this.light1.Size = new System.Drawing.Size(16, 16); this.light0.Location = new System.Drawing.Point(192, 66); this.light0.Size = new System.Drawing.Size(16, 16); this.linkCount.Location = new System.Drawing.Point(88, 182); this.linkCount.Size = new System.Drawing.Size(136, 16); this.linkCountLabel.Location = new System.Drawing.Point(10, 182); this.linkCountLabel.Size = new System.Drawing.Size(64, 16); this.currentPageBox.Location = new System.Drawing.Point(10, 84); this.currentPageBox.Size = new System.Drawing.Size(214, 90); this.currentPageLabel.Location = new System.Drawing.Point(10, 68); this.currentPageLabel.Size = new System.Drawing.Size(100, 16); this.addressLabel.Location = new System.Drawing.Point(10, 4); this.addressLabel.Size = new System.Drawing.Size(214, 16); this.noProxyCheck.Location = new System.Drawing.Point(10, 48); this.noProxyCheck.Size = new System.Drawing.Size(214, 20); this.startButton.Location = new System.Drawing.Point(8, 240); this.startButton.Size = new System.Drawing.Size(216, 20); this.addressBox.Location = new System.Drawing.Point(10, 24); this.addressBox.Size = new System.Drawing.Size(214, 22); //note! USING JUST AUTOSCALEMODE WILL NOT SOLVE ISSUE. MUST USE BOTH! this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); //IMPORTANT this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; //IMPORTANT this.ResumeLayout(false); } protected void Landscape() { this.SuspendLayout(); this.crawlTime.Location = new System.Drawing.Point(216, 136); this.crawlTime.Size = new System.Drawing.Size(96, 16); this.crawlTimeLabel.Location = new System.Drawing.Point(160, 136); this.crawlTimeLabel.Size = new System.Drawing.Size(48, 16); this.crawlStartTime.Location = new System.Drawing.Point(64, 120); this.crawlStartTime.Size = new System.Drawing.Size(248, 16); this.crawlStartedLabel.Location = new System.Drawing.Point(8, 120); this.crawlStartedLabel.Size = new System.Drawing.Size(48, 16); this.light1.Location = new System.Drawing.Point(296, 48); this.light1.Size = new System.Drawing.Size(16, 16); this.light0.Location = new System.Drawing.Point(280, 48); this.light0.Size = new System.Drawing.Size(16, 16); this.linkCount.Location = new System.Drawing.Point(80, 136); this.linkCount.Size = new System.Drawing.Size(72, 16); this.linkCountLabel.Location = new System.Drawing.Point(8, 136); this.linkCountLabel.Size = new System.Drawing.Size(64, 16); this.currentPageBox.Location = new System.Drawing.Point(10, 64); this.currentPageBox.Size = new System.Drawing.Size(302, 48); this.currentPageLabel.Location = new System.Drawing.Point(10, 48); this.currentPageLabel.Size = new System.Drawing.Size(100, 16); this.addressLabel.Location = new System.Drawing.Point(10, 4); this.addressLabel.Size = new System.Drawing.Size(50, 16); this.noProxyCheck.Location = new System.Drawing.Point(168, 16); this.noProxyCheck.Size = new System.Drawing.Size(152, 24); this.startButton.Location = new System.Drawing.Point(8, 160); this.startButton.Size = new System.Drawing.Size(304, 20); this.addressBox.Location = new System.Drawing.Point(10, 20); this.addressBox.Size = new System.Drawing.Size(150, 22); //note! USING JUST AUTOSCALEMODE WILL NOT SOLVE ISSUE. MUST USE BOTH! this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); //IMPORTANT this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; //IMPORTANT this.ResumeLayout(false); }работает как шарм для меня.
похоже, что это проблема с Windows. Вынимание этих двух линий все исправило.
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;вот где я получил решение:
очень сложно создавать приложения с поддержкой DPI в Windows Forms. Вам придется использовать контейнеры макета, которые правильно изменяют размер при изменении DPI (например, TableLayoutPanel или FlowLayoutPanel). Все элементы управления также нуждаются в изменении размера. Конфигурация этих контейнеров может быть сложной задачей.
для простых приложений это может быть сделано в течение разумного периода времени, но для больших приложений это действительно много работы.
- Если вы хотите, чтобы ваше приложение WinForms было приложением с поддержкой DPI, в дополнение к хорошему ответу Trygve, если у вас есть большой проект, вы можете автоматически масштабировать свои формы и их содержимое, вы можете сделать это, создав функцию ScaleByDPI:
функция ScaleByDPI получит управляющий параметр, который обычно является формой, а затем рекурсивно перебирает все элементы управления sub (if (control.HasChildren = = true)), а также масштабировать местоположение и размеры вашего приложение контролирует & размеры и размеры шрифтов в ОС настроен DPI. Вы можете попробовать реализовать и для изображений, иконок и графики.
специальные примечания для функции ScaleByDPI:
а. Для всех элементов управления размером шрифта по умолчанию, вы должны установить свой шрифт.Размер до 8,25.
b. вы можете получить devicePixelRatioX и devicePixelRatioY значения (control.CreateGraphics().DpiX / 96) и (контроль.CreateGraphics().DpiY / 96).
Си. Вам понадобится контроль масштаба.Размер И Контроль.Расположение по алгоритму, который основан на контроле.Док и управление.Значение привязки. Обратите внимание, что контроль.Dock может иметь 1 из 6 возможных значений и этот элемент управления.Якорь может иметь 1 из 16 возможных значений.
d. Этот алгоритм должен будет установить значения для следующих переменных bool isDoSizeWidth, isDoSizeHeight, isDoLocationX, isDoLocationY, isDoRefactorSizeWidth, isDoRefactorSizeHeight, isDoRefactorLocationX, isDoRefactorLocationY, isDoClacLocationXBasedOnRight, isDoClacLocationYBasedOnBottom.
Эл. Если ваш проект использует библиотеку управлять другими то Microsoft контролирует, контролирует, возможно, потребуется специальное лечение.
дополнительная информация о выше (d.) переменные bool:
*иногда группа элементов управления (может быть кнопки) должны быть размещены один за другим на той же вертикальной линии, и их значение якоря включают в себя право, но не слева, или они должны быть размещены один за другим на той же горизонтальной линии, и их значение якоря включите Нижний, но не Верхний, в этом случае вам нужно пересчитать значения местоположения элементов управления.
*в случае элементов управления, которые якорь содержит верхний и нижний и\или левый и правый, вам нужно будет повторно факторизовать значения размера и местоположения элементов управления.
использование функции ScaleByDPI:
a. добавьте следующую команду в конец любого конструктора формы: ScaleByDPI (this);
b. также при добавлении любого элемента управления динамически к вызову формы ScaleByDPI ([ControlName]).
когда вы устанавливаете размер или местоположение любого элемента управления динамически после завершения конструктора, создайте и используйте одну из следующих функций для получения масштабированных значений размера или местоположения: ScaleByDPI_X \ ScaleByDPI_Y \ ScaleByDPI_Size \ ScaleByDPI_Point
чтобы отметить ваше приложение как DPI-aware, добавьте элемент dpiAware в манифест сборки вашего приложения.
Set GraphicsUnit всех элементов управления.Шрифт для системы.Рисунок.GraphicsUnit.Точка
In *.Дизайнер.cs-файлы всех контейнеров, установите значение AutoScaleMode в System.Окна.Формы.AutoScaleMode.Нет
в элементах управления, таких как ComboBox & TextBox, изменение управления.Размер.Он не имеет никакого влияния. В этом случае меняется управление.Шрифт.Размер будет фиксировать высоту управления.
если значение формы StartPosition является FormStartPosition.Центральный экран, вы будете нужно пересчитать расположение окна.
Как исправить размытые формы Windows в настройках с высоким разрешением
- перейдите в конструктор форм, затем выберите свою форму (нажав на его заголовок)
- нажмите F4, чтобы открыть окно свойств,
- найдите AutoScaleMode свойства
- изменить шрифт (по умолчанию) до Dpi.
Теперь перейдите к программе.cs (или файл, в котором находится ваш основной метод) и измените его на выглядит так:
namespace myApplication { static class Program { [STAThread] static void Main() { // ***this line is added*** if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } // ***also dllimport of that function*** [System.Runtime.InteropServices.DllImport("user32.dll")] private static extern bool SetProcessDPIAware(); } }сохранить и скомпилировать. Теперь ваша форма должна снова выглядеть хрустящей.
источник: http://crsouza.com/2015/04/13/how-to-fix-blurry-windows-forms-windows-in-high-dpi-settings/
из опыта:
- не используйте осведомленность DPI с windows forms, если это не критично
- для этого всегда ставим
AutoScaleModeсвойствоNoneна всех формах и пользовательских элементах управления в вашем приложении- результат: WYSIWYG тип интерфейса при изменении настроек DPI
при использовании другого разрешения DPI система заставляет вашу форму переопределять размер, местоположение и шрифт своего элемента управления, но не изображения, решение заключается в изменении DPI формы во время выполнения, При загрузке, так что все возвращается к исходному размеру и местоположению.
это возможное решение, которое я протестировал с помощью приложения для карточной игры, где у меня есть около 80 кнопок изображения, TabControls и т. д.
в каждом событии form_Load добавьте этот фрагмент кода:
Dim dpi As Graphics = Me.CreateGraphics Select Case dpi.DpiX Case 120 '-- Do nothing if your app has been desigbned with 120 dpiCase Else '-- I use 125 AND NOT 120 because 120 is 25% more than 96 Me.Font = New Font(Me.Font.FontFamily, Me.Font.Size * 125 / dpi.DpiX) End Selectкроме того, быстрый трюк для тестирования различных разрешений на одном компьютере, без перезагрузки:
от панель управления, измените разрешение. Не перезапускайте! Вместо этого закройте сеанс и откройте новый с тем же пользователем.
есть еще один нюанс: если вы устанавливаете размер и положение элемента управления во время выполнения, то вы должны применить тот же коэффициент DPI (например. 125 / Dpi.Около года) в новые координаты. Поэтому вам лучше настроить глобальную переменную DPIFactor из приложения.событие запуска.
последнее, но не менее:
Не открывайте приложение в Visual Studio из другого приложения разрешение, чем исходное, или все ваши элементы управления будут перемещаться и изменять размер при открытии каждой формы, и нет пути назад...
надеюсь, что это поможет, счастливое Программирование.
Comments