На пути из Web к Native, часть 1

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

Оставь надежду, всяк сюда входящий. Или… нет?

Имея небольшой опыт в веб-программировании, мне казалось, что все не так плохо. И так по началу и было. За вопрос я взялся основательно: без задачи — нет учебы.

Я решил поставить перед собой большую цель: давным-давно, играя в ммо, я наткнулся на бот-программу, так называемый пакетный кликер. Она отправляла запросы на сервер и заставляла персонажа выполнять в автоматическом режиме невообразимые вещи, что меня очень впечатлило. По заявлениям автора, он ее сделал всего за 3 часа. И вот, уже не маленький я решил, что должен сделать так же.

Бот я выбрал по ряду причин:

  1. Работа с ассемблером.

  2. Какой-никакой GUI.

  3. Сборка и импорт библиотеки.

  4. Мечта детства.

Начал я с реверсинга, попал на форум Tuts4You и прошел челлендж от lena151 (и ее 2006й), состоящий из 40ка reverse_me

Пример из челленджа от lena151 (2006)

Пример из челленджа от lena151 (2006)

Закрепил навыки на коммерческом продукте, запакованном при помощи VMProtect 

Успешно пойденная регистрация в программе

Успешно пойденная регистрация в программе

Приступил к созданию библиотеки и импорту ее в игру, отправка пакета прошла успешно. 

отправка пакета через вешнюю библиотеку, призыв питомца :з

отправка пакета через вешнюю библиотеку, призыв питомца : з

Потеряв голову от «успеха», я решил, ну все. Я готов явить себя миру!

Кроссплатформенное GUIовое приложение

Первым препятствием стал выбранный мной язык — Си. Писать на нем что-то большое — очень больно. Но я сдался не сразу и даже сделал на WinAPI… скролл… 

C language WINAPI оконное приложение со скроллбаром :c

C language WINAPI оконное приложение со скроллбаром : c

Мы плавно подошли к самому главному… 

Сняли с языка : )

Сняли с языка :)

GUI обыкновенный или я твой Antialiasing шатал

Так как все это для обучения и только для обучения. Я решил, делать, так делать. Чтобы один и тот же код работал одинаково плохо хорошо на разных платформах.

Под рукой у мня был старенький мак с MacOS Catalina и ПиСюк с Windows 10. Исследовав рынок фреймворков я нашел 2 кандидата Qt и wxWidgets, но, поскольку Qt это про деньги и вообще попса. А все крутые ребята идут в андеграунд, выбор пал на wxWidgets.

В двух словах о wxWidgets — это нативный Фреймворк, который дает низкоуровневый доступ к системе. То есть я могу сам решить, какими средствами отрисовывать, как хранить и выводить результат.

Например, под виндой мы можем взять Direct2D или GDI, причем использовать все, что доступно одновременно, рисуя в Bitmap по очереди, используя разные средства, а после вывести ее.

При большой настойчивости можно даже подкрутить OpenGL. Но это уже другая история…. 

Думал, что можно все!

Думал, что можно все!

От удивления чуть не слетели штаны, придерживая их одной рукой, второй я тут же скачал бесплатное кросcплатформенное приложение Lunacy и начал наворачивать крутой интерфейс, скругленые углы, трансперенси, блюр… У нас будет их все!  

макет приложения в lunacy

макет приложения в lunacy

Но в итоге, все пошло не по плану.

При работе с unixом, мак или линукс, практически все работает из коробки, но Windows разочаровывает и заставляет разделить свой седалищный нерв на ДО и ПОСЛЕ.

Try HARD..

Try HARD…

Начиная с конфликта пользовательской отрисовки с системной, когда я рисую свое, а параллельно система… Ну, почему бы и нет. Пришлось отказаться от обработки OnPaint события для каждого элемента и делать все в основном, пробрасывая указатели на функцию отрисовки для каждого элемента и выводить в окно Bitmap по готовности, благодаря этому система не имеет доступа к нашему буферу. 

