C++Builder реально классная штука: кидаешь форму мышкой, накидываешь кнопок, дважды кликаешь и пишешь обработчик.
Но однажды я задал себе простой вопрос. Эта про технологию или про продукт?
И решил проверить. Так появился OpenRTL, свободная реализация ядра RTL/VCL-парадигмы на стандартном C++17. Без проприетарных компиляторов, без закрытых библиотек, без лицензий.
То, на что у Embarcadero ушли десятилетия, воспроизводится примерно за 1500 строк, если понимаешь парадигму. Не потому что я гений. А потому что всех убедили, что это сложно. На самом деле не сложно. Просто никто не брался.
Почему это вообще важно
C++Builder Professional стоит $1,599. RAD Studio Architect стоит $4,199. Причём C++Builder дороже Delphi, а умеет меньше. Embarcadero продаёт не технологию. Технология старая и давно не секрет. Они продают монополию. Потому что альтернативы нет.
Есть Lazarus и Project Fresnel. Они ломают монополию, но идут со стороны Pascal и отказываются от VCL-парадигмы. Мне хотелось другого. Сохранить саму VCL-парадигму, но реализовать её на стандартном C++. Но была и вторая проблема, серьёзнее лицензий.
Как устроена VCL
Прежде чем говорить про реализацию, напомню, из чего вообще состоит VCL
Иерархия. Всё начинается с TObject, это корень. У него есть ClassName() и InheritsFrom() — ручной RTTI, без typeid и dynamic_cast как основы. Дальше идёт TComponent: всё, что может чем-то владеть. Потом TControl: всё, что можно показать на экране. Потом TOSControl, TCustomForm, TForm, и уже от них конкретные контролы: TButton, TLabel, TEdit, TComboBox, TCheckBox, TPanel.
Владение. TComponent владеет другими TComponent через Owner и OwnedComponents. Кнопка может принадлежать форме, значит форма её удалит. Это не то же самое, что родитель на экране, и путать их не надо.
Визуальная иерархия. TControl знает своего Parent и список ChildControls. Это про то, кто кого рисует и кто в кого попадает мышью. В VCL это две разные вещи, и это принципиально. Кнопка может принадлежать форме (форма её удалит), но визуально лежать на панели. В Qt это слито в QObject::parent. В VCL же это разделено.
События. OnClick, OnChange, OnClose, OnMouseDown, OnKeyDown. В C++ это std::function, в Object Pascal method pointer. Событие это просто поле. Его можно назначить, переназначить, очистить. Ничего особо нового.
Сгенерированный код. IDE генерирует класс формы: глобальный Application, глобальный Form1, _tWinMain с Application->Initialize(), Application->CreateForm(Form1), Application->Run(). Конструктор TForm1 создаёт контролы и настраивает свойства. Всё остальное лежит в DFM-файле, который IDE читает и пишет.
Что здесь важно для нас. Всё это идеи. Ни одна из них не привязана к Win32, к конкретному компилятору или к конкретному вендору. TObject это просто класс. Owner это просто указатель. OnClick это просто функция. Иерархия это просто наследование. Всё это можно реализовать на стандартном C++.
А теперь поехали: VCL не должен знать про Win32
C++Builder это инструмент только под Windows, и VCL тоже завязан на Windows. TWinControl знает про HWND, TCanvas знает про HDC, TForm знает про WndProc. Перенести это на Linux без переписывания половины кода не выйдет. Поэтому Embarcadero и не делает VCL кроссплатформенным: у них это надстройка над Win32, а не самостоятельная парадигма. FireMonkey они писали с нуля, потому что VCL под другие системы уже не переделать
В этом и есть главная идея OpenRTL
VCL-слой не знает, под какой ОС он работает. Совсем. TControl не знает про HWND. TForm не знает про WndProc. TCanvas не знает про HDC. Всё, что VCL знает про платформу, это абстрактный интерфейс IOSDriver.
class IOSDriver { public: virtual ~IOSDriver() = default; virtual std::unique_ptr<IOSHandle> CreateControl(const ControlDesc& d) = 0; virtual std::unique_ptr<TCanvas> CreateCanvas(IOSHandle* h) = 0; virtual const char* Name() const = 0; virtual int RunMessageLoop() = 0; virtual void SetBounds(IOSHandle* h, int l, int t, int w, int ht) = 0; virtual void SetVisible(IOSHandle* h, bool v) = 0; virtual void SetText(IOSHandle* h, const std::string& text) = 0; virtual std::string GetText(IOSHandle* h) const = 0; virtual void SetEnabled(IOSHandle* h, bool e) = 0; virtual void Invalidate(IOSHandle* h) = 0; virtual void SetCheck(IOSHandle* h, bool c) = 0; virtual bool GetCheck(IOSHandle* h) const = 0; virtual void AddString(IOSHandle* h, const std::string& s) = 0; virtual void SetSel(IOSHandle* h, int idx) = 0; virtual int GetSel(IOSHandle* h) const = 0; virtual void SetEventSink(IOSHandle* h, IEventSink* sink) = 0; };
С другой стороны - IEventSink. Это то, как ОС сообщает VCL, что что-то произошло
struct OSEvent { enum Type { MouseDown, MouseUp, MouseMove, KeyDown, KeyUp, Resize, Move, Close, Paint, Show, Hide, Command, Change }; Type type = Paint; int x = 0, y = 0; int button = 0; int key = 0; int width = 0, height = 0; uint32_t timestamp = 0; bool cancel = false; }; class IEventSink { public: virtual ~IEventSink() = default; virtual void OnOSEvent(OSEvent& e) = 0; };
OSEvent это нормализованное событие
Не WM_PAINT, не WM_LBUTTONDOWN. Просто Paint, MouseDown. Платформа сама обязана перевести своё сообщение в этот формат.
Между ними находится IOSHandle. Это непрозрачный указатель на то, что ОС считает окном
struct IOSHandle { virtual ~IOSHandle() = default; };
VCL не знает, что внутри. Для Win32 это HWND. Для GTK4 это GtkWidget. Для Cocoa это NSView. Она просто передаёт его драйверу и говорит: сделай с ним вот это
Как это выглядит в цепочке
Win32 message (WM_COMMAND) -> WndProc (Win32-специфичный) -> Win* из GWLP_USERDATA (Win32-специфичный) -> ITWindowsDriver::OnCommand (Win32-специфичный) // ===========> Переходная граница Emit() → OSEvent{type=Command} -> IEventSink::OnOSEvent(OSEvent) -> TControl::OnOSEvent -> FOnClick
Выше границы живёт Win32. Ниже границы живёт чистый VCL. TControl не знает, что WM_COMMAND существует. Он знает только, что пришёл OSEvent::Command
Как это работает на практике
virtual void CreateHandle(IOSHandle* parentHandle) { if (FHandle) return; if (!FDriver) return; ControlDesc d; d.kind = Kind(); d.caption = FCaption; d.x = FLeft; d.y = FTop; d.w = FWidth; d.h = FHeight; d.visible = FVisible; d.enabled = FEnabled; d.id = FId; d.parent = parentHandle; FHandle = FDriver->CreateControl(d); //... }
TOSControl формирует описание контрола, ControlDesc, и отдаёт его драйверу. Что драйвер с ним сделает, уже не его дело. TWindowsDriver вызовет CreateWindowExW. TGTKDriver вызовет gtk_button_new. TCocoaDriver вызовет [[NSButton alloc] init]. TOSControl об этом никогда не узнает.
void OnOSEvent(OSEvent& e) override { switch (e.type) { case OSEvent::KeyDown: { int key = e.key; if (FOnKeyDown) FOnKeyDown(this, key, 0); break; } case OSEvent::Change: if (FOnChange) FOnChange(this); break; case OSEvent::Close: if (FOnClose) FOnClose(this, e.cancel); return; default: inherited::OnOSEvent(e); return; } }
С событиями та же логика. TOSControl не разбирает WM_KEYDOWN. Он получает OSEvent::KeyDown с полем key. Откуда взялся key, из Win32 WPARAM, из GTK GdkEventKey::keyval или из Cocoa NSEvent::keyCode, не важно. Драйвер уже нормализовал
Что это даёт
Кроссплатформенность не потом, а по архитектуре.
Я не пишу #ifdef _WIN32 в VCL-слое. Совсем. Потому что VCL-слой не знает, что такое Windows. Если завтра я напишу TGTKDriver, VCL-слой не изменится ни на строку. Достаточно реализовать IOSDriver для GTK4.
Win32 можно заменить, не трогая VCL.
Если завтра Microsoft поменяет Win32 на что-то другое (шутка, но всё же), я перепишу TWindowsDriver, а VCL останется. Если я захочу использовать WinRT или UWP, перепишу драйвер.
Отладка становится проще.
Когда что-то не работает, я точно знаю, где искать. Проблема с отрисовкой? Либо TCanvas в VCL, либо TWindowsCanvas в драйвере. Проблема с событием? Либо TControl::OnOSEvent в VCL, либо Emit в драйвере. Граница проходит по OSEvent, и это точка разреза.
Можно тестировать VCL без ОС.
В теории можно написать TNullDriver, который ничего не создаёт, но логирует вызовы. И тестировать логику VCL без единого окна. Я этого пока не сделал, но архитектура это позволяет. Это прямое следствие того, что VCL не знает про Win32.
Как выглядит драйвер
Здесь весь Win32
Вот код, который превращает ControlDesc в реальное окно Win32. Это сердце TWindowsDriver
std::unique_ptr<IOSHandle> CreateControl(const ControlDesc& d) override { HWND parent = d.parent ? static_cast<Win*>(d.parent)->hwnd.get() : nullptr; DWORD style = 0, exStyle = 0; const wchar_t* cls = nullptr; switch (d.kind) { case ControlKind::Form: cls = L"VCLFormClass"; style = WS_OVERLAPPEDWINDOW; EnsureClass(cls); break; case ControlKind::Panel: cls = L"VCLPanelClass"; style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; EnsureClass(cls); break; case ControlKind::Label: cls = L"STATIC"; style = WS_CHILD | WS_VISIBLE | SS_LEFT; break; case ControlKind::Button: cls = L"BUTTON"; style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON; break; case ControlKind::CheckBox: cls = L"BUTTON"; style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_AUTOCHECKBOX; break; case ControlKind::Edit: cls = L"EDIT"; style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_AUTOHSCROLL; exStyle = WS_EX_CLIENTEDGE; break; case ControlKind::ComboBox: cls = L"COMBOBOX"; style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL; break; case ControlKind::ListBox: cls = L"LISTBOX"; style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY; exStyle = WS_EX_CLIENTEDGE; break; } if (!d.visible) style &= ~WS_VISIBLE; if (!d.enabled) style |= WS_DISABLED; int x = d.x, y = d.y, ww = d.w, hh = d.h; if (d.kind == ControlKind::Form) { RECT r{ 0, 0, ww, hh }; AdjustWindowRectEx(&r, style, FALSE, exStyle); ww = r.right - r.left; hh = r.bottom - r.top; } int ctrlId = 0; if (d.kind != ControlKind::Form && d.kind != ControlKind::Panel) ctrlId = (d.id ? d.id : FNextId++); return CreateWin(d, cls, style, exStyle, parent, x, y, ww, hh, ctrlId); } std::unique_ptr<Win> CreateWin(const ControlDesc& d, const wchar_t* cls, DWORD style, DWORD exStyle, HWND parent, int x, int y, int w, int h, int ctrlId) { auto win = std::make_unique<Win>(); win->driver = this; win->kind = d.kind; win->id = d.id; win->isForm = (d.kind == ControlKind::Form); win->hwnd.reset(::CreateWindowExW( exStyle, cls, Utf8ToW(d.caption).c_str(), style, x, y, w, h, parent, (HMENU)(INT_PTR)ctrlId, FInst, nullptr)); if (!win->hwnd) return nullptr; AttachWin(win->hwnd.get(), win.get()); return win; }
CreateControl достаёт родительский HWND из IOSHandle. d.parent - это IOSHandle*, внутри которого лежит Win*, а внутри Win — сам HWND. VCL-слой об этом не знает: он передал непрозрачный указатель, драйвер сам разобрался, что с ним делать.
Теперь собственно создание окна
std::unique_ptr<Win> CreateWin(const ControlDesc& d, const wchar_t* cls, DWORD style, DWORD exStyle, HWND parent, int x, int y, int w, int h, int ctrlId) { auto win = std::make_unique<Win>(); win->driver = this; win->kind = d.kind; win->id = d.id; win->isForm = (d.kind == ControlKind::Form); win->hwnd.reset(::CreateWindowExW( exStyle, cls, Utf8ToW(d.caption).c_str(), style, x, y, w, h, parent, (HMENU)(INT_PTR)ctrlId, FInst, nullptr)); if (!win->hwnd) return nullptr; AttachWin(win->hwnd.get(), win.get()); return win; }
Win - это структура-обёртка над HWND. Она хранит сам хендл, указатель на драйвер, IEventSink, тип контрола и id.
Это нужно, чтобы WndProc мог достать Win* из HWND и передать сообщение дальше - драйверу, а тот уже отправит его в VCL как OSEvent
CreateControl - это большой switch по ControlKind. Каждому типу контрола соответствует свой системный класс Win32 (BUTTON, EDIT, STATIC, COMBOBOX) и набор стилей (WS_*, BS_*, ES_*, CBS_*). VCL передаёт ControlDesc, драйвер переводит его в вызов CreateWindowExW. Для формы дополнительно вызывается AdjustWindowRectEx — она переводит клиентские размеры в размеры окна с рамкой. После создания окна указатель на Win записывается в GWLP_USERDATA, чтобы WndProc мог найти драйвер. Никакие Win32-константы наружу не уходят: VCL знает только ControlKind::Button, а не BS_PUSHBUTTON
void OnCommand(HWND, Win*, WORD code, HWND child, WORD) override { if (!child) return; auto* sink = SinkForHwnd(child); if (!sink) return; OSEvent e; e.key = (int)code; switch (code) { case BN_CLICKED: e.type = OSEvent::Command; sink->OnOSEvent(e); break; case CBN_SELCHANGE: case EN_CHANGE: e.type = OSEvent::Change; sink->OnOSEvent(e); break; } }
Как это выглядит целиком
class TForm1 : public TForm { INHERITED(TForm); public: explicit TForm1(TComponent* owner) : TForm(owner) { SetCaption("Hello VCL (Win32)"); SetBounds(200, 200, 480, 320); OnClose() = [](TObject*, bool& CanClose) { int r = MessageBoxW(nullptr, L"Точно закрыть приложение?", L"Подтверждение", MB_YESNO | MB_ICONQUESTION); CanClose = r == IDNO; }; auto* panel = new TPanel(this); panel->SetParent(this); panel->SetBounds(10, 10, 460, 80); auto* label = new TLabel(panel); label->SetParent(panel); label->SetBounds(20, 30, 400, 24); label->SetCaption("Press the button!"); auto* button = new TButton(this); button->SetParent(this); button->SetBounds(20, 120, 160, 40); button->SetCaption("Click me"); button->OnClick() = [label](TObject*) { label->SetCaption("Clicked at " + std::to_string(GetTickCount64())); }; } };
Иерархия вызовов
Win32 message => WndProc => Win* (GWLP_USERDATA) => ITWindowsDriver::OnXxx() => Emit() → IEventSink::OnOSEvent(OSEvent) => TControl::OnOSEvent / TOSControl::OnOSEvent => FOnClick / FOnChange / FOnKeyDown
RTL-слой полностью идиоматичен точке входу самой RAD Studio
На момент написания этой статьи RTL-слой реализован полностью: TObject, TComponent, Exception, иерархия исключений, владение. Всё, что есть в настоящем RTL. А сгенерированный класс формы (TForm1) полностью совместим и похож на то, что генерирует RAD Studio, вплоть до Application, Form1, _tWinMain и порядка инициализации. Разница только в архитектуре под капотом.
Это ровно тот код, который сгенерировала бы RAD Studio, если бы у неё был такой бэкенд. Application, Form1, _tWinMain, порядок инициализации, способ создания контролов через new + SetParent + SetBounds, лямбды вместо published-методов. Всё это совместимо и похоже на оригинальный сгенерированный код. Если ты писал на C++Builder, ты узнаешь этот код с первого взгляда.
// Глобальные объекты - как в IDE VCL std::unique_ptr<TApplication> Application; TForm1* Form1 = nullptr; // _tWinMain - билдеровский вход в стиле IDE. int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) { try { Application->Initialize(); Application->MainFormOnTaskBar = true; Application->CreateForm(Form1); Application->Run(); } catch (Exception& exception) { Application->ShowException(&exception); } catch (...) { try { throw Exception(""); } catch (Exception& exception) { Application->ShowException(&exception); } } return 0; } // wWinMain - настоящая точка входа CRT. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int) { TWindowsDriver driver(hInstance); Application = std::make_unique<TApplication>(nullptr); Application->SetDriver(&driver); Application->SetTitle("VCL Demo"); Form1 = new TForm1(Application.get()); return _tWinMain(hInstance, nullptr, nullptr, 0); }
Полный исходный код проекта собирается обычной студией MSVC
Ссылка на GitHub-проект
Комментарии (14)

alan008
05.10.2026 18:02Я пишу на Delphi+VCL. В статье описан крутой подход. Отвязка виджетов от ОС - это как раз самая суть RAD-подхода (жаль что сами Borland/Codegear/Embarcadero до этого не дошли). А ведь пытались еще во времена Kylix.

denis_iii
05.10.2026 18:02На Linux до сих пор все непросто с GUI, в Win32 API все более стабильно, приложение от Windows XP можно запустить на 10/11-й без перекомпиляции.
Одно из возможных практичных решений, просто запускать C++Builder в Wine64 слое. И писать быстро.

rPman
05.10.2026 18:02осталось дело за малым, реализовать gui для редактирования форм в opensource ;)
Скрытый текст
и дождаться, когда RAD выкупят проект и уничтожат, как это сделали майкрософт с monodevelop для .net... надеюсь так не будет

