Implementacja rysowania obiektów w oknie programu

Stronę tą wyświetlono już: 292 razy

Wstęp

Do tej pory w programie Rysowanie omawiane były jedynie elementy związane z implementacją graficznego interfejsu użytkownika. Interfejs ten jest oczywiście mocno ograniczony do minimum, ponieważ jedynym moim celem jest pokazanie w przybliżeniu jak można stworzyć podstawy do utworzenia bardziej złożonych programów. Celem naszego programu jest oczywiście rysowanie różnych obiektów, a tymi obiektami są:

  • line - czyli linia;
  • circle - czyli okrąg;
  • rectangle - czyli prostokąt

W powyższym nazewnictwie użyłem nazw angielskich, ponieważ również i w kodzie programu będę takich nazw używał tworząc deklarację klas opisujących te obiekty. I teraz powstaje pewien problem, ponieważ obiekty powinny być rysowane kolejno jeden nad drugim a ja muszę je jakoś przechowywać w jednym kontenerze. Jak to zrobić? Odpowiedź jest prosta, trzeba utworzyć interfejs, czyli klasę abstrakcyjną, po której moje klasy opisujące poszczególne obiekty będą dziedziczyły. Spójrzmy więc łaskawym okiem na poniższą ilustrację.

Diagram pokazujący powiązania klas opisujących obiekty z interfejsem
Rys. 1
Diagram pokazujący powiązania klas opisujących obiekty z interfejsem

Jak widać na powyższym rysunku, klasa i_dr_obj {i - interface (interfejs), dr - draving (rysowanego), obj - object (obiektu)} jest dziedziczona przez wszystkie klasy opisujące obiekty rysowane w programie, czyli: line; circle oraz rectangle. Teraz mogę sobie spokojnie przechowywać moje obiekty w kontenerze wskaźników do interfejsów std::vector<i_dr_obj*>. Oczywiście klasa i_dr_obj musi zawierać funkcje abstrakcyjne i wymuszać obsługę pewnych mechanizmów, które są związane z obsługą wyświetlania i dodawania nowego obiektu do programu.

Dodatkowo wewnątrz programu utworzone zostaną dwie grupy klas:

  • opisujące pióro rysowania przypisane do danego obiektu;
  • opisujące wypełnienie rysowanego obiektu;

Uwzględniając wyżej wymienione klasy schemat zależności zmieni się do postaci pokazanej na poniższym rysunku.

Schemat klas w programie Rysowanie
Rys. 2
Schemat klas w programie Rysowanie.

Jak widać na powyższym schemacie klasy pen i hpen mają luźnie powiązanie z klasą abstrakcyjną i_dr_obj oraz z klasami line, circle oraz rectangle. Luźne powiązanie polega na tym, że klasy pen oraz hpen zostały wykorzystane w następujących metodach oraz konstruktorze wcześniej wymienionych klas:

  • dla klasy abstrakcyjnej i_dr_obj:
    • i_dr_obj(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush, pen &p, brush &b) - konstruktor;
    • virtual std::wstring toString(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) = 0; - metoda związana z konwersją do tekstu;
    • virtual void Draw(HDC &hdc, std::vector<hpen> &tPen, std::vector<hbrush> &tbrush) = 0; - metoda związana z rysowaniem.
  • dla klas dziedziczących line, circle rectangle:
    • konstruktory poszczególnych klas;
    • virtual std::wstring toString(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) - metoda związana z konwersją do tekstu;
    • virtual void Draw(HDC &hdc, std::vector<hpen> &tPen, std::vector<hbrush> &tbrush) - metoda związana z rysowaniem.

Kod klas utworzonych na potrzeby programu

Zanim opiszę kod klas, najpierw trzeba do projektu dodać plik drawing_class_def.h w taki sam sposób jak plik winmain.cpp. Oto kod programu, który powinien znaleźć się w tym pliku:

