Usuwanie dynamicznie utworzonych obiektów

Autor podstrony: Krzysztof Zajączkowski

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

Wstęp

Skoro zrealizowane zostało dodawanie obiektów oraz ich zaznaczanie najwyższa pora nadeszła aby zacząć coś robić z tymi zaznaczonymi obiektami. Pierwszą taką operacją będzie usuwanie obiektów. Realizację tego zadania przekażemy w "ręce" klasy select_obj, gdyż ta przechowuje wewnątrz pewne informacje, które powinny zostać odpowiednio ustawione w przypadku usuwania obiektów. Oczywiście usuwanie obiektów powinno zostać podpięte pod przycisk delete klawiatury, a co za tym idzie do projektu konieczne będzie dodanie akceleratorów.

Dodawanie akceleratorów do zasobów programu

Na razie dodany zostanie tylko jeden akcelerator tak jak na poniższym rysunku zostało to pokazane.

Widok dodanego akceleratora do projektu programu Rysowanie
Rys. 1
Projekt programu rysowanie - widok dodanego akceleratora związanego z usuwaniem obiektów

Akcelerator należy oczywiście podpiąć do projektu w sposób już wcześniej omawiany na stronie Programowanie → C++ WinApi → Dodawanie menu, akceleratora, ikony i kursora do programu, toteż ja skupię się jedynie na obsłudze komunikatu przychodzącego od akceleratora do okna rysowanie:

case WM_COMMAND: { if((HWND)lParam == toolbar){ UINT n = LOWORD(wParam); if(n != ID_SELECT && st == state::sel){ SelObjAct.Clear(); InvalidateRect(hWndDraw, NULL, true); } switch(n){ case ID_LINE: // komunikat przychodzący od przycisku toolbar-a o identyfikatorze ID_LINE { st = dr_line; SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie linii"); // ustawienie tekstu w ostatnim polu statusbar-u } break; case ID_CIRCLE: // to samo co poprzednio, tylko dla ID_CIRCLE { st = dr_circle; SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie okręgu"); // ustawienie tekstu w ostatnim polu statusbar-u } break; case ID_RECTANGLE: // to samo co poprzednio, tylko dla ID_RECTANGLE { st = dr_rect; SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie prostokąta"); // ustawienie tekstu w ostatnim polu statusbar-u } break; case ID_SELECT: // to samo co poprzednio, tylko dla ID_SELECT { st = sel; SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie edycja"); // ustawienie tekstu w ostatnim polu statusbar-u } break; } }else if(HIWORD(wParam) == 1){ // obsługa akceleratora switch(LOWORD(wParam)){ // id akceleratora case ID_ACCELERATOR_DELETE: // usuwanie obiektów { switch(st){ case state::sel: { SelObjAct.Delete(hWndDraw, tObj); // wywołanie metody klasy SelObjAct, która usunie obiekty zaznaczone } break; } } break; } } } break;

Powyżej został wstawiony cały kod związany z komunikatem WM_COMMAND obsługiwanym wewnątrz funkcji procedury okna WndDrawingProc.

Metoda Delete klasy select_obj

Pozostało już tylko dodanie do klasy select_obj nowej metody o nazwie Delete, która będzie wyglądała następująco:

void Delete(HWND hWndDraw, std::vector<i_dr_obj*> &tObj){ if(!tSelObj.empty()){ // jak coś jest zaznaczone to if(objundercursor && objundercursor->Selected()){ // jeżeli obiekt pod kursorem jest już zaznaczony objundercursor = NULL; // to trzeba ustawić NULL bo ten obiekt zostanie usunięty } for(int i = 0; i < tObj.size(); i++){ // iterowanie po tablicy interfejsów graficznych obiektów if(tObj[i]->Selected()){ // jak zaznaczony delete tObj[i]; // zwalniam dynamicznie przypisaną pamięć tObj.erase(tObj.begin() + i); // usuwam obiekt i --; // muszę przesunąć ideks w dół bo jeden już usunąłem } } SetRectEmpty(&selrect); // prostokąt zaznaczenia powinien być pusty tSelObj.clear(); // czyszczę tablicę zaznaczonych obiektów InvalidateRect(hWndDraw, NULL, false); // i odświerzam jagby nigdy nic się nie stało okno } }

Po serii tych jakże wyczerpujących operacji można się cieszyć programem, który nie tylko dodaje, rysuje i zaznacza obiekty, ale również umożliwia ich usuwanie!

Propozycje książek

Załączniki:

Wersja programu Rysowanie z strony tutaj