1QDenisQ Автор
05.10.2026 18:02Исходный код под MIT и иначе не будет. А что по поводу GUI редактирования форм. Более чем реализуемо

Error1024
05.10.2026 18:02Есть Lazarus и Project Fresnel. Они ломают монополию, но идут со стороны Pascal и отказываются от VCL-парадигмы. Мне хотелось другого. Сохранить саму VCL-парадигму, но реализовать её на стандартном C++. Но была и вторая проблема, серьёзнее лицензий.
Щито за ахинея, лол.
В Лазарусе - буквально VCL парадигма, в виде клона VCL, названного LCL.
Fresnel - не дошел даже до беты, никто его не использует, только лишь апдейты проскакивают в рассылках. Но откуда ИИ это знать то.
Прежде чем говорить про реализацию, напомню, из чего вообще состоит VCL
Иерархия. Всё начинается с TObject, это корень. У него есть ClassName() и InheritsFrom() — ручной RTTI, без typeid и dynamic_cast как основы. Дальше идёт TComponent: всё, что может чем-то владеть. Потом TControl: всё, что можно показать на экране. Потом TOSControl, TCustomForm, TForm, и уже от них конкретные контролы: TButton, TLabel, TEdit, TComboBox, TCheckBox, TPanel.
ИИ перемешало все. TObject и TComponent - это не часть VCL, а часть языка Object Pascal/RTL.
OnClick это просто функция.
Это указатель на метод. Self + Addr. Не функция.
VCL под другие системы уже не переделать
Поставьте Lazarus и пользуйтесь кроссплатформенным LCL.
На момент написания этой статьи RTL-слой реализован полностью: TObject, TComponent, Exception, иерархия исключений, владение. Всё, что есть в настоящем RTL
Вы забыли - самое важное - RTTI, который и обеспечивает магию "бросания" кнопок на форму.
В целом - поздравляю - вы переизобрели wxWidgets, только в виде недоделанной и забагованной ИИ реализации.
---
Впрочем, к автору данного "творения" у меня нет вопросов, у меня вопрос к тем, кто плюсы "этому" наставил.
Один из самых ИИ-слопных текстов, в хабе C++, что я видел.
Я так понимаю, плюсы наставили, исключительно, из-за тряски от того, что в 2026 году Object Pascal все еще существует и имеет "фишки", которых все еще нет в C++.

