С windows gui framework

Не Windows единой: как писать кроссплатформенные приложения с GUI на C#

На C# можно создавать красивые приложения, но до недавних пор — не для всех платформ. Рассказываем, как писать одно приложение для всех ОС сразу.

Microsoft выпустила уже третью версию кроссплатформенного .NET Core с открытым исходным кодом, но мы до сих пор не получили инструмента для создания графических интерфейсов.

Пока есть Xamarin, который можно использовать только для Windows 10 и мобильных устройств. Но что делать тем, кто хочет создавать графические интерфейсы для Linux или Mac OS?

Тут помогут фреймворки от сторонних разработчиков.

Пишет о программировании, в свободное время создает игры. Мечтает открыть свою студию и выпускать ламповые RPG.

Какой фреймворк выбрать

Мне удалось найти 2 более-менее популярных фреймворка (оба основаны на Skia ):

  1. SpaceVIL. Он привлёк меня тем, что в нём элементы GUI отрисовываются, а не берутся из API операционной системы. Поэтому приложение будет выглядеть одинаково на всех устройствах. В нём даже можно создавать собственные элементы любого вида. Однако он пока достаточно сырой — об этом говорит уже то, что в официальной документации есть ошибки в инструкции для новичков.
  2. AvaloniaUI. Это более популярный и проработанный фреймворк, который позволяет создавать интерфейсы как для мобильных устройств, так и для Linux и OS X. Также в нём используется диалект XAML, что будет плюсом для тех, кто пробовал создавать приложения для Windows. В нём даже есть поддержка MVVM.

Я попробовал оба, и второй показался мне более удобным: в нём есть язык разметки, поддержка MVVM, быстрая установка, лёгкий переход с WPF. Поэтому я выбрал его.

Как начать использовать AvaloniaUI

Я буду создавать приложение в Linux Ubuntu, но эта инструкция подойдёт всем, кто использует .NET Core. Создавать приложения можно и в Visual Studio, скачав для него расширение, но так как его нет на Linux, я буду пользоваться терминалом.

Для начала клонируйте себе на компьютер этот репозиторий:

В нём находятся шаблоны для создания приложения с AvaloniaUI. Если вы не умеете пользоваться git, то просто скачайте содержимое и распакуйте куда-нибудь на компьютере. Затем откройте консоль и введите следующую команду:

Она установит шаблоны для создания приложения. Чтобы проверить, добавились ли шаблоны, используйте команду:

Вы увидите список всех установленных шаблонов. Среди них должны быть Avalonia Window, Avalonia .NET Core MVVM App, Avalonia UserControl и Avalonia .NET Core App. Если они на месте, можно продолжать.

Откройте в консоли папку, в которой хотите создать проект, и введите:

Будет создано приложение с использованием MVVM. Практически вся документация по AvaloniaUI написана с использованием этого паттерна, поэтому проще будет разрабатывать на нём.

Теперь можно приступать к работе над приложением.

Создаём калькулятор на AvaloniaUI

У вас будут созданы следующие папки

  • Assets — сюда можно загружать различные компоненты программы вроде иконок, изображений, звуков и прочего.
  • Models — эта папка предназначена для классов, которые будут выступать в роли модели.
  • ViewModels — здесь находятся классы-посредники между видом и моделью.
  • Views — все окна будут находиться здесь.

Сначала посмотрим в файл Program.cs в корневом каталоге:

Нас интересует метод AppMain(). В нём создаётся окно (MainWindow) с указанием DataContext (используется для привязки данных), а потом это окно запускается.

В этом методе можно определить свою логику инициализации приложения. Например, объявить экземпляр модели и передать его в конструктор MainWindowViewModel(). Однако перед этим нужно определить конструктор, который будет принимать такой аргумент.

Читайте также:  Прикольные эффекты для windows

У нас очень простое приложение, поэтому мы реализуем всю логику прямо в MainWindowViewModel.cs. Там будут необходимые свойства и методы.

Для начала нужно подключить пространство имён ReactiveUI, которое в AvaloniaUI используется для реализации паттерна MVVM:

С windows gui framework

wNim is Nim’s Windows GUI Framework, based on winim. Layout DSL is powered by Yuriy Glukhov’s Kiwi constraint solving library.

Basic code structure:

Getter and Setter:

With git on windows:

The easiest way to use wNim is to import the whole package.

However, the modules of wNim can be aslo imported one by one to speed up compilation time.

There are some simple rules:

To compile the examples, try following command:

For Windows XP compatibility, add:

To compile by Tiny C Compiler, or want to add some resource files, take a look at https://github.com/khchen/winim/tree/master/tcclib

Q: Why I start this project?

In the first, I just wanted to write some code to test and prove my winim library. I wrote some event handler, some GUI control class, more and more. Finally, it become a whole GUI framework now.

Q: Why the class and api name look so like wxWidgets?

English is not my mother tongue, I often have no idea how to name an object or a function. So I borrow wxWidgets’ names to develop my own framework.

Q: Why not add linux or macOS support?

I start from winim. It is just a Windows API module.