Пример системной отрисовки параллельно пользовательской..

Пример системной отрисовки параллельно пользовательской…

Но результатом всех этих мучений стало то, что всю грязную работу при работе с контролями (размеры, позиция, события) берет на себя система, а мы просто берем и рисуем свои крутости в окно.

И здесь я бы хотел продемонстрировать микро-гайд, как создать простое окно без рамки и накидать в него наши ништяки кастомные контролы, надеюсь, это даст Вам пищу для размышлений при создании своих проектов. Уточню, что я не заканчивал техно-ВУЗов, не являюсь техно-гуру и иже с ними. Я просто неравнодушный скиталец, потому, прошу простить за неточности и ошибки.

* Библиотека

Если Вы работаете под Windows, то Вашим выбором наверняка должен стать MinGW, потому, что они проделали большую работу, по приведению вин среды к GNU подобной.
Все отлично собирается при помощи gccшного компилятора и готовые библиотеки wxWidgets доступны в репозитории pacman.

win_x86

pacman -S mingw-w64-i686-wxwidgets3.1-msw

pacman -S mingw-w64-i686-wxwidgets3.1-msw-libs

win_x64

pacman -S mingw-w64-x86_64-wxwidgets3.1-msw

pacman -S mingw-w64-x86_64-wxwidgets3.1-msw-libs

Под MacOS мне пришлось собирать все самому, собирая из библиотек доступных в репозитории macports я не смог нормально залинковаться, но может это моя криворукость.

git clone https://github.com/wxWidgets/wxWidgets

cd wxWidgets

mkdir build-cocoa-debug

cd build-cocoa-debug

../configure --enable-debug

make

Собираем семплы и демки

cd samples; make;cd ..

cd demos;   make;cd ..

* Makefile

Далее создадим make file.

Единственным отличием Windows от MacOS является сборка ресурсов (картинок, иконок и др.)

Под Windows мы используем windres, чтобы захардкодить их в объектный файл, в данном случае я назвал его resource.o 

Пример Make файла под Windows

Пример Make файла под Windows

Под MacOS мы просто собираем bundle и кладем их в папочку, без разбора копируем все из папки ./src 

Пример Make файла под MacOS

Пример Make файла под MacOS

* Main.cpp

Создаем MAIN.CPP 

Пример файла main.cpp

Пример файла main.cpp

Пример файла surface.h

Пример файла surface.h

Получаем простое-пустое окно

Результат работы нашего кода - пустое окно без оконной рамки..

Результат работы нашего кода — пустое окно без оконной рамки…

Добавление ресурсов (вин/мак), происходит удивительно легко, как я уже упомянул, в Windows мы все собираем в объектный файл, а под MacOS просто собираем bundle, после можно простым вызовом макроса wxBitmap bmpName("bmp_name_without_png_ext", wxBITMAP_TYPE_PNG_RESOURCE); получуть переменную bmpName, в которой будет наша картинка.

Не забудьте создать под Windows файл resource.rc, прописать путь и типы переменных.

Не забудьте создать под Windows файл resource.rc, прописать путь и типы переменных.

Отрисовка с проброской указателя на функции. Чтобы избежать проблем с мерцанием, полосованием и прочей нечестью, мы не обрабатываем каждый элемент по отдельности. Получим событие OnPaint(wxPaintEvent& e) мы вызываем из нашего списка дочерние методы по указателю.

Bindимся к нашему методу в конструкторе Bind(wxEVT_PAINT, &Surface::OnPaint, this);

Пример обработки события Paint

Пример обработки события Paint

Мой чудо-каст методов для отрисовки отдельных элементов : )

Мой чудо-каст методов для отрисовки отдельных элементов :)

После всех мучений я остановился на этом

Накашлял : )

Накашлял :)

ПЫ. СЫ. Все действия производятся исключительно в образовательных целях и не являются призывом к действию.

© Habrahabr.ru