#ifndef DRAWING_CLASS_DEF
#define DRAWING_CLASS_DEF
#include <windows.h>
#include <string>
// ######################### KLASA pen ############################
// Ta klasa będzie opisywała wędzel obramowania obiektów:
// r - składowa czerwona;
// g - składowa zielona;
// b - składowa niebieska;
// width - szerokość pióra;
// ps_style - styl linii pióra
class pen{
protected:
BYTE r; // składowa czerwona koloru pióra
BYTE g; // składowa zielona koloru pióra
BYTE b; // składowa niebieska koloru pióra
int width; // szerokość pióra
public:
enum ps{ // dostępne ustawienia stylu pióra
solid = PS_SOLID, // linia ciągła
dash = PS_DASH, // przerwywana
dot = PS_DOT, // kropkowana
dashdot = PS_DASHDOT, // kreska kropka
dashdotdot = PS_DASHDOTDOT, // kreska kropka kropka
null = PS_NULL, // brak
insideframe = PS_INSIDEFRAME // a to nie wiem
};
protected:
enum ps ps_style; // styl pióra
public:
pen():r(255), g(0), b(0), width(1), ps_style(solid){}; // domyślny konstruktor
pen(BYTE r, BYTE g, BYTE b, int width, enum ps ps_style) : r(r), g(g), b(b), width(width), ps_style(ps_style){}; // konstruktor ustawiający
pen(const pen &p):r(p.r), g(p.g), b(p.b), width(p.width), ps_style(p.ps_style){}; // konstruktor kopiujący
virtual void SetColor(BYTE r, BYTE g, BYTE b){
this->r = r;
this->b = b;
this->g = g;
}
virtual void SetStyle(enum ps style){
ps_style = style;
}
virtual void SetPen(BYTE r, BYTE g, BYTE b, enum ps style){
this->r = r;
this->g = g;
this->b = b;
ps_style = style;
}
bool operator ==(const pen &p) const { // operator porównania
if(!memcmp(this, &p, sizeof(pen))){
return true;
}
return false;
}
std::wstring toString() const { // zamiana na ciąg znaków
std::wstring str;
wchar_t buffor[100];
wsprintf(buffor, L"r %i; g %i; b %i; width %i; style %i", r, g, b, width, (int)ps_style);
str = buffor;
return str;
}
};
// ########################## KLASA hpen ###########################
class hpen : public pen{
HPEN hPen; // uchwyt pędzla
public:
hpen(BYTE r, BYTE g, BYTE b, int width, pen::ps style) : pen(r, g, b, width, style), hPen(CreatePen((int)style, width, RGB(r, g, b))){};
hpen(const pen p) : pen(p), hPen(CreatePen((int)ps_style, width, RGB(r, g, b))){};
hpen(const hpen &hp) : pen(hp), hPen(CreatePen((int)ps_style, width, RGB(r, g, b))){};
hpen() : pen(), hPen(CreatePen((int)ps_style, width, RGB(r, g, b))){};
void SelectPen(HDC &hdc){
SelectObject(hdc, hPen);
}
virtual void SetColor(BYTE r, BYTE g, BYTE b){
this->r = r;
this->b = b;
this->g = g;
DeleteObject(hPen);
hPen = CreatePen((int)ps_style, width, RGB( r, g, b));
}
virtual void SetStyle(enum ps style){
ps_style = style;
DeleteObject(hPen);
hPen = CreatePen((int)ps_style, width, RGB( r, g, b));
}
virtual void SetPen(BYTE r, BYTE g, BYTE b, enum ps style){
this->r = r;
this->g = g;
this->b = b;
ps_style = style;
DeleteObject(hPen);
hPen = CreatePen((int)ps_style, width, RGB( r, g, b));
}
~hpen(){
DeleteObject(hPen);
}
};
// ############################# KLASA brush #####################################
class brush{
protected:
BYTE r;
BYTE g;
BYTE b;
public:
brush(BYTE r, BYTE g, BYTE b):r(r), g(g), b(b){};
brush(const brush &br) : r(br.r), g(br.g), b(br.b){};
virtual void SetColor(BYTE r, BYTE g, BYTE b){
this->r = r;
this->g = g;
this->b = b;
}
std::wstring toString() const {
std::wstring str;
wchar_t buffor[100];
wsprintf(buffor, L"brush: r %i, g %i, b %i", r, g, b);
str = buffor;
return str;
}
bool operator ==(const brush &br) const {
if(memcmp(this, &br, sizeof(brush))){
return false;
}
return true;
}
};
// ############################# KLASA hbrush ##################################
class hbrush : public brush{
protected:
HBRUSH hBrush; // uchwyt wypełnienia
public:
hbrush(const brush &br) : brush(br), hBrush(CreateSolidBrush(RGB(r, g, b))){};
hbrush(const hbrush &hbr) : brush(hbr), hBrush(CreateSolidBrush(RGB(r, g, b))){};
virtual void SetColor(BYTE r, BYTE g, BYTE b){
this->r = r;
this->g = g;
this->b = b;
DeleteObject(hBrush);
hBrush = CreateSolidBrush(RGB(r, g, b));
}
void SelectBrush(HDC &hdc){
SelectObject(hdc, hBrush);
}
~hbrush(){
DeleteObject(hBrush);
}
};
// ###################### TYP ENUMEROWANY DLA OPISU TRYBU PRACY PROGRAMU #####################
enum state{
dr_line, // rysowanie linii
dr_circle, // rysowanie okręgu
dr_rect, // rysowanie prostokąta
sel // tryb edycji
};
// ############### DAFINICJA INTERFEJSU KLAS DZIEDZICZĄCYCH ###############
class i_dr_obj{ // i - interface; dr - draving; obj - object (interfejs rysowanego obiektu)
protected:
bool selected;
int pen_index; // index pędzla rysowania
int brush_index; // index wypełnienia rysowania
public:
i_dr_obj(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush, pen &p, brush &b):selected(false), pen_index(-1), brush_index(-1){
for(int i = 0; i < tPen.size(); i++){ // dla każdego elementu kontenera tPen
if((pen)tPen[i] == p){ // sprawdzam, czy nie ma już utworzonego pióra o takich samych parametrach
pen_index = i; // jeżeli jest takie pióro to zapamiętuję jego index
break; // i kończę zabawę z iterowaniem
}
}
if(pen_index == -1){ // jak pen_index jest równe -1 to znaczy, że nie ma w tPen takiego pióra więc
pen_index = tPen.size(); // przypisuję index ostatniego elementu
hpen hp(p); // tworzę nową definicję pióra
tPen.push_back(hp); // dodaję definicję pióra
}
for(int i = 0; i < tBrush.size(); i++){ // dla każdego elementu kontenera tBrush
if((brush)tBrush[i] == b){ // sprawdzam, czy nie ma już utworzonego pędzla o takich samych parametrach
brush_index = i; // jeżeli taki pędzel już istnieje to zapamiętuję jego index
break; // i kończę zabawę z iterowaniem
}
}
if(brush_index == -1){ // jak brush_index jest równy -1 to znaczy, że w tBrush nie ma takiego pędzla
brush_index = tBrush.size(); // więc przypisuję index ostatniego elementu kontenera (który zaraz dodam)
hbrush hbr(b); // tworzę ten element
tBrush.push_back(hbr); // i dodaję go do kontenera
}
};
virtual std::wstring toString(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const = 0; // każda definicja klasy musi obsługiwać tę metodę
virtual void Draw(HDC &hdc, std::vector<hpen> &tPen, std::vector<hbrush> &tbrush) const = 0; // każda definicja klasy musi obsługiwać tę metodę
virtual void WmLButtonDown(POINT &mp) = 0;
virtual void WmLButtonUp(POINT &mp) = 0;
bool Selected() const {return selected;}; // określa, czy obiekt został zaznaczony
virtual bool Select(POINT &ps) = 0; // każda definicja klasy musi obługiwać tę metodą
virtual ~i_dr_obj(){};
};
// ######################### DEFINICJA KLASY LINE (LINIA) ########################
class line : public i_dr_obj{
POINT begin;
POINT end;
public:
line(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush, pen &p, brush &b):i_dr_obj(tPen, tBrush, p, b){begin.x = begin.y = end.x = end.y = 0;};
virtual std::wstring toString(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
std::wstring str;
wchar_t buffor[100];
wsprintf(buffor, L"Line %i %i; %i %i", begin.x, begin.y, end.x, end.y);
str = buffor;
str += tPen[this->pen_index].toString();
str += tBrush[this->brush_index].toString();
return str;
}
virtual void Draw(HDC &hdc, std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
tPen[pen_index].SelectPen(hdc);
tBrush[brush_index].SelectBrush(hdc);
MoveToEx(hdc, begin.x, begin.y, NULL);
LineTo(hdc, end.x, end.y);
}
virtual void WmLButtonDown(POINT &mp){
begin = mp;
end = mp;
}
virtual void WmLButtonUp(POINT &mp){
end = mp;
}
virtual bool Select(POINT &ps){
return false;
}
};
// ######################### DEFINICJA KLASY CIRCLE (OKRĄG) ########################
class circle : public i_dr_obj{
POINT begin;
POINT end;
public:
circle(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush, pen &p, brush &b):i_dr_obj(tPen, tBrush, p, b){begin.x = begin.y = end.x = end.y = 0;};
virtual std::wstring toString(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
std::wstring str;
wchar_t buffor[100];
wsprintf(buffor, L"Circle %i %i; %i %i", begin.x, begin.y, end.x, end.y);
str = buffor;
str += tPen[this->pen_index].toString();
str += tBrush[this->brush_index].toString();
str += tBrush[this->brush_index].toString();
return str;
}
virtual void Draw(HDC &hdc, std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
tPen[pen_index].SelectPen(hdc);
tBrush[brush_index].SelectBrush(hdc);
Ellipse(hdc, begin.x, begin.y, end.x, end.y);
}
virtual void WmLButtonDown(POINT &mp){
begin = mp;
end = mp;
}
virtual void WmLButtonUp(POINT &mp){
end = mp;
if(abs(begin.x - end.x) < abs(begin.y - end.y)){
end.y = begin.y + abs(begin.x - end.x) * ( begin.y < end.y ? 1 : -1);
}else{
end.x = begin.x + abs(begin.y - end.y) * ( begin.x < end.x ? 1 : -1);
}
}
virtual bool Select(POINT &ps){
return false;
}
};
// ######################### DEFINICJA KLASY RECTANGLE (PROSTOKĄT) ########################
class rectangle : public i_dr_obj{
POINT begin;
POINT end;
public:
rectangle(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush, pen &p, brush &b):i_dr_obj(tPen, tBrush, p, b){begin.x = begin.y = end.x = end.y = 0;};
virtual std::wstring toString(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
std::wstring str;
wchar_t buffor[100];
wsprintf(buffor, L"Rectangle %i %i; %i %i", begin.x, begin.y, end.x, end.y);
str = buffor;
str += tPen[this->pen_index].toString();
str += tBrush[this->brush_index].toString();
return str;
}
virtual void Draw(HDC &hdc, std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
tPen[pen_index].SelectPen(hdc);
tBrush[brush_index].SelectBrush(hdc);
Rectangle(hdc, begin.x, begin.y, end.x, end.y);
}
virtual void WmLButtonDown(POINT &mp){
begin = mp;
end = mp;
}
virtual void WmLButtonUp(POINT &mp){
end = mp;
}
virtual bool Select(POINT &ps){
return false;
}
};
#endif