Мы продолжаем поддерживать и внедрять инновации в среду выполнения 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 и выше) так, как оно будет выглядеть во время выполнения:

(Мы знаем, что форма в дизайнере все еще выглядит как Windows 7, мы над этим работаем ...)
(Мы знаем, что форма в дизайнере все еще выглядит как Windows 7, мы над этим работаем ...)

Обратите внимание, что 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)


  1. Hwd
    18.11.2021 19:01
    +4

    Зачем заморачиваться с WinForms, если уже столько лет есть WPF? Дайте ему уже благополучно загнуться.


    1. vabka
      18.11.2021 19:14
      +2

      WF часто используют там, где нужно за пару кликов накидать UI для чего-нибудь, без сложного дизайна и без заглубления в XAML. И не всегда это делают профессиональные разработчики.

      Слышал, что таким промышляют во всяких лабораториях, чтобы сделать UI для какой-нибудь экспериментальной установки.

      Ну и ещё всякое легаси есть.

      VB Net же всё ещё не закопали )


      1. Hwd
        18.11.2021 19:37
        +2

        На самом деле, быстро накидать простой интерфейс в визуальном редакторе драг/дропом можно и в WPF, не залезая в xaml. Выглядеть будет как винформс.


    1. alec_kalinin
      18.11.2021 19:16
      +10

      Самым удивительным является тот факт, что 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.


      1. Hwd
        18.11.2021 19:35
        +3

        Qt - это ведь для C++, а не для .Net, насколько я знаю.


        1. alec_kalinin
          18.11.2021 19:45

          В целом да, Qt это для C++. Хотя у них есть QML/QtQuick для написания UI на основе декларативного JavaScript.

          Но огромный плюс Qt это очень стабильный API для кроссплатформенного декстопа. Qt было, есть и будет. Хотя и на C++.

          А вот что и когда Microsoft решить закопать в следующий раз, это большой вопрос. Начинать проект на WPF сейчас крайне рискованно. Команду WPF почти разогнали и не факт, что восстановят. Пулл-реквесты висят годами.

          А WinUI 3 где-то раз в 100 медленнее WPF.

          И что делать?...


          1. Hwd
            18.11.2021 20:32
            +1

            Ну, если так рассуждать, то тогда вместо Qt лучше сразу смотреть в сторону asp net core 6 ( оно всё таки своё, родное). Интерфейс в браузере, а сам бэкенд хостить в докер-контейнере. Собственно так и делаю уже несколько лет. Печально, что WPF прикопали. Мне он нравился и я лелеял надежду, что его всё же сделают кросплатформенным, вопреки заявлениям.


            1. vabka
              22.11.2021 13:15
              +1

              Мне кажется, проще Avalonia дотащить до уровня WPF, чтобы и 3d из коробки (не из коробки кто-то уже и так реализует) было, и всё остальное, чем пытаться сделать WPF кроссплатформенным.


      1. codecity
        19.11.2021 00:04
        +4

        Самым удивительным является тот факт, что WinForms сейчас гораздо живее WPF.

        Совершенно согласен — удивительно, но так и случилось.

        MS пытались изменить ситуацию на рынке технологий, но технологии живут своей жизнью и даже создателю не всегда под силу этим процессом управлять.

        Неплохо бы портировать WinForm на Linux, типа как Mono но от корпорации.


        1. nikolayv81
          19.11.2021 18:28
          -1

          И после портирования потерять часть рынка windows только потому что теперь компании необязательно покупать лицензии windows чтобы их программы работали....


    1. courage_andrey
      19.11.2021 16:00
      +1

      Потому что WPF не лучше WinForms. Да, в некоторых местах он шагнул далеко вперёд: темплейты, стили, анимации, свойства и события прокачались, разметку теперь не нужно переписывать при изменении DPI или языка (ну ладно, хотя бы не так часто и геморройно). Но в некоторых вещах (RichTextBox и WebBrowser) он просто не юзабелен, только WindowsFormsHost и спасает...
      P.S.: ~10 лет опыт работы с WPF, ~5 лет WinForms.


      1. Hwd
        19.11.2021 21:11

        Ну вот как не лучше-то? Например, 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, насколько я помню, есть только одна старая, толковая книжка (всё от того же Чарльза Петцольда).


  1. debagger
    18.11.2021 19:40

    Насколько больно будет мигрировать проект на WinForms, написанный на VB.net, который сейчас работает под .Net Framework 4.0? Кто-нибудь сталкивался с подобными задачами?


    1. werwolflg
      18.11.2021 19:54

      Так он скорее всего у вас WinForms и использует. Или имеется ввиду портировать с VB.Net на C#? Для последнего есть утилиты, но чистить код и поправлять всё равно придётся. Переносил проект с VB.Net с .Net Framework 3.5 на С# .Net Framework 4.


    1. Siemargl
      18.11.2021 22:38

      Рано мигрировать. VB.NET поддерживается и в NET 5 и в .NET 6

      Даже чуть развился в 5


    1. courage_andrey
      19.11.2021 10:43

      По моему опыту - это лотерея. Если кода, ипользующего подкапотные костыли .NET и WinForms мало, то вполне возможно, что удастся реально обойтись заявленным в статье Application.SetDefaultFont. Шаг в сторону (не ту) - здравствуйте, две недели отладки. Мигрировал по версиям 2 своих pet-проекта и 2 крупные enterprise-системы. Ни разу не угадал с прогнозом сложности таких изменений - причём ошибался в обе стороны.


  1. DancingOnWater
    19.11.2021 11:16

    Все прекрасно, но что с Linux?

    Раньше была поддержка Winforms от Mono, но еще в .Net 5 вы все сломали


    1. Larymar
      19.11.2021 12:52

      Там у майков есть MAUI и коммунити пишет Avaloniaui


      1. MTyrz
        19.11.2021 14:44

        К winforms ни то, ни другое не относится, если я верно помню.


      1. DancingOnWater
        19.11.2021 15:18

        Ни то, ни другое, насколько я знаю, с Winforms несовместимо. И в моем случае, вы предлагаете мигрировать весь проект. И это можно было бы сделать, но есть два НО:

        1) До этого все работало в Mono. (Есть мелочи, но это действительно мелочи)

        2) До этого Microsoft похоронила WPF, Silverlight, плиточный дизайн. Сейчас занята тем, что активно закапывает UWP. И да, MAUI официально Linux не поддерживает, это отдано на откуп энтузиастам.


        1. AnarchyMob
          20.11.2021 11:07

          Есть ещё кроссплатформенный Eto.Forms


          1. DancingOnWater
            25.11.2021 10:34

            Спасибо за информацию. Выглядит очень интересно.


        1. Polazhenko
          03.12.2021 16:08

          Как насчёт - platform.uno