Error1024
05.10.2026 18:02https://github.com/QbitQuantum/GUIFramework/commit/d1487d5dd3609ae46e957dcf4cebbea73eb6615c
«RAD на C++ возможен только в проприетарном инструменте.» Это утверждение было верно 30 лет. Мы его ломаем.
Никаких торговых марок Embarcadero. Имена классов (TObject, TComponent, TForm) — общеупотребительные в мире RAD-разработки. Мы не используем код Embarcadero. Мы воспроизводим идеи — а идеи не защищены.
Кто «мы» то? Вы тут один.
Интересно, почему шизо-архитекторы на Хабре - всегда от «мы» пытаются писать?

Einherjar
05.10.2026 18:02Embarcadero продаёт не технологию. Технология старая и давно не секрет. Они продают монополию. Потому что альтернативы нет.
Альтернатив как раз навалом, и даже бесплатно. Они продают легаси, кровавый энтерпрайз сидит на этом с проектами написанными при царе горохе и кодом настолько макаронным что даже ии не разберет, дешевле отстегнуть 4к за лицензию чем разгребать чтобы хотя бы понять как работает, не говоря про то чтобы мигрировать на что то худо бедно распространенное
dbpatch
Borland C++ как язык был изначально существенно расширен, из реально значимых: properties, closure aka member function that also holds an object pointer aka event handler, virtual constructors, и эти расширения пока так и не вошли в -fborland-extensions для clang. Да, есть MS specific реализация properties, но она сильно примитивна, плюс еще нужны __published и .dfm streams.
Так что увы, сделать что-то вроде LCL/FPC и Lazarus IDE с поддержкой Visual Form Inheritance не получится. А для остального есть wxWidgets, Qt, да и GTK+ и тот уже много десятков лет как обзавелся кроссплатформой.
1QDenisQ Автор
Мой подход позиционировался как часть фреймворка, не завязанного под билдер. К тому же при все желание компиляторы той же студии поддерживают плагины, при том что с постоянным API. Это очень тяжело но реально. К тому что RTTI аля рефлексия в будущих стандартах уже не за горами. В точности повторить невозможно. Но можно хотя бы приблизиться. Да и своего рода .dfm как парсинг структуры и создание в рантайме хоть и нетривиальная, но выполнимая задача
dbpatch
Да это понятно. В наше время через AI можно играть в любой постмодерн. И да, было бы интересно попросить у Claude расширение для clang, реализующее __properties...
Но все равно не понятно, чем не устроил wxWidgets - там же все озвученные идеи выше уже много лет как реализованы.
Это какой? VS, VS Code или RAD Studio?
DFM появился во времена, когда память измерялась мегабайтами, и тогда он был фантастически быстр и прям очень актуален. Но с современной парадигмы разработки (git, 2-way merge, 3-way merge и прочий sdlc) этот формат очень неудобен, даже в текстовом виде. Впрочем, этой же проблемой страдают практически все современные IDE с визуальным проектированием форм (1C, Oracle APEX и прочие LowCode), как правило предлагая как альтернативу костыли в виде собственных VCS.
В этом плане (IDE для UI) наиболее приблизился к Delphi скорее Qt c их Qt Designer, хотя с позиции DataAware и VisualFormInheritance это все еще - скорее детский садик, штаны на лямках.
В бытность Borland вложила многие сотни человеко-лет в свою IDE/VCL, а вот полноценно повторить это даже группой энтузиастов за много лет так и не удалось никому (даже ребятам из LCL/Lazarus/FPC)
1QDenisQ Автор
С ним я не знаком. Да и цель проекта показать как можно изменить конкретно данный фреймворк, а не просто сказать "вот есть wxWidgets" и закончить статью.
VS, VS Code или RAD Studio. Каждый поддерживает плагины, но не совместимые между собой. Проще использовать встроенный движок, для анализа проекта, но тогда мы просто переходим к концепции того Qt с его MOC-объектами и встроенного движка.
Использование .dfm или же его подмножества, еще раз повторю, сохранить привычность с С+ RAD Studio, а не изобретать велосипед
Ядро написано полностью. Все остальные классы это тривиальные классы у которых по 5-10 депрекейт методов, и обратная совместимость с кучей костылей. Они легко реализуемы, будь желание этим заниматься. Да и я сам понимаю что не прямой конкурент, и не собираюсь становиться. Это PET-проект и не более
Error1024
Какое, к черту «ядро»?
Все, что есть - это ИИ слоп файл WindowsProject1.cpp, с впечатанным в него WinApi, не расширяемая хардкод-обертка названная VCL, и хардкод пример использования, внутри этого файла "ядра".
Освойте Codex или Claude Code хотя бы, они умеют создавать отдельные файлы, далеко на копировании в чатик и обратно не уехать.
https://github.com/QbitQuantum/GUIFramework/blob/main/WindowsProject1.cpp
1QDenisQ Автор
Я планирую вести проект, так как очень прикольный. Но сейчас я больше упариваюсь (извините за выражение) именно в архитектуру. Чтобы сделать ядро стабильным. А прочее такие как dfm streams пока не критично. Идея сделать именно на шаблона проперти. Выглядеть будет ужасно. Но что дают, тем и пользуемся
Error1024
Открыл ваш гитхаб, посмотрел проекты, до ИИ эпохи, из 24 года.
Обнаружил кучу недоделанных мега C++ IDE состоящих из Form1 + Button1, и пустых обработчиков:
https://github.com/QbitQuantum/IDE_SimpleCppParser/blob/main/ide_bilix.cpp
Просто бессмысленный говнокод:
https://github.com/QbitQuantum/Basics/blob/main/%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F%20%5B%D0%AD%D0%B2%D0%BE%D0%BB%D1%8E%D1%86%D0%B8%D0%B8%5D%20%D0%B1%D0%BE%D1%82%D0%B0/ProjectModify/ProjectModify.cpp
И даже невероятное Hello World на нативном C++(ЩИТО ЭТО, ЛОЛ):
https://github.com/QbitQuantum/Basics/blob/main/HelloWorld%20%D0%BD%D0%B0%20%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%BC%20%D0%A1%2B%2B.cpp
С 25 года же, на вашем гитхабе попер "сеньерский"(ИИ) код.
Какая еще "АРХИТЕКТРУА", господи, попишите простые программы на готовых технологиях для начала, а потом уже "АРХИТЕКТУРА".
Если, таки хотите научиться писать код, сами, без ИИ - то поставьте Delphi, Lazarus, или Qt, и поделайте простые, но законченные программки и утилиты, не мега проекты. Потом, с опытом, вы начнете делать более сложные вещи, и поймете зачем нужен этот ООП вообще.
От того же, что ИИ пишет за вас "сеньерские" проекты и статьи, с мега парадигмами - сеньером вы не становитесь, это приходит только с опытом своих проектов и ошибок.
Ну или забейте, и через ИИ делайте проекты, не заглядывая в код, если есть крутые идеи, ИИ уже достаточно хорош, чтобы без "сеньерских" тычков делать сложные штуки, и прогресс двигается дальше. Но прекратите хаб про C++ превращать в ИИ слоп, плиз.