Q: How is wNim compare to nimx, libui, NiGui etc?

They are all good GUI librarys. I think wNim is easier to use and produce smaller exe file. However, it only support Windows system.

Read license.txt for more details.

Copyright (c) 2017-2020 Kai-Hung Chen, Ward. All rights reserved.

Что случилось с GUI-фреймворками?

Это третий пост в моем квесте по поиску GUI-фреймворка для десктопных приложений. Первый, второй.

Давайте немного сориентирую, что я ищу. Для многих «GUI-фреймворк» почти равно библиотека виджетов, чем больше тем лучше. Чтобы GUI собрать из кубиков лего минимальными силами. Меня это не очень возбуждает, потому что универсальных виджетов мало, а что-то более интересное надо делать под себя все равно. Поэтому для фреймворка важнее «уметь доделать свое», чем «побольше готового».

Также популярно мнение что GUI-фреймворк это look and feel, платформенно-зависимый или же просто не вырвиглазный. Типа это сложная часть, повторить лук платформы. Мне тоже пофиг. Дело в том, что сейчас самое идеальное время для GUI-фреймворка: все наигрались в игру «сделай look and feel как настоящий» и привыкли к веб-приложениям, где вообще каждый первый сайт разный. Плюс в моду вошел flat и минимализм, то есть виджеты рисовать дешево и просто, как никогда. А платформенный look and feel это иллюзия, все равно в каждом реальном приложении миллион случаев, которые не укладываются в стандартные checkbox/input/dropdown. И чем больше приложение, тем больше надо тюнить и дорисовывать самому. UI это не лего, его надо дизайнить и рисовать как целое, тогда будет гармонично.

Таким образом, от GUI фреймворка мне бы хотелось иметь базовые сложные вещи покрытыми (платформенно-зависимая обработка ввода, скроллинг, быстрый рендеринг, вывод шрифтов, dpi handling), какие-то базовые графические примитивы (прямоугольник там, линия, градиент, тенюшечки, svg) и возможность залезть под капот и все застайлить и запрогать как хочется.

Я НЕ ищу сокращения затрат на дизайнера за счет использования готовых компонент/дефолтного look and feel. Меня интересует возможность потратить много и долго, но сделать самому и хорошо, чем кое-как и из готового. Pixel-перфект и именно так, как мне нужно, а не так, как автор фреймворка сделал и сейчас уже хрен отковыряешь. Качественное вылизанное end-user приложение, а не дешево выглядящий массово производимый enterprise.

Читайте также:  Windows file server tools

UPD: Ну и не надо учить меня программировать. Наверное навязывать там свой MVC или VDOM или что сейчас модное и свежее сильно не стоит. А то мода меняется, а фреймворк должен выжить.

То есть нужны идеально композируемые низкоуровневые примитивы без look and feel.

Чтобы не повторять ошибок истории, надо их знать. Я не знаю. Поэтому мне нужна ваша помощь: расскажите, что да как, коротко, доходчиво, грубо. Вопросы конечно кажутся философскими, но нужны именно конкретные инсайты. Ответ «WPF гААААвно» не нужен, он не конкретный и непонятно, в чем конкретно затык, а вот «в WPF нельзя было делать мультидокументные приложения, поэтому он сошел на нет» (например) очень хороший ответ.

Вопросы примерно такие:

— Почему у Java не получилось AWT?

— Зачем понадобился Swing? Что принципиально изменилось по сравнению с AWT? Я так понимаю AWT пилился на C++, а Swing на Java? И стало лень писать по версии под платформу?

— Почему Swing плохо работает? Это косяк реализации или какая-то принципиальная проблема? И в чем именно заключается это «плохо работает»? Тормозит? Разъезжается? Что?

— Что за история с JavaFX, зачем он был нужен, зачем начинать опять новый фреймворк, какую принципиальную инновацию по сравнению со Swing хотели привнести (неужели CSS?) и что не задалось? Почему ноль интереса? Все разочаровались?

— Есть ли какой-то принципиальный затык в реализации кросс-платформенных GUI? У веба вроде бы получается, почему больше ни у кого нет?

— Почему Windows переизобретает свой тулкит в каждой версии, а macOS живет на Cocoa десятилетиями?

— Какое положение занимает QT? Я так понимаю что он C++ и bloated, то есть нацелен больше на энтерпрайз?

— Flutter подход выглядит а) разумно и б) достаточно правдоподобно в) не как говно. То есть поднять свой GUI тулкит с нуля вполне можно и можно даже достаточно убедительно сэмулировать нативный look-and-feel. Почему ни у кого больше такое не получалось?

— Если брать не только кросс-платформенные GUI, то какие есть киллер-фичи, которых больше нигде нет? Что незаменимо и неповторимо?

— UPD 2: Я читаю, что в JavaFX вводится Scene Graph, а в Swing все на JPanel. При этом разница ускользает от меня. Чем принципиально отличаются подходы? (кроме названий классов)

— UPD 3: Я ничего не знаю про tcl/tk, но многие вспоминают его с теплом. Почему?

