mmote.ru/content/posts/fox-toolkit-apps/index.md

277 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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.
<!--more-->
Все шаги до компиляции аналогичны шагам в [предыдущей статье](/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 <GL/gl.h>
#ifndef WIN32 // ifndef заменить на ifdef
#include <GL/glx.h> // 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 <map>
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<std::pair<int, int>, 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<int, int> 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.
А если честно, библиотека меня крайне выбесила.