Listing 1
  1. #ifndef DRAWING_CLASS_DEF
  2. #define DRAWING_CLASS_DEF
  3. #include <windows.h>
  4. #include <string>
  5. // ######################### KLASA pen ############################
  6. // Ta klasa będzie opisywała wędzel obramowania obiektów:
  7. // r - składowa czerwona;
  8. // g - składowa zielona;
  9. // b - składowa niebieska;
  10. // width - szerokość pióra;
  11. // ps_style - styl linii pióra
  12. class pen{
  13. protected:
  14. BYTE r; // składowa czerwona koloru pióra
  15. BYTE g; // składowa zielona koloru pióra
  16. BYTE b; // składowa niebieska koloru pióra
  17. int width; // szerokość pióra
  18. public:
  19. enum ps{ // dostępne ustawienia stylu pióra
  20. solid = PS_SOLID, // linia ciągła
  21. dash = PS_DASH, // przerwywana
  22. dot = PS_DOT, // kropkowana
  23. dashdot = PS_DASHDOT, // kreska kropka
  24. dashdotdot = PS_DASHDOTDOT, // kreska kropka kropka
  25. null = PS_NULL, // brak
  26. insideframe = PS_INSIDEFRAME // a to nie wiem
  27. };
  28. protected:
  29. enum ps ps_style; // styl pióra
  30. public:
  31. pen():r(255), g(0), b(0), width(1), ps_style(solid){}; // domyślny konstruktor
  32. 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
  33. pen(const pen &p):r(p.r), g(p.g), b(p.b), width(p.width), ps_style(p.ps_style){}; // konstruktor kopiujący
  34. virtual void SetColor(BYTE r, BYTE g, BYTE b){
  35. this->r = r;
  36. this->b = b;
  37. this->g = g;
  38. }
  39. virtual void SetStyle(enum ps style){
  40. ps_style = style;
  41. }
  42. virtual void SetPen(BYTE r, BYTE g, BYTE b, enum ps style){
  43. this->r = r;
  44. this->g = g;
  45. this->b = b;
  46. ps_style = style;
  47. }
  48. bool operator ==(const pen &p) const { // operator porównania
  49. if(!memcmp(this, &p, sizeof(pen))){
  50. return true;
  51. }
  52. return false;
  53. }
  54. std::wstring toString() const { // zamiana na ciąg znaków
  55. std::wstring str;
  56. wchar_t buffor[100];
  57. wsprintf(buffor, L"r %i; g %i; b %i; width %i; style %i", r, g, b, width, (int)ps_style);
  58. str = buffor;
  59. return str;
  60. }
  61. };
  62. // ########################## KLASA hpen ###########################
  63. class hpen : public pen{
  64. HPEN hPen; // uchwyt pędzla
  65. public:
  66. 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))){};
  67. hpen(const pen p) : pen(p), hPen(CreatePen((int)ps_style, width, RGB(r, g, b))){};
  68. hpen(const hpen &hp) : pen(hp), hPen(CreatePen((int)ps_style, width, RGB(r, g, b))){};
  69. hpen() : pen(), hPen(CreatePen((int)ps_style, width, RGB(r, g, b))){};
  70. void SelectPen(HDC &hdc){
  71. SelectObject(hdc, hPen);
  72. }
  73. virtual void SetColor(BYTE r, BYTE g, BYTE b){
  74. this->r = r;
  75. this->b = b;
  76. this->g = g;
  77. DeleteObject(hPen);
  78. hPen = CreatePen((int)ps_style, width, RGB( r, g, b));
  79. }
  80. virtual void SetStyle(enum ps style){
  81. ps_style = style;
  82. DeleteObject(hPen);
  83. hPen = CreatePen((int)ps_style, width, RGB( r, g, b));
  84. }
  85. virtual void SetPen(BYTE r, BYTE g, BYTE b, enum ps style){
  86. this->r = r;
  87. this->g = g;
  88. this->b = b;
  89. ps_style = style;
  90. DeleteObject(hPen);
  91. hPen = CreatePen((int)ps_style, width, RGB( r, g, b));
  92. }
  93. ~hpen(){
  94. DeleteObject(hPen);
  95. }
  96. };
  97. // ############################# KLASA brush #####################################
  98. class brush{
  99. protected:
  100. BYTE r;
  101. BYTE g;
  102. BYTE b;
  103. public:
  104. brush(BYTE r, BYTE g, BYTE b):r(r), g(g), b(b){};
  105. brush(const brush &br) : r(br.r), g(br.g), b(br.b){};
  106. virtual void SetColor(BYTE r, BYTE g, BYTE b){
  107. this->r = r;
  108. this->g = g;
  109. this->b = b;
  110. }
  111. std::wstring toString() const {
  112. std::wstring str;
  113. wchar_t buffor[100];
  114. wsprintf(buffor, L"brush: r %i, g %i, b %i", r, g, b);
  115. str = buffor;
  116. return str;
  117. }
  118. bool operator ==(const brush &br) const {
  119. if(memcmp(this, &br, sizeof(brush))){
  120. return false;
  121. }
  122. return true;
  123. }
  124. };
  125. // ############################# KLASA hbrush ##################################
  126. class hbrush : public brush{
  127. protected:
  128. HBRUSH hBrush; // uchwyt wypełnienia
  129. public:
  130. hbrush(const brush &br) : brush(br), hBrush(CreateSolidBrush(RGB(r, g, b))){};
  131. hbrush(const hbrush &hbr) : brush(hbr), hBrush(CreateSolidBrush(RGB(r, g, b))){};
  132. virtual void SetColor(BYTE r, BYTE g, BYTE b){
  133. this->r = r;
  134. this->g = g;
  135. this->b = b;
  136. DeleteObject(hBrush);
  137. hBrush = CreateSolidBrush(RGB(r, g, b));
  138. }
  139. void SelectBrush(HDC &hdc){
  140. SelectObject(hdc, hBrush);
  141. }
  142. ~hbrush(){
  143. DeleteObject(hBrush);
  144. }
  145. };
  146. // ###################### TYP ENUMEROWANY DLA OPISU TRYBU PRACY PROGRAMU #####################
  147. enum state{
  148. dr_line, // rysowanie linii
  149. dr_circle, // rysowanie okręgu
  150. dr_rect, // rysowanie prostokąta
  151. sel // tryb edycji
  152. };
  153. // ############### DAFINICJA INTERFEJSU KLAS DZIEDZICZĄCYCH ###############
  154. class i_dr_obj{ // i - interface; dr - draving; obj - object (interfejs rysowanego obiektu)
  155. protected:
  156. bool selected;
  157. int pen_index; // index pędzla rysowania
  158. int brush_index; // index wypełnienia rysowania
  159. public:
  160. i_dr_obj(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush, pen &p, brush &b):selected(false), pen_index(-1), brush_index(-1){
  161. for(int i = 0; i < tPen.size(); i++){ // dla każdego elementu kontenera tPen
  162. if((pen)tPen[i] == p){ // sprawdzam, czy nie ma już utworzonego pióra o takich samych parametrach
  163. pen_index = i; // jeżeli jest takie pióro to zapamiętuję jego index
  164. break; // i kończę zabawę z iterowaniem
  165. }
  166. }
  167. if(pen_index == -1){ // jak pen_index jest równe -1 to znaczy, że nie ma w tPen takiego pióra więc
  168. pen_index = tPen.size(); // przypisuję index ostatniego elementu
  169. hpen hp(p); // tworzę nową definicję pióra
  170. tPen.push_back(hp); // dodaję definicję pióra
  171. }
  172. for(int i = 0; i < tBrush.size(); i++){ // dla każdego elementu kontenera tBrush
  173. if((brush)tBrush[i] == b){ // sprawdzam, czy nie ma już utworzonego pędzla o takich samych parametrach
  174. brush_index = i; // jeżeli taki pędzel już istnieje to zapamiętuję jego index
  175. break; // i kończę zabawę z iterowaniem
  176. }
  177. }
  178. if(brush_index == -1){ // jak brush_index jest równy -1 to znaczy, że w tBrush nie ma takiego pędzla
  179. brush_index = tBrush.size(); // więc przypisuję index ostatniego elementu kontenera (który zaraz dodam)
  180. hbrush hbr(b); // tworzę ten element
  181. tBrush.push_back(hbr); // i dodaję go do kontenera
  182. }
  183. };
  184. virtual std::wstring toString(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const = 0; // każda definicja klasy musi obsługiwać tę metodę
  185. virtual void Draw(HDC &hdc, std::vector<hpen> &tPen, std::vector<hbrush> &tbrush) const = 0; // każda definicja klasy musi obsługiwać tę metodę
  186. virtual void WmLButtonDown(POINT &mp) = 0;
  187. virtual void WmLButtonUp(POINT &mp) = 0;
  188. bool Selected() const {return selected;}; // określa, czy obiekt został zaznaczony
  189. virtual bool Select(POINT &ps) = 0; // każda definicja klasy musi obługiwać tę metodą
  190. virtual ~i_dr_obj(){};
  191. };
  192. // ######################### DEFINICJA KLASY LINE (LINIA) ########################
  193. class line : public i_dr_obj{
  194. POINT begin;
  195. POINT end;
  196. public:
  197. 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;};
  198. virtual std::wstring toString(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
  199. std::wstring str;
  200. wchar_t buffor[100];
  201. wsprintf(buffor, L"Line %i %i; %i %i", begin.x, begin.y, end.x, end.y);
  202. str = buffor;
  203. str += tPen[this->pen_index].toString();
  204. str += tBrush[this->brush_index].toString();
  205. return str;
  206. }
  207. virtual void Draw(HDC &hdc, std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
  208. tPen[pen_index].SelectPen(hdc);
  209. tBrush[brush_index].SelectBrush(hdc);
  210. MoveToEx(hdc, begin.x, begin.y, NULL);
  211. LineTo(hdc, end.x, end.y);
  212. }
  213. virtual void WmLButtonDown(POINT &mp){
  214. begin = mp;
  215. end = mp;
  216. }
  217. virtual void WmLButtonUp(POINT &mp){
  218. end = mp;
  219. }
  220. virtual bool Select(POINT &ps){
  221. return false;
  222. }
  223. };
  224. // ######################### DEFINICJA KLASY CIRCLE (OKRĄG) ########################
  225. class circle : public i_dr_obj{
  226. POINT begin;
  227. POINT end;
  228. public:
  229. 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;};
  230. virtual std::wstring toString(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
  231. std::wstring str;
  232. wchar_t buffor[100];
  233. wsprintf(buffor, L"Circle %i %i; %i %i", begin.x, begin.y, end.x, end.y);
  234. str = buffor;
  235. str += tPen[this->pen_index].toString();
  236. str += tBrush[this->brush_index].toString();
  237. str += tBrush[this->brush_index].toString();
  238. return str;
  239. }
  240. virtual void Draw(HDC &hdc, std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
  241. tPen[pen_index].SelectPen(hdc);
  242. tBrush[brush_index].SelectBrush(hdc);
  243. Ellipse(hdc, begin.x, begin.y, end.x, end.y);
  244. }
  245. virtual void WmLButtonDown(POINT &mp){
  246. begin = mp;
  247. end = mp;
  248. }
  249. virtual void WmLButtonUp(POINT &mp){
  250. end = mp;
  251. if(abs(begin.x - end.x) < abs(begin.y - end.y)){
  252. end.y = begin.y + abs(begin.x - end.x) * ( begin.y < end.y ? 1 : -1);
  253. }else{
  254. end.x = begin.x + abs(begin.y - end.y) * ( begin.x < end.x ? 1 : -1);
  255. }
  256. }
  257. virtual bool Select(POINT &ps){
  258. return false;
  259. }
  260. };
  261. // ######################### DEFINICJA KLASY RECTANGLE (PROSTOKĄT) ########################
  262. class rectangle : public i_dr_obj{
  263. POINT begin;
  264. POINT end;
  265. public:
  266. 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;};
  267. virtual std::wstring toString(std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
  268. std::wstring str;
  269. wchar_t buffor[100];
  270. wsprintf(buffor, L"Rectangle %i %i; %i %i", begin.x, begin.y, end.x, end.y);
  271. str = buffor;
  272. str += tPen[this->pen_index].toString();
  273. str += tBrush[this->brush_index].toString();
  274. return str;
  275. }
  276. virtual void Draw(HDC &hdc, std::vector<hpen> &tPen, std::vector<hbrush> &tBrush) const {
  277. tPen[pen_index].SelectPen(hdc);
  278. tBrush[brush_index].SelectBrush(hdc);
  279. Rectangle(hdc, begin.x, begin.y, end.x, end.y);
  280. }
  281. virtual void WmLButtonDown(POINT &mp){
  282. begin = mp;
  283. end = mp;
  284. }
  285. virtual void WmLButtonUp(POINT &mp){
  286. end = mp;
  287. }
  288. virtual bool Select(POINT &ps){
  289. return false;
  290. }
  291. };
  292. #endif

