--- title: "Fox Toolkit - пишем маленькие кросс-платформенные приложения с более мощной библиотекой" categories: ["cpp", "archive"] date: 2015-08-21T00:00:00+03:00 draft: false featured_image: miniature.jpg --- После того, как мы [поиграли с FLTK](/fltk-apps), я нашёл ещё одну библиотеку виджетов - Fox Toolkit. Эта библиотека предоставляет более широкие возможности для разработки приложений с графическим интерфейсом. Библиотека также поставляется в виде исходного кода и скачивается с [официального сайта](http://www.fox-toolkit.org/download.html). В статье рассматривается версия 1.6.50. Компилируем под Windows. Все шаги до компиляции аналогичны шагам в [предыдущей статье](/fltk-apps). Открываем документик по пути `куда_распаковали\doc\win32.html` и листаем в самый низ. Ух ты, всё так просто. Только не компилируется нихрена. Оказывается, не один я столкнулся с этой проблемой, так что гугл помог. Вот [тема на форуме](https://forum.fox-toolkit.org/index.php?topic=34.0), которая мне помогла. Итак, что нужно сделать: 1. Запустить `./configure --without-x --without-xft` вместо `./configure` 2. Исправить заголовочный файл `куда_распаковали\include\xincs.h`: ```cpp #ifdef HAVE_GL_H // (240 строка) #ifndef SUN_OGL_NO_VERTEX_MACROS #define SUN_OGL_NO_VERTEX_MACROS #endif #ifndef HPOGL_SUPPRESS_FAST_API #define HPOGL_SUPPRESS_FAST_API #endif #include #ifndef WIN32 // ifndef заменить на ifdef #include // GL/glx.h заменить на GL/glext.h #endif // (250 строка) ``` Всё, теперь запускаем **make**, а потом **make install.** Затем можно забирать результат из `туда_куда_установлен_MinGw\msys\1.0\local`. На этом с компиляцией всё. # Пишем программу В качестве примера снова будем писать программу, которая будет считать количество нарисованных пикселей. Почему бы и нет? Используем разметку, которую мы нарисовали в предыдущей статье. fox_test.cpp: ```cpp #include "fox-1.6/fx.h" #include char buf[16]; struct point { int x, y; }; #define CANVAS_X 10 #define CANVAS_Y 10 #define CANVAS_WIDTH 180 #define CANVAS_HEIGHT 100 #define GRID_LEN 5 // размер зерна в холсте class PaintWindow : public FXMainWindow { FXDECLARE(PaintWindow) typedef std::map, point> PointMap; private: FXCanvas *canvas; // холст, на котором будем рисовать FXLabel *count_label; // надпись FXFont *big_font; // шрифт для надписи int isMouseDown; FXColor drawColor; // цвет пикселей на холсте FXColor bgColor; // цвет фона холста PointMap pixels; // карта с координатами пикселей void setpixel(FXEvent *event); protected: PaintWindow() { } public: enum { // ID обработчиков событий ID_CANVAS = FXMainWindow::ID_LAST, }; long onPaint(FXObject *, FXSelector, void *); long onMouseDown(FXObject *, FXSelector, void *); long onMouseUp(FXObject *, FXSelector, void *); long onMouseMove(FXObject *, FXSelector, void *); PaintWindow(FXApp *a); virtual void create(); virtual ~PaintWindow(); }; FXDEFMAP(PaintWindow) PaintWindowMap[] = { // определяем обработчики событий FXMAPFUNC(SEL_PAINT, PaintWindow::ID_CANVAS, PaintWindow::onPaint), FXMAPFUNC(SEL_LEFTBUTTONPRESS, PaintWindow::ID_CANVAS, PaintWindow::onMouseDown), FXMAPFUNC(SEL_RIGHTBUTTONPRESS, PaintWindow::ID_CANVAS, PaintWindow::onMouseDown), FXMAPFUNC(SEL_LEFTBUTTONRELEASE, PaintWindow::ID_CANVAS, PaintWindow::onMouseUp), FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, PaintWindow::ID_CANVAS, PaintWindow::onMouseUp), FXMAPFUNC(SEL_MOTION, PaintWindow::ID_CANVAS, PaintWindow::onMouseMove) }; FXIMPLEMENT(PaintWindow, FXMainWindow, PaintWindowMap, ARRAYNUMBER(PaintWindowMap)) PaintWindow::PaintWindow(FXApp *a) : FXMainWindow(a, a->getAppName(), NULL, NULL, DECOR_TITLE | DECOR_BORDER | DECOR_MINIMIZE | DECOR_CLOSE, //настраиваем вид окна 0, 0, 200, 300) { //выставляем размер окна canvas = new FXCanvas(this, this, ID_CANVAS, FRAME_SUNKEN | FRAME_THICK | LAYOUT_EXPLICIT, CANVAS_X, CANVAS_Y, CANVAS_WIDTH, CANVAS_HEIGHT); // задаём параметры холста, LAYOUT_EXPLICIT - абсолютное позиционирование count_label = new FXLabel(this, "...", NULL, LAYOUT_EXPLICIT, 34, 177, 133, 56); FXFontDesc fontdescription; getApp()->getNormalFont()->getFontDesc(fontdescription); // получаем стандартный шрифт big_font = new FXFont(getApp(), fontdescription.face, 37, FXFont::Normal); // создаём стандартный шрифт с нужным размером big_font->create(); count_label->setFont(big_font); drawColor = FXRGB(0, 0, 0); bgColor = FXRGB(255, 255, 255); isMouseDown = 0; } PaintWindow::~PaintWindow() { } void PaintWindow::create() { FXMainWindow::create(); show(PLACEMENT_SCREEN); //показываем окно в центре экрана } void PaintWindow::setpixel(FXEvent *event) { int x = event->win_x; int y = event->win_y; if (x < 0 || y < 0 || x + 2 >= CANVAS_WIDTH || y + 2 >= CANVAS_HEIGHT) return; // проверяем, не вышел ли курсор за пределы холста x = (event->win_x + 2) / GRID_LEN; y = (event->win_y + 2) / GRID_LEN; std::pair p = std::make_pair(x * GRID_LEN, y * GRID_LEN); // создаём хеш из двух координат FXDCWindow dc(canvas); bool add = event->click_button == 1; // если кнопка левая, то рисуем, правой - удаляем dc.setForeground(add ? drawColor : bgColor); if (add) { point pixel; pixel.x = x * GRID_LEN; pixel.y = y * GRID_LEN; pixels[p] = pixel; } else { pixels.erase(p); } dc.fillRectangle(x * GRID_LEN, y * GRID_LEN, GRID_LEN, GRID_LEN); // рисуем квадратики sprintf(buf, "%d px", pixels.size()); count_label->setText(buf); // обновляем надпись } long PaintWindow::onMouseUp(FXObject *, FXSelector, void *ptr) { // при отпускании мыши canvas->ungrab(); // отключаем перетаскивание в холсте if (isMouseDown) { FXDCWindow dc(canvas); dc.setForeground(drawColor); isMouseDown = 0; } return 1; } long PaintWindow::onMouseDown(FXObject *, FXSelector, void *ptr) { // при нажатии мыши canvas->grab(); // включаем перетаскивание в холсте setpixel((FXEvent *) ptr); isMouseDown = 1; return 1; } long PaintWindow::onMouseMove(FXObject *, FXSelector, void *ptr) { if (isMouseDown) { setpixel((FXEvent *) ptr); } return 1; } long PaintWindow::onPaint(FXObject *, FXSelector, void *ptr) { //если окно сворачивается или выходит за пределы видимости, то его нужно перерисовать FXEvent *ev = (FXEvent *) ptr; FXDCWindow dc(canvas, ev); dc.setForeground(bgColor); dc.fillRectangle(ev->rect.x, ev->rect.y, ev->rect.w, ev->rect.h); typedef PointMap::iterator it_type; for (it_type iterator = pixels.begin(); iterator != pixels.end(); iterator++) { // перебираем все пиксели наносим их на холст int x = iterator->second.x; int y = iterator->second.y; dc.setForeground(drawColor); dc.fillRectangle(x, y, GRID_LEN, GRID_LEN); } return 1; } int main(int argc, char **argv) { FXApp application("Pixels", "MultiMote"); application.init(argc, argv); new PaintWindow(&application); application.create(); return application.run(); } ``` ##### Компилируем исходник следующей командой: ```cmd g++ имя_исходника -o имя_результата -static -static-libgcc -static-libstdc++ -lFOX-1.6 -mwindows ``` **-static -static-libgcc -static-libstdc++** – связываем библиотеки MinGw с приложением, чтобы оно запускалось на других компьютерах **-lFOX-1.6** – подключаем библиотеку **-mwindows** – убираем окно команд и подключаем несколько системных приложений Также можно добавить флаги **-O2** и **-s** для уменьшения размера исполняемого файла. ![|580](exe.png) Теперь можно запускать: ![|206](app.png) Под linux приложение выглядит точно так же: ![|659](linux.png) Цель достигнута :) Итак, можно делать выводы. Библиотека предоставляет гораздо большие возможности, чем FLTK. А если честно, библиотека меня крайне выбесила.