Последние несколько дней я пытался найти библиотеку, которая бы позволила мне писать на C++ программы с GUI. Мои требования были довольно просты:
Достаточно только поддержки Windows;
Разрешено коммерческое использование;
Простая стилизация, в том числе и тёмный режим;
Результатом должен быть единый файл
.exe
размером меньше 40 МБ без или с минимальным количеством зависимостей;Написание части программы с GUI не должно занимать больше времени, чем сама функциональность.
WinUI 3
На первый взгляд кажется идеальным выбором. Позволяет использовать современные компоненты Windows, в то же время допуская настройку цветов стилизации. Для дизайна можно пользоваться XAML, который очень легко освоить, или же напрямую работать с Visual Studio designer.
Проблема: выпуск приложений в неупакованном виде поддерживается не очень хорошо. При попытках перенести приложение в VM или на другой компьютер чаще всего оно отказывалось запускаться из-за отсутствия каких-то непонятных зависимостей. Хуже того, в комплекте нужно поставлять несколько файлов .dll
, управляющих функциональностью WinUI. Получить единый портируемый файл .exe
невозможно. Использование упакованного вида обычно работает без проблем, но приложения устанавливаются как пакеты AppX, что привносит множество других проблем (особенно если вам нужен доступ ко всем Win32 API).
Win32 / MFC / небольшие библиотеки-обёртки для Win32
Мне нужна была высокая степень портируемости, так что логично было использовать нативный рендеринг операционной системы. Такая программа может быть единым файлом .exe
(если мы статически компонуем MFC) и в то же время очень маленькой (всего несколько килобайтов). Можно было бы использовать и ещё более минимальную библиотеку, которую уже написали, что позволило бы мне быстро превратить концепцию в работающее приложение.
Проблема: стилизовать нативные элементы управления (controls) Win32 крайне сложно. Мне пришлось бы писать собственную функцию Paint для каждого элемента управления, что потребовало бы столько времени, что я бы успел ещё и обзавестись семьёй. Существует «тайный» тёмный режим для элементов управления Win32, используемый в Проводнике Windows, который можно активировать, но он охватывает только часть элементов управления и выглядит не очень красиво.
Qt
Эта библиотека — Святой Грааль GUI для C++. Хотя она довольно сложна, в ней есть удобная стилизация при помощи языка Qt Style Sheets, похожего на CSS.
Проблема: при динамической компоновке для запуска приложения требуется куча разных .dll
общим размером более 40 МБ. Можно статически скомпоновать Qt в программу, что существенно уменьшит её размер (так как неиспользуемые части удаляются), но тогда по лицензии LGPL Qt вам придётся сделать её опенсорсной или распространять в виде объектных файлов. Или же можно ежегодно покупать коммерческую лицензию за несколько тысяч долларов.
wxWidgets
Достаточно простая в изучении библиотека с опцией использования wxFormBuilder. Её лицензия менее требовательна, чем у Qt, и её можно статически скомпоновать в исполняемый файл размером 3 МБ.
Проблема: в Windows эта библиотека использует нативные компоненты Win32 и не предоставляет никаких опций стилизации (так как мы не можем напрямую переписать функции Paint, она даже хуже, чем применение непосредственно Win32/MFC). Она поддерживает применение тёмных элементов управления Проводника Windows, но, как я говорил, они некрасивые.
hikogui
Довольно новая библиотека GUI retained mode, использующая в качестве бэкенда Vulkan. Имеет встроенный тёмный режим и достаточно проста в самостоятельной стилизации.
Проблема: для успешной компиляции вам понадобится докторская степень по computer science со специализацией в разработке ПО. Потратив больше получаса на попытки скомпилировать пример (в том числе различных веток и меток релизов), единственное, что мне удалось получить — это исполняемый файл, немедленно вылетавший с ошибкой нарушения доступа внутри какой-то библиотеки Vulkan, поэтому я просто сдался. Проект выглядит очень многообещающе, хотя мне и не нравится активное применение надоедливой STL (без которой иногда даже можно было обойтись).
Sciter
Хорошая альтернатива Electron, позволяющая писать GUI для десктопного приложения на HTML/CSS.
Проблема: вы могли подумать, что проблема будет заключаться в большом размере, но на самом деле готовое приложение со всеми .dll
занимает около 25 МБ, что меня вполне устраивает. Библиотека могла бы быть ещё лучше, если бы она была опенсорсной и можно было бы пользоваться статически скомпонованной версией для коммерческого использования (та же проблема, что и у Qt). Она не такая дорогая, как Qt (сейчас $310 за лицензию Indie), поэтому я бы заплатил и был счастлив. Но проблема в том, что, как видно на скриншоте (посмотрите на значки заголовка окна), рендеринг неидеален. У меня возникали всевозможные проблемы со сглаживанием шрифтов и изображений. Кроме того, что бы я ни делал, у окна сохранялась довольно толстая (2-3 пикселя) серая рамка, которую никак нельзя ни настроить, ни изменить.
WinForms / WPF
Если вы начнёте спрашивать на форумах про GUI-библиотеки C++ для Windows, то чаще всего вам будут говорить, что это плохая идея (не спорю с этим) и что вместо этого вам нужно писать фронтенд программы на каком-то другом стеке, а затем просто загрузить свою написанную на C++ функциональность как компонент/модуль. Это позволит легко стилизовать её и сильно ускорить разработку. Теоретически, можно получить единый .exe
небольшого размера и использовать WinForms/WPF. Это возможно реализовать двумя способами:
Встроить
.dll
как ресурс в приложение и заставить его извлекать библиотеку в какую-то временную папку, а затем использовать P/Invoke и вызывать скомпилированную.dll
из приложения на C#/.NET.Использовать C++/CLI.
Проблема: .NET Framework поставляется в комплекте с Windows 10+, так что, строго говоря, это удовлетворяет требованию отсутствия зависимостей. Проблема в том, что при встраивании .dll
его всё равно придётся куда-то извлекать и писать дополнительный код для работы P/Invoke, а C++/CLI компилируется в код .NET IL (иными словами, можно открыть получившееся приложение в dnSpy и увидеть код на C++, транслированный в эквивалент на C#); мне же нужно не это, а нативный код).
Решение?
Это лишь некоторые из рассмотренных мной вариантов. После длительных попыток работы со всевозможными библиотеками и даже написания собственных стилей MFC я осознал, что для простых приложений нет ничего более подходящего, чем Dear ImGui.
У неё есть недостатки, в основном возникающие при попытке создания сложных UI; кроме того, это UI не retained mode, а immediate mode, так что только для рендеринга UI с частотой 60 или более кадров нам придётся задействовать GPU-рендерер наподобие DirectX.
Однако библиотека отвечает всем остальным требованиям, потому что DirectX по умолчанию встроен в современные версии Windows.
Выше показан написанный мной пример того, как можно применять встроенную функцию множественных вьюпортов при создании простых приложений с GUI.
Скомпилированная программа весит всего 500 КБ и не требует ничего устанавливать, даже VC++ redistributable, если статически скомпоновать в него MFC.
Комментарии (189)
ImagineTables
01.07.2024 14:15+2Странные утверждения, я бы сказал. Начиная от приложения, которое можно статически слинковать с MFC и в то же время оно будет весить несколько килобайт, до неотключаемой рамки у скайтеровского приложения. Да и остальное не лучше. Я бы сказал, это всё не случайные ошибки, а глубокое непонимание сути. MFC это не GUI-библиотека, а фреймворк для поддержания полного жизненного цикла документа, гуишная часть там вспомогательная, как и замена STL, если это понимать, можно не строить иллюзий по поводу небольшого размера (хотя, конечно, он всё равно будет сильно меньше, чем у Хромиума, гы-гы). Что касается Скайтера, он не занимается никакими рамками.
bfDeveloper
01.07.2024 14:15+12ImGui - шедевр, каких мало, но я бы не сравнивал его с Qt или WPF, это соврешенно разные весовые категории. ImGui идеально решает задачу отображения вспомогательных данных, простых кнопочек и крутилок конфигов, но сложные интерфейсы ещё и с высокой степенью кастомизации я бы на нём делать не стал.
Arenoros
01.07.2024 14:15что может быть более кастамизируемо чем прямое взаимодейтсвие с шейдерами и всем остальным конвейером рендеринга без каких либо промежуточных API OS?))
Onito
01.07.2024 14:15Ну, на qt всё это тоже есть и с очень удобными обертками и интегрировано в виджеты, даже бэкенды на свой вкус можно выбрать а не только вулкан, только это надо ещё придумать гуй который нельзя сделать тем что есть и нужно лезть на этот уровень
Arenoros
01.07.2024 14:15в qt можно зарендерить чтоб кнопка при нажатии например взрывалась на партикли? если да то я этого реально не знал. И не совсем понял про "только вулкан" imgui поддерживает вообще любой рендерер который умеет треугольники рисовать. Ну и я не спорю что для больших приложений qt гораздо проще и быстрее использовать, по крайней мере пока что.
rPman
01.07.2024 14:15например взрывалась на партикли
очень жаль, что это тоже называют под одну гребенку GUI, просто когда обсуждают тот или иной движок, одни подразумевают возможность это сделать а другие даже не задумываются об художественных изысках и думают о том, например, как бы удобнее было делать элементы, взаимное расположение и размер которых взаимосвязаны сложным образом, а третьим подавай удобный функционал с visivyg биндингами с данными или синтаксическим сахаром для удобства описания этого.
А ведь изначально api/библиотеки для gui буквально занимались только доставкой контента (текста, изображений и компонентов взаимодействия) на экран рабочего стола... а сам контент пусть разработчик создает, зачем это тянуть в библиотеку? Qt например вырос не в просто движок для GUI но и сложную и многофункциональную (для своего времени) систему по работе со всем, начиная с работой с сетью или базами данных и заканчивая элементальными типами данных типа строки.
HemulGM
01.07.2024 14:15Такое не только qt может и тем более не только imGUI. В Delphi fmx тоже выбирается бэк. Gdi, opengl, directx, direct2d, metal, opengles, skia. И поддерживаются шейдеры, так что можно не только взорвать кнопку, но и поджечь рядом стоящие.
Wolf4D
01.07.2024 14:15+4Как у ImGui с accessability? Она довольно далека от нативных элементов, всё-таки. И как у приложения с её использованием с энергопотреблением? Если я пишу условный калькулятор или какой-нибудь генератор отчётов с двумя кнопочками и одной областью просмотра - не заставит ли это пользовательское железо раскочегаривать мощности GPU?
Mabu
01.07.2024 14:15Accessibility на нуле: NVDA не озвучивает текст под курсором.
Похоже что Accessibility нормально работает только в WinAPI.
viordash
01.07.2024 14:15+14а наследников Borland C++ нет уже?
Судя по дельфи, создание UI в виндовс, это было совсем несложно. И ехешник единый можно получить
TerrorDroid
01.07.2024 14:15+4Оно около живое в виде Embarcadero RAD Studio, на бумаге выглядит очень интересно, но чёрт его знает как оно в жизни
mentin
01.07.2024 14:15Там вроде нативные контролы - то есть отпадает по критерию стилизации и темной темы. Вообще без этого критерия всё было бы гораздо проще. Ну или если бы нативные контролы поддержали стилизацию (это уже совсем мечты).
plashenkov
01.07.2024 14:15+6Там есть VCL и FireMonkey. Последний — кроссплатформенный (Windows, Linux, mac), поддерживает визуальные стили. VCL (нативные контролы) также поддерживает стили, есть тёмный стиль Windows 11, очень приличный (ставится через GetIt). У Delphi и C++Builder есть и бесплатные версии сейчас. Вообще технологически всё это очень приличное. Для меня всё выглядит так, будто Delphi / С++Builder в какой-то момент проиграла некую информационную войну. При этом технология не просто приличная, а прекрасная.
morgot
01.07.2024 14:15+1Студия в 2008 или каком году стала бесплатной, имею ввиду сначала экспресс, а потом комьюнити. А дельфи не могла себе этого позволить, видимо поэтому и проиграли. Жаль, VCL намного лучше убогого MFC
HemulGM
01.07.2024 14:15+2В Delphi нативные контролы поддерживают стилизацию. Как уже сказали ниже, есть масса всевозможных тем (а точнее, скинов). В том числе и выглядящих нативно. Например, как темная тама Win10/11.
Классическое Win32 приложение на Delphi + VCL
maxcat
01.07.2024 14:15Скины это старомодно. Вот стили и темы другое дело.
На делфи наверное сильно неудобно менять облик элементов вплоть до грязных знаков с изменением приватных полей на каждый чих, а не как на WPF: задал стиль, засунул его в словарь ресурсов и применяешь на элементы, их потомки, составные элементы
HemulGM
01.07.2024 14:15+1В VCL с этим не очень. А вот в FMX с этим легче легкого. И удобнее даже, чем WPF.
Hidden text
Создал стиль (для чего угодно). При чем создал визуально
И применяешь к чему угодно
При этом, в стиле могут быть любые поля и контролы, к которым можно получать доступ для каждого отдельного конечного контрола
Последний скрин - это то, что сделано именно таким способом. Здесь каждый контрол имеет свой стиль (WinUI 3, в данном случае). Создан отдельно мной. Всё исключительно штатными средствами.
shybovycha
01.07.2024 14:15+2не в С++, но в паскале был вроде опенсорсный Lazarus, но это ближе к Delphi
Flyingfolds
01.07.2024 14:15+1C++ Builder просто замечательный и удобный. Главный минус это в том что писать на нём будешь сам и только для себя.
rPman
01.07.2024 14:15Скажи честно, долго ли мидлу или выше уровнем программисту, без практики с продуктами borland, разобраться в проекте с++ builder, ничем не отличается от любого другого проекта на c++, и идеологии visyvig построения интерфейсов.
Hidden text
Я бы вот с майкрософтовским wpf по остерегся иметь дело, но это наверное личная неприязнь из прошлого а не обоснованные претензии.
morgot
01.07.2024 14:15Есть, и почему-то про С++ билдер (сейчас он иначе называется) все забывают
А как по мне, идеальный вариант по быстрому сделать Gui, если только под винду
TerrorDroid
01.07.2024 14:15+2Было бы интересно посмотреть, что было бы при использовании RAD Studio — они вроде активно рекламируют кросс-платформернность, гибкий UI и мелкий размер
Indemsys
01.07.2024 14:15Вот статья где реализован симулятор файловой системы на C++ в RAD Studio. Весит 3 мегабайта. Сама файловая система не больше десятка килобайт занимает.
Но меньше там не получить, потому что RAD тянет с собой огромный кусок библиотеки VCL с ресурсами если нужен единственный .exe
alan008
01.07.2024 14:15Кросс платформенные компоненты GUI (т.н. Fire Monkey) до сих пор какие-то странные/сырые, хотя появились лет 10 назад. Доверять в Delphi можно только старым компонентам VCL , но этот фреймворк не кроссплатформенный, он только под Windows
HemulGM
01.07.2024 14:15Не соглашусь. Они странные (т.е. их нужно понять). Они далеко уже не сырые и прекрасно справляются со своей задачей. Множество проектов на FMX уже несколько лет в проде прекрасно себя чувствуют.
HemulGM
01.07.2024 14:15Вот пример кроссплатформенного проекта на delphi (и нет, это не html)
https://github.com/HemulGM/ChatGPT
xi-tauw
01.07.2024 14:15+3стилизовать нативные элементы управления (controls) Win32 крайне сложно. Мне пришлось бы писать собственную функцию Paint для каждого элемента управления, что потребовало бы столько времени, что я бы успел ещё и обзавестись семьёй.
В прошлой жизни, мне надо было перенести код с чего-то типа Borland C++ Builder на чистую студию, сохранив 5-6 кастомных "красивых" окошек. С одной стороны, там были только кнопки, рисунки, чекбоксы и эдиты, с другой - весь перенос занял у меня месяца два с полной поддержкой всяких радостей типа разных цветов для активной-неактивной-нажатой кнопки. Так что переписывание обработчиков WM_PAINT не настолько страшное, как представляется.
qw1
01.07.2024 14:15У автора вопрос не в том, чтобы раз перенести, а чтобы в будущем на этом быстро делать приложения.
В вашем подходе, насколько сложно добавить новую кнопку нужного цвета? Снова придётся переопределять WM_PAINT? Портируемое приложение устоялось и меняться не будет. А новое - раскрашивал кнопку полдня, потом кнопка не пригодилась - работа впустую.
DesertDragon
01.07.2024 14:15Вроде есть полуавтоматизированное перекрашивание нативных win32 контролов:
https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/apply-windows-themes
xi-tauw
01.07.2024 14:15Соглашусь, что мы с автором решали разные задачи, но это не умаляет того, что сложность процесса все же переоценена.
AllKnowerHou
01.07.2024 14:15Pyqt+pyinstaller
Ikolo92
01.07.2024 14:15+2Эм... Изначально поставили цель писать на C++. Ладно б вы ещё шарп посоветовали, но, если человек пишет на плюсах, значит 99% вероятность, что с питоном его задача не совместима априори
AllKnowerHou
01.07.2024 14:15Вроде тема такая: Разработка интерфейса для Windows — это боль
Ikolo92
01.07.2024 14:15Ну мы же взрослые люди. Умеем читать не только заголовок.
Последние несколько дней я пытался найти библиотеку, которая бы позволила мне писать на C++ программы с GUI. Мои требования были довольно просты:
AllKnowerHou
01.07.2024 14:15писать на C++ программы с GUI
Вчерашний день
Ikolo92
01.07.2024 14:15Да какая разница. Человеку нужно - мы можем только посоветовать, если он об этом просил
Elendiar1
01.07.2024 14:15А как тогда с rust? У него есть неплохой крейт tauri и windows-rs. Я с электрона на него пересел. Правда насчет портативности не в курсе - использую nsis установщик.
Но выходной размер - мое почтение.
qw1
01.07.2024 14:15Но выходной размер - мое почтение
Я думал, в хорошем смысле )))
А тут html/js/react, значит, надо в себя включать браузер.Elendiar1
01.07.2024 14:15Так я и в хорошем, там используется системный webview. Размер инсталлятора можно уложить в пару(2/3/5) мегабайт.
KhodeN
01.07.2024 14:15В случае с tauri - нет, его фишка в том, что он на каждой платформе использует платформенный WebView, т.е. браузер с собой не тащит.
qw1
01.07.2024 14:15А в Windows какой системный WebView? IE11? Старый Edge? Новый Edge?
plashenkov
01.07.2024 14:15+2Если вы зайдёте в список установленных приложений, то найдёте там "Среда выполнения Microsoft Edge WebView2 Runtime". Вот это оно. Т.е. актуальный Edge, основанный на Chromium
bogolt
01.07.2024 14:15+7Win32/ImgUI/wxWidgets/Qt в одном сравнении ? Ну такое.
Мы сравнили: нож, газонокосилку, набор отверток и роботизированный завод по производству роботизированных заводов... и оказалось что консервной банки достаточно для забивания двух гвоздей в домашних условиях.
Ну правда, ImGui и виджеты?
Win32 и Qt ?
Автор это очень очень разные штуки, если они у вас в одном сравнении вы вообще не понимаете что вам нужно.
ImGui это круто, но там совершенно непривычная модель рендеринга, когда вы каждый фрейм говорите системе что именно рисовать, совершенно противополжная всем другим моделям, где вы создаете объекты и они там как-то существуют.
WxWidgets это полный простите пиздец, единственная ( сомнительная ) ценность которого это нативные контролы операционной системы. Впрочем может он за прошедшие 10 лет возмужал, но по моим воспоминаниям пользоваться этим нерабочим поделием было невозможно.
Win32 - да можно, но это боль и бессмысленно низкий уровень. Если конечнь цель экономить кило/мегайбайты, чисто по фану то да, иначе просто бессмысленно.
Qt - серьезный продукт на котором можно запилить как мини прогу так и большое тяжело приложение с чем угодно.
(остальные решения щупать не доводилось ).
dalerank
01.07.2024 14:15ImGui самая обычная модель отрисовки и обработки событий, если вы посмотрите из какой области пришел сам фреймфорк. Это самый простой цикл обработки сообщений в играх и графических приложениях.
bogolt
01.07.2024 14:15+2Да я понимаю, но согласитесь сранивать ImGui с Qt это.. ну я не знаю даже... они разные настолько что области их применения почти не пересекаются. И там и там можно сделать кнопки но с совершенно разной сложностью и целями.
ImGui крут когда у нас есть наш движок и нужно в него добавить пару кнопок, берем и делем. А Qt это же целый мир, если уже брать Qt то придется все на нем делать там соверешнно другая модель разработки и сложность собственно решений. Да и добавить Qt в уже существующий проект это ппц как дорого, а вот докинуть пару файлов imgui должно быть в разы проще. Короче я не понимаю зачем эти вещи в одном списке.
dalerank
01.07.2024 14:15Это да, хочется и красиво и код не писать. Автор похоже просто мечется в море ui фреймворков, не зная к какому берегу примкнуть. Из того что мне довелось пробовать можно добавить еще boden, cegui, elements, foxui, gltk, gacui, nana, mygui, nanogui, rml, xtd. И все небольшие, все можно скомпилить в пару сотен кб
Dooez
01.07.2024 14:15Возможно ImGui не так удобен если нужна стилизация. Нет разделения на форму и код. Нет встроенной поддержки системных тем.
Но функционально на нем можно сделать наверное все, что может понадобиться в относительно нормальном интерфейсе. А с дополнениями вроде ImPlot вообще мощнейший инструмент с минимальными затратами на освоение.
Мне искренне интересно, что по-вашему может Qt, что не получится сделать с Dear ImGui?
HemulGM
01.07.2024 14:15Например, удобную работу юзера с таблицами, взаимодействием с ОС, четкая отрисовка шрифтов, работа с окнами, привычный вид элементов интерфейса, оптимизация отрисовки (частичная, а не всегда всю сцену). Работа с текстом и многое, многое другое, что всплывает при разработке
Arenoros
01.07.2024 14:15согласен только касаемо "привычный вид элементов интерфейса" и то это спорный аргумент, благодаря засилию веб технологий для отрисовки гуи сейчас иметь нативный вид элементов вообще не в тренде, можно открыть 10 своих самых "любимых" приложений и не увидеть там ни одного нативного элемента.
а по поводу всего остального, чего из перечисленного нет тут, тут или тут
HemulGM
01.07.2024 14:15Не, конечно, "нативный" вид контролов не котируется, особенно в Windows. Но я всё же имел ввиду именно привычность структуры контрола. И ожидаемое поведение.
vagon333
При уважении к желанию Сэма (автора), есть прекрасный тост (из известного фильма) про желания и возможности.
Если изначально UI либы созданы и поставляются как наборы DLL и ресурсов, то желание запихнуть все в один EXE-шник, а затем динамически распаковывать звучит так себе.
Получается: либо свое, либо узкий набор решений.