Kod główny programu

W pliku winmain.cpp trzeba załączyć wcześniej utworzony plik drawing_class_def.h dopisując następującą linijkę kodu:

Listing 2
  1. #include "drawing_class_def.h"

na samym początku kodu. Teraz cała funkcja procedury okna potomnego rysowania WndDrawingProc będzie wyglądała następująco:

Listing 3
  1. // ################################### Procedura okna dokumentu #####################################
  2. LRESULT CALLBACK WndDrawingProc(HWND hWndDraw, UINT msg, WPARAM wParam, LPARAM lParam){
  3. static POINT mousepos; // współrzędne kursora w oknie
  4. static i_dr_obj* obj; // wskaźnik na interfejs dodawanego obiektu
  5. static std::vector<i_dr_obj*> tObj; // tablica interfejsów obiektów rysowanych
  6. static enum state st; // tryb rysowania lub edycji
  7. static std::vector<hpen> tPen; // tablica wykorzystywanych pędzli
  8. static std::vector<hbrush> tBrush; // tablica wykorzystywanych wypełnień
  9. switch(msg){
  10. case WM_CREATE:
  11. {
  12. obj = NULL;
  13. }
  14. break;
  15. case WM_PAINT:
  16. {
  17. PAINTSTRUCT ps;
  18. HDC hdc = BeginPaint(hWndDraw, &ps);
  19. SetBkMode(hdc, TRANSPARENT);
  20. for(std::vector<i_dr_obj*>::iterator i = tObj.begin(); i < tObj.end(); i++){
  21. (*i)->Draw(hdc, tPen, tBrush); // rysowanie dodanych obiektów
  22. }
  23. if(obj){
  24. obj->Draw(hdc, tPen, tBrush); // rysowanie dodawanego obiektu
  25. }
  26. EndPaint(hWndDraw, &ps);
  27. }
  28. break;
  29. case WM_LBUTTONDOWN:
  30. {
  31. SetCapture(hWndDraw);
  32. switch(st){
  33. case dr_line: // tworzę obiekt typu line
  34. {
  35. obj = new line(tPen, tBrush, pen(255,0,0,1,pen::ps::solid), brush(0,0,150));
  36. obj->WmLButtonDown(mousepos);
  37. }
  38. break;
  39. case dr_circle: // tworzę obiekt typu circle
  40. {
  41. obj = new circle(tPen, tBrush, pen(0,255,0,1,pen::ps::solid), brush(0,150,0));
  42. obj->WmLButtonDown(mousepos);
  43. }
  44. break;
  45. case dr_rect: // tworzę obiekt typu rectangle
  46. {
  47. obj = new rectangle(tPen, tBrush, pen(0, 150, 255, 1, pen::ps::solid), brush(150,0,200));
  48. obj->WmLButtonDown(mousepos);
  49. }
  50. break;
  51. case sel: // trzyb zaznaczania (nie obsłużony jeszcze)
  52. {
  53. }
  54. break;
  55. }
  56. }
  57. break;
  58. case WM_LBUTTONUP:
  59. {
  60. switch(st){
  61. case dr_line: // dodawanie obiektu do kontenera
  62. {
  63. if(obj){
  64. obj->WmLButtonUp(mousepos);
  65. tObj.push_back(obj);
  66. }
  67. }
  68. break;
  69. case dr_circle: // dodawanie obiektu do kontenera
  70. {
  71. if(obj){
  72. obj->WmLButtonUp(mousepos);
  73. tObj.push_back(obj);
  74. }
  75. }
  76. break;
  77. case dr_rect: // dodawanie obiektu do kontenera
  78. {
  79. if(obj){
  80. obj->WmLButtonUp(mousepos);
  81. tObj.push_back(obj);
  82. }
  83. }
  84. break;
  85. case sel: // tryb edycji (nie obsłużony)
  86. {
  87. }
  88. break;
  89. }
  90. obj = NULL;
  91. ReleaseCapture();
  92. }
  93. break;
  94. case WM_MOUSEMOVE:
  95. {
  96. mousepos.x = LOWORD(lParam); // pobieranie współrzędnej x
  97. mousepos.y = HIWORD(lParam); // pobieranie współrzędnej y
  98. wchar_t buffor[100]; // bufor do konwersji na tekst
  99. wsprintf(buffor, L"X = %i",mousepos.x); // konwersja na tekst współrzędnej x
  100. SendMessage(statusbar, SB_SETTEXT, 0, (LPARAM)buffor); // ustawienie tekstu pierwszej pozycji paska kontrolki statusbar
  101. wsprintf(buffor, L"Y = %i",mousepos.y); // konwersja na tekst współrzędnej y
  102. SendMessage(statusbar, SB_SETTEXT, 1, (LPARAM)buffor); // ustawienie tekstu drugiej pozycji paska kontrolki statusbar
  103. if(wParam & MK_LBUTTON && obj){
  104. obj->WmLButtonUp(mousepos); // zmiana obiektu, podczas ruchu mychy
  105. InvalidateRect(hWndDraw, NULL, true); // odświerzanie okna w celu odrysowania nowych ustawień obiektu
  106. }
  107. }
  108. break;
  109. case WM_COMMAND:
  110. {
  111. if((HWND)lParam == toolbar){
  112. switch(LOWORD(wParam)){
  113. case ID_LINE: // komunikat przychodzący od przycisku toolbar-a o identyfikatorze ID_LINE
  114. {
  115. st = dr_line;
  116. SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie linii"); // ustawienie tekstu w ostatnim polu statusbar-u
  117. }
  118. break;
  119. case ID_CIRCLE: // to samo co poprzednio, tylko dla ID_CIRCLE
  120. {
  121. st = dr_circle;
  122. SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie okręgu"); // ustawienie tekstu w ostatnim polu statusbar-u
  123. }
  124. break;
  125. case ID_RECTANGLE: // to samo co poprzednio, tylko dla ID_RECTANGLE
  126. {
  127. st = dr_rect;
  128. SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie prostokąta"); // ustawienie tekstu w ostatnim polu statusbar-u
  129. }
  130. break;
  131. case ID_SELECT: // to samo co poprzednio, tylko dla ID_SELECT
  132. {
  133. st = sel;
  134. SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie edycja"); // ustawienie tekstu w ostatnim polu statusbar-u
  135. }
  136. break;
  137. }
  138. }
  139. }
  140. break;
  141. case WM_DESTROY: // tutaj sprzątanko się rozpoczyna
  142. {
  143. for(std::vector<i_dr_obj*>::iterator i = tObj.begin(); i < tObj.end(); i++){
  144. delete *i; // usuwanie obiektów
  145. }
  146. // czyszczenie kontenerów
  147. tObj.clear();
  148. tPen.clear();
  149. tBrush.clear();
  150. }
  151. break;
  152. }
  153. return DefWindowProc(hWndDraw, msg, wParam, lParam);
  154. }

W tej chwili program już rysuje poszczególne obiekty, ale jeszcze nie ma możliwości zaznaczania i zmiany ustawień obiektów. Poniżej zamieszczam screen programu.

Rysujący program Rysowanie
Rys. 3
Widok programu Rysowanie, który jak widać już rysuje.

Komentarze