Мы продолжаем поддерживать и внедрять инновации в среду выполнения Windows Forms. В этой статье обсудим, что мы сделали в рамках .NET 6.0.
Улучшения и исправления специальных возможностей
Сделать приложения Windows Forms более доступными для большего числа пользователей - одна из главных целей нашей команды. Опираясь на импульс, который мы получили в период разработки .NET 5.0, в этом релизе мы внесли дальнейшие улучшения, включая, помимо прочего, следующее:
Улучшена поддержка вспомогательных технологий при использовании приложений Windows Forms. Провайдеры UIA (Microsoft UI Automation) позволяют таким инструментам, как Экранный диктор и другие, взаимодействовать с элементами приложения. UIA также часто используется для автоматизации тестирования приложений. Мы добавили поддержку UIA для следующих элементов управления: CheckedListBox; LinkLabel; Panel; ScrollBar; TabControl; TrackBar.
Улучшены уведомления экранного диктора в элементах управления заголовками столбцов DataGridView, ErrorProvider и ListView.
Всплывающие подсказки клавиатуры для элементов управления TabControl-TabPage и TreeView-TreeNode.
ScrollItem Control Pattern поддержка для ComboBoxItemAccessibleObject.
Исправлены типы элементов управления для лучшей поддержки Text Control Patterns.
ExpandCollapse Control Pattern поддержка для DateTimePicker.
Invoke Control Pattern поддержка для компонента UpDownButtons в DomainUpDown и NumericUpDown.
Улучшен цветовой контраст в следующих элементах управления: CheckedListBox, DataGridView, Label, PropertyGridView, ToolStripButton.
Начальная загрузка приложения
В .NET Core 3.0 мы начали модернизировать и обновлять Windows Forms. В рамках этой инициативы мы изменили шрифт по умолчанию на Segoe UI, 9f (dotnet/winforms#656), и быстро узнали, что многие вещи зависят от метрик шрифта по умолчанию. Например, конструктор больше не был настоящим WYSIWYG, поскольку процесс Visual Studio выполняется под .NET Framework 4.7.2 и использует старый шрифт по умолчанию (Microsoft Sans Serif, 8.25f), а приложение .NET во время выполнения использует новый шрифт. Это изменение также усложнило для некоторых пользователей миграцию своих больших приложений с выверенными макетами. Несмотря на то, что мы предоставили стратегии миграции, применение их к сотням форм и элементам управления могло бы стать серьезной задачей.
Чтобы упростить миграцию этих приложений с идеально-выверенной точностью до пикселя, мы представили новый API (подробности см. в публикации о шрифтах по умолчанию для всего приложения):
void Application.SetDefaultFont(Font font)
Однако этого API было недостаточно для обеспечения возможности дизайнера отображать формы и элементы управления с использованием одного и того же нового шрифта. В то же время из-за того, что наши другие команды усиленно настаивали на небольших шаблонах приложений, наш Program.cs и его метод Main() стали выглядеть очень устаревшими, и мы решили следовать общей тенденции .NET и урезать шаблон. Встречайте новую загрузочную программу Windows Forms:
class Program
{
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
ApplicationConfiguration.Initialize() - это API, сгенерированный источником, который генерирует следующие вызовы:
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.SetDefaultFont(new Font(...));
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Параметры этих вызовов настраиваются с помощью свойств MSBuild в файлах csproj или props. Дизайнер Windows Forms в Visual Studio 2022 также знает об этих свойствах (пока он читает только шрифт по умолчанию) и может показать вам ваше приложение (C#, .NET 6.0 и выше) так, как оно будет выглядеть во время выполнения:
Обратите внимание, что Visual Basic по-разному обрабатывает эти значения по умолчанию для всего приложения. В .NET 6.0 Visual Basic представляет новое событие приложения ApplyApplicationDefaults, которое позволяет вам определять параметры всего приложения (например, HighDpiMode или шрифт по умолчанию) обычным способом Visual Basic. В ближайшем будущем также появится дизайнерская поддержка шрифта по умолчанию, настроенного через свойства MSBuild. Для получения дополнительных сведений перейдите в специальный пост в блоге о Visual Basic, в котором обсуждаются новые возможности Visual Basic.
Обновления шаблона
Как упоминалось выше, мы обновили наши шаблоны C# в соответствии с соответствующими изменениями в рабочих нагрузках .NET, шаблоны Windows Forms для C# были обновлены для поддержки директив global using, пространств имен с файловой областью и ссылочных типов, допускающих значение NULL. Поскольку для типичного приложения Windows Forms требуется атрибут STAThread, и оно состоит из нескольких типов, разделенных на несколько файлов (например, Form1.cs и Form1.Designer.cs), операторы верхнего уровня отсутствуют в шаблонах Windows Forms. Однако обновленные шаблоны включают код начальной загрузки приложения.
Больше конструкторов среды выполнения
Мы завершили перенос недостающих конструкторов и связанную с ними инфраструктуру, которая позволяет создавать универсального дизайнера (например, дизайнера отчетов). Для получения более подробной информации обратитесь к нашему более раннему анонсу.
Если вы считаете, что мы забыли о конструкторе, от которого зависит ваше приложение, сообщите нам об этом в нашем репозитории GitHub.
Высокий DPI и улучшения масштабирования
Мы работали над пространством с высоким DPI, чтобы заставить приложения Windows Forms правильно поддерживать режим PerMonitorV2 из коробки. Это сложная задача, и, к сожалению, мы не смогли добиться того, на что рассчитывали. Тем не менее в этом выпуске мы добились некоторого прогресса, и теперь можно:
Создавайте элементы управления с той же поддержкой DPI, что и приложение.
Правильно масштабируйте ContainerControls и дочерние окна MDI в режиме PerMonitorV2 в большинстве сценариев. По-прежнему существует несколько конкретных сценариев (например, привязка) и элементов управления (например, MonthCalendar), в которых взаимодействие остается некачественным.
Другие заметные изменения
Новые перегрузки для методов Control.Invoke() и Control.BeginInvoke(), которые принимают Action и Func и позволяют писать более современный и лаконичный код.
Новый API Control.IsAncestorSiteInDesignMode является дополнительным к Component.DesignMode и указывает, размещен ли один из прародителей элемента управления, а также находится ли этот сайт в режиме разработки. Специальная запись в блоге, посвященная этому API, появится позже, так что следите за обновлениями.
Поведение всплывающей подсказки по умолчанию в стиле Windows 11 заставляет всплывающую подсказку оставаться открытой при наведении на нее мыши и не исчезать автоматически. Всплывающую подсказку можно закрыть клавишами CONTROL или ESCAPE.
Комментарии (23)
debagger
18.11.2021 19:40Насколько больно будет мигрировать проект на WinForms, написанный на VB.net, который сейчас работает под .Net Framework 4.0? Кто-нибудь сталкивался с подобными задачами?
werwolflg
18.11.2021 19:54Так он скорее всего у вас WinForms и использует. Или имеется ввиду портировать с VB.Net на C#? Для последнего есть утилиты, но чистить код и поправлять всё равно придётся. Переносил проект с VB.Net с .Net Framework 3.5 на С# .Net Framework 4.
courage_andrey
19.11.2021 10:43По моему опыту - это лотерея. Если кода, ипользующего подкапотные костыли .NET и WinForms мало, то вполне возможно, что удастся реально обойтись заявленным в статье Application.SetDefaultFont. Шаг в сторону (не ту) - здравствуйте, две недели отладки. Мигрировал по версиям 2 своих pet-проекта и 2 крупные enterprise-системы. Ни разу не угадал с прогнозом сложности таких изменений - причём ошибался в обе стороны.
DancingOnWater
19.11.2021 11:16Все прекрасно, но что с Linux?
Раньше была поддержка Winforms от Mono, но еще в .Net 5 вы все сломали
Larymar
19.11.2021 12:52Там у майков есть MAUI и коммунити пишет Avaloniaui
DancingOnWater
19.11.2021 15:18Ни то, ни другое, насколько я знаю, с Winforms несовместимо. И в моем случае, вы предлагаете мигрировать весь проект. И это можно было бы сделать, но есть два НО:
1) До этого все работало в Mono. (Есть мелочи, но это действительно мелочи)
2) До этого Microsoft похоронила WPF, Silverlight, плиточный дизайн. Сейчас занята тем, что активно закапывает UWP. И да, MAUI официально Linux не поддерживает, это отдано на откуп энтузиастам.
Hwd
Зачем заморачиваться с WinForms, если уже столько лет есть WPF? Дайте ему уже благополучно загнуться.
vabka
WF часто используют там, где нужно за пару кликов накидать UI для чего-нибудь, без сложного дизайна и без заглубления в XAML. И не всегда это делают профессиональные разработчики.
Слышал, что таким промышляют во всяких лабораториях, чтобы сделать UI для какой-нибудь экспериментальной установки.
Ну и ещё всякое легаси есть.
VB Net же всё ещё не закопали )
Hwd
На самом деле, быстро накидать простой интерфейс в визуальном редакторе драг/дропом можно и в WPF, не залезая в xaml. Выглядеть будет как винформс.
alec_kalinin
Самым удивительным является тот факт, что WinForms сейчас гораздо живее WPF. Если поглядеть на GitHub репозиторий WPF, то большинство коммитов сейчас делается автоматическим копированием зависимостей с WinForms.
В общем это даже понятно. WinForms является оберткой над Win32 API, а это в некотором смысле основа десктопа Windows.
А вот WPF Microsoft старательно закапывает ради нового продукта под названием Win UI 3, надстроенного над новым Windows App SDK, который является в некотором смысле реинкарнацией невзлетевшего UWP.
Но пока Win UI 3 крайне сырая и медленная. Более того, многих возможностей WPF там нет, и не скоро появятся. В частности довольно удобная 3D графика WPF в WinUI 3 не факт, что вообще когда-нибудь появится.
Так что если что-то сейчас писать для Windows декстопа, то вариантов то почти нет. WPF Microsoft старательно убивает, WinUI может вообще не взлететь. Писать на JavaScript под Electron? Или ReactNative?
С этой точки зрения WinForms живее всех живых.
А вообще, я бы рекомендовал Qt для нового декстоп проекта под Windows.
Hwd
Qt - это ведь для C++, а не для .Net, насколько я знаю.
alec_kalinin
В целом да, Qt это для C++. Хотя у них есть QML/QtQuick для написания UI на основе декларативного JavaScript.
Но огромный плюс Qt это очень стабильный API для кроссплатформенного декстопа. Qt было, есть и будет. Хотя и на C++.
А вот что и когда Microsoft решить закопать в следующий раз, это большой вопрос. Начинать проект на WPF сейчас крайне рискованно. Команду WPF почти разогнали и не факт, что восстановят. Пулл-реквесты висят годами.
А WinUI 3 где-то раз в 100 медленнее WPF.
И что делать?...
Hwd
Ну, если так рассуждать, то тогда вместо Qt лучше сразу смотреть в сторону asp net core 6 ( оно всё таки своё, родное). Интерфейс в браузере, а сам бэкенд хостить в докер-контейнере. Собственно так и делаю уже несколько лет. Печально, что WPF прикопали. Мне он нравился и я лелеял надежду, что его всё же сделают кросплатформенным, вопреки заявлениям.
vabka
Мне кажется, проще Avalonia дотащить до уровня WPF, чтобы и 3d из коробки (не из коробки кто-то уже и так реализует) было, и всё остальное, чем пытаться сделать WPF кроссплатформенным.
codecity
Совершенно согласен — удивительно, но так и случилось.
MS пытались изменить ситуацию на рынке технологий, но технологии живут своей жизнью и даже создателю не всегда под силу этим процессом управлять.
Неплохо бы портировать WinForm на Linux, типа как Mono но от корпорации.
nikolayv81
И после портирования потерять часть рынка windows только потому что теперь компании необязательно покупать лицензии windows чтобы их программы работали....
courage_andrey
Потому что WPF не лучше WinForms. Да, в некоторых местах он шагнул далеко вперёд: темплейты, стили, анимации, свойства и события прокачались, разметку теперь не нужно переписывать при изменении DPI или языка (ну ладно, хотя бы не так часто и геморройно). Но в некоторых вещах (RichTextBox и WebBrowser) он просто не юзабелен, только WindowsFormsHost и спасает...
P.S.: ~10 лет опыт работы с WPF, ~5 лет WinForms.
Hwd
Ну вот как не лучше-то? Например, WPF элементы поддерживают перекрытия за счёт коэффициента прозрачности. WinForms такого не умеет. В WPF интерфейс можно делать очень красивым, гораздо красивее, чем WinForms (при условии, что есть талант по части стилей). Всякие анимашки, "вау"-эффекты, даже 3D-интерфейсы можно делать. Всё это обрабатывается видеокартой (DirectX). Для WinForms графика обрабатывается центральным процессором. Чтобы сделать красивый "вау"-интерфейс средствами WinForms придётся попотеть гораздо больше и ещё не факт, что всё получится.
Да, "из коробки" элементов в WPF не так много, как хотелось бы, однако самому создавать кастомные элементы на WPF гораздо легче/удобней, чем для WinForms, а это многого стОит... К тому же, если организация ценит своё время, то вообще может купить разработчику расширенный набор WPF-контролов (например от DevExpress, хотя то же самое можно сказать и в копилку WinForms).
В Windows есть WinForms и WPF, при этом оба никуда не денутся, ибо проверены годами и широко используются. WPF гораздо развитей, поэтому я не вижу смысла использовать WinForms в новых проектах. На мой взгляд, использование WinForms при наличии возможности использования WPF, это как покупка персональных, именованных граблей, на которые придётся часто наступать.
WPF сложнее в изучении в виду того, что подлежащей освоению информации гораздо больше, чем для WinForms (это минус).
Крис Андерсон, будучи архитектором WPF, лаконично, но достаточно понятно излагает материал по WPF. Мэтью Мак-Дональд и Чарльз Петцольд делают это более фундаментально (Петцольд больше с уклоном на код, а Мак-Дональд - на XAML и потому, на мой взгляд, гармонично дополняют друг друга).
В то же время по WinForms, насколько я помню, есть только одна старая, толковая книжка (всё от того же Чарльза Петцольда).