В общем, интересует история развития мысли и инсайты. Истории вроде «взяли ту же идею и понадеялись что сделаем лучше, а получилось то же самое» — не интересуют. Ну потому что а что вы ожидали? Истории «у фреймворка Х была вООООт такая амбиция (какая?), но он разбился о такую проблему (какую?)» — интересуют очень.

Если вы работали с GUI кроме веба, расскажите, что там у вас была за история?

Кроссплатформенный GUI на C# и веб-технологии

Самая первая спецификация продукта, частично устная, содержала требование – наличие кроссплатформенного(Windows, Linux, Mac) клиента под десктоп и облегченную версию мобильного(Windows, Android, iPhone). По возможности интерфейс должен быть максимально похожим на разных ОС.
Благодаря Mono мы можем писать кроссплатформенные приложения, но вопрос с GUI остается открытым. Имеющиеся технологии под .Net(Windows Forms, WPF) хорошо работают только под Windows, и у нас уже был печальный опыт портирования Windows Forms. Под Linux мы можем использовать GtkSharp, но идея ставить Mono на Windows при наличии .Net мне не нравится. В итоге приходится писать и поддерживать отдельный интерфейс под каждую ОС.
Что в этой ситуации могла придумать команда .Net(с уклоном под веб)? Решили встраивать Webkit и писать GUI на связке html-js-css.
На сегодняшний день мы 2 года успешно используем такой подход для Windows и год – под Linux и Mac. До мобильной платформы пока руки не дошли.

Читайте также:  Windows drivers visual studio

Зачем?

Идентичный интерфейс под всеми платформами. Возможны лишь незначительные отличия при отрисовке шрифтов, при отображении элементов. Последнее всегда объясняется ошибками в верстке.
Разработка под одну ОС. Эмпирическим путем нами было выявлено, что достаточно вести основную разработку под Windows, а под остальными платформами лишь иногда проверять. Например, перед релизом.
Вся сила веб-разработки. Особенно это актуально, если команда состоит из веб-разработчиков. Можно использовать html5, css3, привычные подходы и библиотеки. Мы, кстати, используем популярный фреймворк для построения веб-приложений, в итоге у нас интерфейс только на js.
Разделение на frontend и backend. Появляется возможность вести отдельно разработку представления и логики приложения, согласовав апи. Например, наш интерфейс — это полноценное веб-приложение, взаимодействующее с «сервером» через ajax-запросы. В десктоп приложении эмулируем обработку этих запросов. Таким образом, можно разрабатывать и отлаживать интерфейс с использованием инструментов разработчика в Chrome, закинув необходимые mock ответы на локальный сервер. Особо уверенные в себе разработчики, которым достаточно доступа к dom и консоли, могут использовать firebug lite в десктоп приложении.
Есть о чем написать на хабр. Подобные эксперименты добавляют азарта при разработке и скрашивают суровые будни программиста.

Под каждую платформу создаем нативное приложение, GUI которого состоит из одного элемента пользовательского интерфейса – браузера, растянутого во все окно.
Нам нужно научиться отображать html в браузере, найти способ осуществлять вызовы js-C# и С#-js. Различия в вызовах могут показаться странными, но есть простое объяснение – в используемых браузерах реализован и работает разный функционал.

Mac OSX

Выбора что встраивать под маком нету. Поэтому используем MonoMac и стандартный браузер. Но тут есть подвох в лицензиях. Можно свободно распространять приложение без Mono, т.е. пользователь сам должен будет поставить Mono и, следовательно, приложение не может попасть в AppStore. Если же мы хотим встроить Mono в приложение, то придется покупать Xamarin.Mac, который обойдется в 300 или 1000 долларов в зависимости от размера компании за одного программиста.
Под мак получился самый лаконичный код. Единственное не интуитивно понятное место — вызов С# из js.
После инициализации браузера нам надо создать объект, через который js сможет вызывать методы контроллера из C#. Назовем объект interaction:

Определяем методы и указываем, какие из них могут быть вызваны из js:

Теперь в js мы можем вызвать метод сallFromJs:

Рабочий пример на github.
Этого видео мне очень не хватало, когда я разбирался: «Как добавить ссылку на WebView в код контроллера».

Ubuntu

Под Mono используем пакет webkit-sharp.
Плавно увеличивается количество не интуитивно понятного кода.
Для вызова C# из js можно перехватывать переход по ссылке.

Вызов из js будет выглядеть так:

Еще один способ завязывается на событие TitleChanged.
В js устанавливаем title у документа:

В С# срабатывает событие TitleChanged, мы десериализуем title и аналогично предыдущему подходу вызываем обработчик.

В рассматриваемой обертке WebKit можно из С# исполнять любой js код, что позволяет нам реализовать вызов js из C#:

Windows

Основную разработку мы ведем под Windows.
Подробности уже были описаны моим коллегой год назад и за это время принципиально ничего не изменилось. В какой-то степени это свидетельствует о надежности подхода. Также в статье больше деталей, которые вполне достаточно рассмотреть на примере одной ОС.
Я лишь добавлю пример на github.

Оцените статью