Witam!
Tworzę aktualnie projekt, w którym chcę mieć zorganizowanie, zhierarchizowane GUI, podobnie jak wygląda to w C#. Więc zabrałem się do roboty i na początek stworzyłem klasę CControl (która w moim przypadku jest abstrakcyjna, ale o tym zaraz...), która zapewnia obsługę zdarzeń, pozycję itp. Potem stworzyłem klasę/kontrolkę CPanel, która jest niejako prototypem dla klas zawierających w sobie kolejne kontrolki. Potem stworzyłem sobie klasę CButton dziedziczącą po CControl (ponieważ button nie potrzebuje mieć kontrolek-dzieci) i działa ona tak jak powinna. Następnym krokiem było stworzenie jakiegoś pojemnika na kontrolki, stworzyłem więc klasę CContainer dziedziczącą po CPanel. I tu zaczynają się schody ponieważ CPanel zawiera vector CContainerów, aby móc po nich iterować i wywoływać ich zdarzenia. Więc sytuacja w kodzie wygląda tak:
ClassContainer.h
#ifndef DEF_CONTAINER
#define DEF_CONTAINER
#include "main.h"
#include "ClassTitleBox.h"
using std::vector;
class CContainer : public CPanel
{
public:
CContainer();
void initialize(int id, char* name, int x, int y , int sizeX, int sizeY, char* titleText, int hidable, int minizable);
void remove();
void Draw();
int onMouseDown(int x, int y);
int onMouseUp(int x, int y);
int onMouseMove(int x, int y);
int onKeyDown(int Key);
void Minimize(int mode);
void Hide(int mode);
void setFollowMouse(int mode);
void setRelativeMousePos(int x, int y);
void setTitleText(char* textString);
int getActualSizeX();
int getActualSizeY();
private:
};
#endif
ClassPanel.h
#ifndef PANEL_H
#define PANEL_H
#include "main.h"
#include "ClassControl.h"
#include "ClassButton.h"
#include "ClassContainer.h"
using std::vector;
class CPanel : public CControl
{
public:
CPanel();
vector<CButton> Buttons;
void AddButton(CButton Btn);
vector<CContainer> Containers;
void AddContainer(CContainer Cnt);
virtual void Draw();
virtual int onMouseDown(int x, int y);
virtual int onMouseUp(int x, int y);
virtual int onMouseMove(int x, int y);
virtual int onKeyDown(int Key);
protected:
void DrawChildren();
int ProcessMouseDown(int x, int y);
int ProcessMouseUp(int x, int y);
int ProcessMouseMove(int x, int y);
int ProcessKeyDown(int Key);
private:
};
#endif // PANEL_H
W main.h znajdują się jakieś funkcje globalne i includy windows.h, vector.h itd. Nazwy metod i parametry jakie przyjmują nie są ważne :)
Gdy próbuję to skompilować kompilator krzyczy, że expected class-name before '{' token przy okazji podświetlając pierwszy nawias { deklaracji klasy CContainer. No i jest to dość logiczne, ponieważ CContainer nie ma pojęcia o istnieniu klasy CPanel. Spróbowałem dodać w pliku ClassContainer.h #include "ClassPanel.h", lecz znowu ten sam błąd, ponieważ plik ClassPanel.h jest obdarzony jest zabezpieczeniem w postaci #ifndef. Dodałem więc deklarację klasy class CPanel; najpierw w pliku ClassPanel.h jeszcze przed includami, a potem w ClassContainer.h po includach - błąd w obu przypadkach był ten sam, mianowicie forward declaration of struct CPanel'// na deklaracji klasy i //invalid use of undefined type struct CPanel' przy //class CContainer : public CPanel. Trochę mnie dziwi słówko struct w tym błędzie... Moje pytanie brzmi w jaki sposób mam napisać includy/deklaracje czy coś innego, aby poprawnie mi się wszystko skompilowało i działało jak należy?
Na początku napisałem o klasie CControl. Deklaruje ona metodę Draw, która odświeża/rysuję kontrolkę i eventy myszki. Aby ułatwić sobie pracę chciałem zrzutować inne kontrolki do ich klasy bazowej (oczywiście wtedy CControl nie może i nie była abstrakcyjna) i wywołać tą metodę Draw, lecz niestety nie udało się tak zrobić i muszę dla każdego elementu osobno iterować, tworzyć nowy vector i metody dodające/usuwające kontrolki. Da się zrobić tak, żeby wywołać metody Draw klas pochodnych w jednej iteracji? Czyli zamiast:
vector<CButton>::reverse_iterator btnIT;
for(btnIT = Buttons.rbegin(); btnIT != Buttons.rend(); ++btnIT)
{
btnIT->onMouseDown(x, y);
}
vector<CContainer>::reverse_iterator cntIT;
for(cntIT = Containers.rbegin(); cntIT != Containers.rend(); ++cntIT)
{
cntIT->onMouseDown(x, y);
}
//i dla każdego kolejnego typu kontrolek to samo, a jest/będzie ich sporo...
zrobić tak:
vector<CControl>::reverse_iterator ctrlIT;
for(ctrIT = Controls.rbegin(); ctrlIT != Controls.rend(); ++ctrlIT)
{
ctrlIT->onMouseDown(x, y);
}
Jeszcze pytanie numer 3. Czy idę w dobrą stronę ku zorganizowaniu GUI? Czy są na to jakieś inne sposoby?
Przydługawy post mi wyszedł, ale liczę na waszą pomoc! :D
Przy okazji dodam, że jako IDE używam Code::Blocks.
Pozdrawiam, Wronq!