Window wrapper - Kritik ist gesucht



  • Schönen guten Tag,
    als Übung für mich bin ich nun schon seit einiger Zeit dabei folgendes Programm zu schreiben:
    Eine Headerdatei mit der man Windows-Fenster aus der Konsole heraus erstellen kann, Texte oder Figuren in den Fenstern erzeugen und diese formatieren kann (z.B. Farbe, Position...)...

    Da ich bei meinem ersten Versuch bereits gescheitert bin, wollte ich Versuch 2 nochmals von euch "kontrollieren lassen" (natürlich nur falls jemand viel Zeit hat;-).

    Ich habe den Code eingekürzt und nur die Funktionen gelassen die repräsentativ für den Aufbau meines Programms stehen. (ist wohl immer noch zu lang, vielleicht hat ja tatsächlich jemand Lust darüberzuschauen...)

    Die Konsolenausgaben könnt ihr ignorieren, die dienen nur mir zur Kontrolle (und ergeben nur für mich einen Sinn)

    #include <iostream>
    #include "wdlcWindows.h"
    using namespace std;
    
    int main(int argc, char *argv[]) {
    
    	Windowclan a("Clan1");	//Fensterverbund erstellen, beim Aufruf von a() 
    							//werden alle Fenster dieses Verbundes geöffnet
    
    	a.f("Window1");		//Fenster erstellen
    
    	a.t("Text1");		//Text im Fenster ausgeben
    
    	a.f("Window2");
    	a.ff(255,0,0);		//Fensterfarbe einstellen, gilt nur für
    						//das zuvor erstellte Fenster
    	a.t("Text2");
    	a.tf(0,255,0);		//Textfarbe einstellen, gilt nur für den zuvor erstellten Text
    	a.t("Text3");	
    
    	a.f("Window3");
    	a.t("Text4");
    
    	a.a();		//Ausgabe aller Fenster des Verbunds
    
    	Windowclan b("Clan2");
    	b.sff(100,100,100);		//Standart-Fensterfarbe, alle Fenster dieses
    							//Verbunds haben diese Farbe	
    	b.f("Window1");
    	b.stf(255,0,0);			//Standart-Textfarbe, alle Texte des zuvor
    							//erstellten Fensters haben diese Farbe	
    	b.t("Text1");
    	b.t("Text2");
    
    	b.t("Text3");
    	b.tf(0,0,0);		//Durch Einstellen einer anderen Textfarbe wird die 
    						//Standart-Textfarbe überschrieben	
    	b.f("Window2");
    
    	b.t("Text4");
    	b.t("Text5");
    
    	b.f("Window3");	
    	b.ff(0,0,0);		//Durch Einstellen einer anderen Fensterfarbe wird die 
    						//Standart-Fensterfarbe überschrieben		
    	b.t("Text6");
    
    	b.a();
    
    	return 0;
    }
    
    #ifndef wdlc_WINDOWS_H
    #define wdlc_WINDOWS_H
    
    #include<vector>
    #include<memory>
    #include<string>
    
    #include"wdlcWindow.h"
    
    class Window;
    
    class Windowclan{	
    private:
    	friend class Textboxes; 
    	friend class Figures;
    	friend class Window;
    
    	static int Calls;
    
    	static bool Is_registrate; 
    
    	std::vector<std::unique_ptr<Window>> windows;
    
    	std::string IP;
    	std::string Class_name;
    
    	int Window_position;
    
    	POINT SPosition;
    	RECT SSize;
    	HBRUSH SBackground;
    
    public:
    	Windowclan();
    	Windowclan(const std::string Name);
    
    	std::string get_ip();				//IP-Adresse des Clans bekommen
    	const char* getWindowclanName();	//Name des Fensterverbundes bekommen
    
    	void sff(const int rot, const int gruen, const int blau);	//Standard Fensterfarbe
    	std::string get_sff();
    
    	void f(const std::string Fenstername); 		//Fenster anlegen
    	std::string get_fip();							//IP-Adresse des Fensters bekommen
    
    	void ff(const int rot, const int gruen, const int blau); 						//Fensterfarbe für aktuelles Fenster
    	std::string get_ff();
    
    	void stf(const int rot, const int gruen, const int blau);
    	std::string get_stf();
    
    	void t(const std::string Text);		//Text anlegen
    	std::string get_tip();					//IP-Adresse des Textes bekommen
    
    	void tf(const int rot, const int gruen, const int blau); 						//Textfarbe für aktuellen Text
    	std::string get_tf();
    
    	void a();	//Ausgeben der Fenster
    };
    
    #endif
    
    #include <iostream>
    
    #include "wdlcWindows.h"
    #include "wdlcWindow.h"
    
    int Windowclan::Calls=1;
    
    Windowclan::Windowclan(): 
    		Window_position(-1), IP(std::to_string(Calls*100000000)), Class_name("Unbenannt"), 
    		SSize({0,0,400,400}), SPosition({400,20}), SBackground(CreateSolidBrush(RGB(255,255,255))){
    	Calls++;
    	std::cout<<"newWindowverbund - "<<Class_name<<" IP: "<<IP<<"\n";
    }
    
    Windowclan::Windowclan(const std::string Name): 
    		Window_position(-1), IP(std::to_string(Calls*100000000)), Class_name(Name), SSize({0,0,400,400}), 
    		SPosition({400,20}), SBackground(CreateSolidBrush(RGB(255,255,255))){
    	Calls++;
    	std::cout<<"newWindowverbund - "<<Class_name<<" IP: "<<IP<<"\n";
    }
    
    std::string Windowclan::get_ip(){		//IP-Adresse des Clans bekommen
    	return IP; 
    }
    
    const char* Windowclan::getWindowclanName(){	//Name des Fensterverbundes bekommen
    	return Class_name.c_str();
    }
    
    void Windowclan::sff(const int rot, const int gruen, const int blau){ 	//Standard Fensterfarbe
    	if(rot>=0 && rot<=255 && gruen>=0 && gruen<=255 && blau>=0 && blau<=255){
    		SBackground=CreateSolidBrush(RGB(rot, gruen, blau));
    		std::cout<<"sff - "<<get_sff()<<" gesetzt \n";
    	} 
    	else std::cout<<"sff - Ungueltige Farbwerte! \n";
    }
    
    std::string Windowclan::get_sff(){		//Standard Fensterfarbe bekommen
    	LOGBRUSH Brush;
    	GetObject(SBackground, sizeof(LOGBRUSH), &Brush);
    	COLORREF Colorref = Brush.lbColor;
    	std::string color=std::to_string(GetRValue(Colorref))+" "+std::to_string(GetGValue(Colorref))+" "+std::to_string(GetBValue(Colorref));
    	return color;
    }
    
    void Windowclan::f(const std::string Fenstername){	//Fenster anlegen
    	windows.push_back(std::unique_ptr<Window>(new Window(stoi(get_ip())+(Window_position+2)*100000, 
    															Class_name+" - "+Fenstername, SPosition, SSize, SBackground)));
    	Window_position+=1;
    	std::cout<<Window_position<<" "<<Fenstername<<" angelegt IP: "<<windows.back()->getIP()<<"\n";
    }
    
    std::string Windowclan::get_fip(){	//IP-Adresse des Fensters bekommen
    	if(Window_position>=0){
    		return windows.back()->getIP();
    	}
    	else std::cout<<"get_fip - Noch kein Fenster erstellt! \n";
    }
    
    void Windowclan::ff(const int rot, const int gruen, const int blau){		//Fensterfarbe für aktuelles Fenster
    	if(Window_position>=0){
    		if(rot>=0 && rot<=255 && gruen>=0 && gruen<=255 && blau>=0 && blau<=255){
    			windows.back()->setBackground(rot, gruen, blau);
    			std::cout<<" gesetzt \n";
    		}
    		else std::cout<<"ff - Ungueltige Farbwerte! \n";
    	}
    	else std::cout<<"ff - Noch kein Fenster erstellt! \n";
    }
    
    std::string Windowclan::get_ff(){		//Fensterfarbe für aktuelles Fenster bekomme
    	if(Window_position>=0){
    		return windows.back()->getBackground();
    	}
    	else std::cout<<"get_ff - Noch kein Fenster erstellt! \n";
    }
    
    void Windowclan::stf(const int rot, const int gruen, const int blau){	//Standard Fensterfarbe
    	if(Window_position>=0){
    		if(rot>=0 && rot<=255 && gruen>=0 && gruen<=255 && blau>=0 && blau<=255){
    			windows.back()->setSTextcolor(rot, gruen, blau);
    			std::cout<<" gesetzt \n";
    		}
    		else std::cout<<"stf - Ungueltige Farbwerte! \n";
    	}
    	else std::cout<<"stf - Noch kein Fenster erstellt! \n";
    }
    
    std::string Windowclan::get_stf(){	//Standard Fensterfarbe bekommen
    	if(Window_position>=0){
    		return windows.back()->getSTextcolor();
    	}
    	else std::cout<<"get_stf - Noch kein Fenster erstellt! \n";
    }
    
    void Windowclan::t(const std::string Text){	//Text anlegen
    	if(Window_position>=0){
    		windows.back()->setString(Text);
    		std::cout<<" gesetzt IP: "<<windows.back()->textboxes.back()->getIP()<<"\n";
    	}
    	else std::cout<<"t - Noch kein Fenster erstellt! \n";
    }
    
    std::string Windowclan::get_tip(){	//IP-Adresse des Textes bekommen
    	if(Window_position>=0 && windows.back()->Textbox_position>=0){
    		return windows.back()->textboxes.back()->getIP();
    	}
    	else std::cout<<"get_tip - Noch kein Fenster oder kein Text erstellt! \n";
    }
    
    void Windowclan::tf(const int rot, const int gruen, const int blau){		//Textfarbe für aktuellen Text
    	if(Window_position>=0 && windows.back()->Textbox_position>=0){
    		if(rot>=0 && rot<=255 && gruen>=0 && gruen<=255 && blau>=0 && blau<=255){
    			windows.back()->textboxes.back()->setTextcolor(rot, gruen, blau);
    			std::cout<<" gesetzt \n";
    		}
    		else std::cout<<"tf - Ungueltige Farbwerte! \n";
    	}
    	else std::cout<<"tf - Noch kein Fenster oder kein Text erstellt! \n";
    }
    
    std::string Windowclan::get_tf(){		//Textfarbe für aktuellen Text bekommen
    	if(Window_position>=0 && windows.back()->Textbox_position>=0){
    		return windows.back()->textboxes.back()->getTextcolor();
    	}
    	else std::cout<<"get_tf - Noch kein Fenster oder kein Text erstellt! \n";
    }
    
    bool Windowclan::Is_registrate=FALSE;
    
    void Windowclan::a(){	//Ausgabe der Fenster
    	if(Window_position>=0){
    		Window::This(this);
    
    		if(Is_registrate!=TRUE){
    			Window::Registrate_wndclass();
    			Is_registrate=TRUE;
    		} 
    
    		int a=0;
    		for(auto &Counter : windows){
    
    			Counter->MyHandle=CreateWindowEx(0, "Fenster", Counter->Name.c_str(), WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,
    								 				Counter->Position.x+a*10, Counter->Position.y+a*20, Counter->Size_old.right, 
    												Counter->Size_old.bottom, 0, 0, GetModuleHandle(NULL), Counter->My_this);
    			if(Counter->MyHandle==NULL){
      	 			std::cout<<std::endl<<"-----Fenster konnte nicht erzeugt werden!\n-----";
     	  			exit(0);
     	  		}
    			else std::cout<<Counter->Name.c_str()<<" - Kreiert \n";
    
    			ShowWindow(Counter->MyHandle, SW_SHOW);
    			UpdateWindow(Counter->MyHandle);
    			if(Counter->Default_position) a++;
    		}
    
    		MSG msg;
    		while(GetMessage(&msg,0,0,0)){
     	  	    TranslateMessage(&msg);
     	  	    DispatchMessage(&msg);
     	  	}
    	}
    	else std::cout<<"a - Noch kein Fenster erstellt! \n";
    }
    
    #ifndef wdlc_WINDOW_H
    #define wdlc_WINDOW_H
    
    #include<windows.h>
    #include<vector>
    #include<memory>
    #include<string>
    
    #include"wdlcWindows.h"
    #include"wdlcTextbox.h"
    
    class Windowclan;
    
    class Window{
    	friend class Textboxes; 
    	friend class Figures;
    	friend class Windowclan;
    
    	static Windowclan *pwindowclan;
    	static void Registrate_wndclass();
    	static void This(Windowclan *Zeiger);
    	static LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
    	LRESULT CALLBACK MyWindowProc(UINT msg,WPARAM wParam,LPARAM lParam);
    
    	std::vector<std::unique_ptr<Textbox>> textboxes;
    
    	HWND MyHandle; 
    	Window *My_this;
    
    	std::string IP;	
    	std::string Name;
    
    	int Textbox_position;
    
    	bool Default_position;
    	POINT Position;
    	RECT Size_old, Size;
    	HBRUSH Background;
    
    	POINT STextposition;
    	COLORREF STextcolor;
    	COLORREF STextbackground;
    
    	Window(const int IP, const std::string Name, const POINT SPosition, const RECT SSize, const HBRUSH SBackground);
    
    	std::string getIP();
    
    	void setSTextcolor(const int red, const int green, const int blue);
    	std::string getSTextcolor();
    
    	void setBackground(const int red, const int green, const int blue);
    	std::string getBackground();
    
    	void setString(const std::string newString);
    };
    
    #endif
    
    #include<iostream>
    
    #include "wdlcWindow.h"
    
    Windowclan *Window::pwindowclan;
    
    Window::Window(const int IP, const std::string Name, const POINT Position, const RECT Size, const HBRUSH Background): 
    		Textbox_position(-1), IP(std::to_string(IP)), My_this(this), Name(Name), Position(Position), Size(Size), 
    		Size_old(Size), Background(Background), Default_position(TRUE), STextposition({50, 50}), STextcolor(RGB(0, 0, 0)),
    		STextbackground(RGB(255, 255, 255)){
    	std::cout<<"\n Window - ";
    }
    
    void Window::This(Windowclan *Pointer){
    	pwindowclan=Pointer;	
    }
    
    void Window::Registrate_wndclass(){
    	WNDCLASSEX wcx;
       	wcx.cbClsExtra=0;
       	wcx.cbSize=sizeof(WNDCLASSEX);
       	wcx.cbWndExtra=0;								
       	wcx.hbrBackground=CreateSolidBrush(RGB(255, 255, 255));		
       	wcx.hCursor=LoadCursor(GetModuleHandle(NULL),IDC_ARROW);
       	wcx.hIcon=LoadIcon(GetModuleHandle(NULL),NULL);
       	wcx.hIconSm=wcx.hIcon;
       	wcx.hInstance=GetModuleHandle(NULL);
       	wcx.lpfnWndProc=WndProc;
       	wcx.lpszClassName="Fenster";
       	wcx.lpszMenuName=NULL;
       	wcx.style=CS_HREDRAW|CS_VREDRAW;
    
       	if(!RegisterClassEx(&wcx)){
           	std::cout<<std::endl<<"-----Registrierung der Fensterklasse fehlgeschlagen!\n-----";
           	std::cin.get();
           	exit(-1);
       	}
    }
    
    LRESULT CALLBACK Window::WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam){ 
        if(Message == WM_CREATE) {
        	   ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)((CREATESTRUCT*)lParam)->lpCreateParams); 
       	} 
    
        Window* pReceiver = (Window*)GetWindowLongPtr(hWnd, GWLP_USERDATA); 
    
        if (!pReceiver) {
               	return ::DefWindowProc(hWnd, Message, wParam, lParam); 
        } 
        return pReceiver->MyWindowProc(Message, wParam, lParam); 
    } 
    
    LRESULT CALLBACK Window::MyWindowProc(UINT msg,WPARAM wParam,LPARAM lParam){
        switch(msg){
        	case WM_DESTROY:{
        		for(auto &Counter : pwindowclan->windows){
        			DestroyWindow(Counter->MyHandle);
    			}
    			PostQuitMessage(0);
           	}break;
    
            case WM_CREATE:{
            	break;
            }
    
    		case WM_SIZE:{
    			Size.right=LOWORD(lParam);
           		Size.bottom=HIWORD(lParam);
    		}break;
    
        	case WM_PAINT:{
         	   	for(auto &CounterA : pwindowclan->windows){
         	       	PAINTSTRUCT ps;
         	       	HDC hdc = BeginPaint(CounterA->MyHandle, &ps);
    
    				FillRect(hdc, &Size, Background);
    
         	       	int Counter_lines=0;
         	       	for(auto &CounterB : CounterA->textboxes){
         	       		SetTextColor(hdc, CounterB->Textcolor);
         	       		SetBkColor(hdc, CounterB->Background);
         	       		if(CounterB->Default_position){
         	       			TextOut(hdc, CounterB->Position.x, CounterB->Position.y+19*Counter_lines, 
    									CounterB->getString(), strlen(CounterB->getString()));
    						Counter_lines+=1;
         	       		} 
         	       		else TextOut(hdc, CounterB->Position.x, CounterB->Position.y, CounterB->getString(), 
    									strlen(CounterB->getString()));
    
         	       	}	
         	       	EndPaint(CounterA->MyHandle, &ps);
    			}
    
         	}return 0;
       	}
        return ::DefWindowProc(MyHandle,msg,wParam,lParam);
    }
    
    std::string Window::getIP(){
    	return IP;
    }
    
    void Window::setSTextcolor(const int red, const int green, const int blue){
    	if(red>=0 && red<=255 && green>=0 && green<=255 && blue>=0 && blue<=255){
    		STextcolor=RGB(red, green, blue);
    		std::cout<<"stf - "<<getSTextcolor();
    	}
    	else std::cout<<"stf - Ungueltige Farbwerte! \n";
    }
    
    std::string Window::getSTextcolor(){
    	std::string color=std::to_string(GetRValue(STextcolor))+" "+std::to_string(GetGValue(STextcolor))+" "+std::to_string(GetBValue(STextcolor));
    	return color;
    }
    
    void Window::setBackground(const int red, const int green, const int blue){
    	if(red>=0 && red<=255 && green>=0 && green<=255 && blue>=0 && blue<=255){
    		Background=CreateSolidBrush(RGB(red, green, blue));
    		std::cout<<"ff - "<<getBackground();
    	}
    	else std::cout<<"ff - Ungueltige Farbwerte! \n";
    }
    
    std::string Window::getBackground(){
    	LOGBRUSH Brush;
    	GetObject(Background, sizeof(LOGBRUSH), &Brush);
    	COLORREF Colorref = Brush.lbColor;//!!!
    	std::string color=std::to_string(GetRValue(Colorref))+" "+std::to_string(GetGValue(Colorref))+" "+std::to_string(GetBValue(Colorref));
    	return color;
    }
    
    void Window::setString(const std::string String){
    	textboxes.push_back(std::unique_ptr<Textbox>(new Textbox(stoi(getIP())+Textbox_position+2, String, 
    																STextposition, STextcolor, STextbackground)));
    	Textbox_position+=1;
    	std::cout<<Textbox_position<<" wurde";
    }
    
    #ifndef wdlc_TEXTBOX_H
    #define wdlc_TEXTBOX_H
    
    #include<windows.h>
    #include<string>
    
    class Textbox{
    	friend class Figures;
    	friend class Window; 
    	friend class Windowclan;
    
    	std::string IP;
    	std::string String;
    
    	bool Default_position;
    	POINT Position;
    	COLORREF Textcolor;
    	COLORREF Background;
    
    	Textbox(const int IP, const std::string String, const POINT Position, const COLORREF Textcolor, const COLORREF Background);
    
    	std::string getIP();	
    	const char* getString();
    
    	void setTextcolor(const int red, const int green, const int blue);
    	std::string getTextcolor();
    };
    
    #endif
    
    #include<iostream>
    
    #include "wdlcTextbox.h"
    
    Textbox::Textbox(const int IP, const std::string String, const POINT Position, const COLORREF Textcolor, const COLORREF Background): 
    		IP(std::to_string(IP)), String(String), Default_position(TRUE), Position(Position), 
    		Textcolor(Textcolor), Background(Background){
    	std::cout<<"t - ";		
    }
    
    std::string Textbox::getIP(){
    	return IP;
    }
    
    const char* Textbox::getString(){
    	return String.c_str();
    }
    
    void Textbox::setTextcolor(const int red, const int green, const int blue){
    	if(red>=0 && red<=255 && green>=0 && green<=255 && blue>=0 && blue<=255){
    		Textcolor=RGB(red, green, blue);
    		std::cout<<"ff - "<<getTextcolor();
    	}
    	else std::cout<<"sff - Ungueltige Farbwerte! \n";
    }
    
    std::string Textbox::getTextcolor(){
    	std::string color=std::to_string(GetRValue(Textcolor))+" "+std::to_string(GetGValue(Textcolor))+" "+std::to_string(GetBValue(Textcolor));
    	return color;
    }
    

    Noch keine Funktion:

    #ifndef wdlc_FIGURE_H
    #define wdlc_FIGURE_H
    
    #include<string>
    
    class Figures{
    	friend class Textboxes;
    	friend class Window; 
    	friend class Windowclan;
    
    };
    
    #endif
    

    Zugriff soll nur über das Windowclan-Objekt und dessen public-Funktionen möglich sein. (Ich habe schon überlegt ob ich die lieber auslagern soll, zumindest scheinen die mir Fehlplatziert zu sein?, auch bei den ganzen Windows-Funktionen bin ich mir unsicher ob die an der richtigen Stelle sind?)

    Die Funktionsnamen in dieser Klasse sollen ein schnelleres Konstruieren der Fenster ermöglichen (Beispiel ist in der Main), ob man keine Kürzel verwenden sollte, darüber kann man sich streiten, ist ja kommentiert was die machen, ansonsten sind in allen anderen Klassen die Namen natürlich eindeutig.

    Ich habe mich bemüht keinen "Missbrauch" zu gestatten (z.B. negative Farbwerte), wobei der ctor noch fehlt, der kommt zu späterem Zeitpunkt. Auf Vererbung habe ich absichtlich verzichtet.

    Die MyWindowProc() ist noch reichlich unausgereift, da ist auf jeden Fall noch arbeit reinzustecken.

    Mir geht es vor allem um Hinweise zum Aufbau und zur Funktionsweise, damit ich mir keinen schlechten Stil angewöhne. (Programmieren bringe ich mir selbst bei, da ist die Wahrscheinlichkeit hoch das dies passiert...)

    Vorab schon mal Vielen Dank,
    MFG John.



  • John1 schrieb:

    Da ich bei meinem ersten Versuch bereits gescheitert bin, wollte ich Versuch 2 nochmals von euch "kontrollieren lassen"

    In Hinsicht auf was? Das scheint eher was fürs C++ Forum zu sein, nicht WinApi. Oder geht es dir darum, ob deine Wrapper sinnvoll sind? Das wäre recht schwer zu beantworten. Kommt drauf an, was man machen will. Will man jetzt genau dieses Testprogramm haben, ist es völlig ausreichend. Will man ein komplexeres Framework aufbauen, dass man dann in einem größeren Programm benutzen will, ist es ziemlich sicher nicht ausreichend und wahrscheinlich auch nicht gut/flexibel genug.

    Der Stil gefällt mir jetzt nicht so. Ich habs mir nicht durchgeschaut (wenn du willst, dass jemand deinen C++ Code bewertet, lass den Thread ins C++ Forum verschieben, vielleicht findet sich da jemand), mir sind schon beim Drüberscrollen paar Sachen aufgefallen, die mir nicht gefallen:

    - const std::string Name, sollte wohl eher const std::string**&** Name sein
    - Überall Inkonsistenzen, z.B. ist der Parameter hier großgeschrieben, später oft klein
    - const char * und std::string gemischt, warum reichen dir strings nicht?
    - static? Warum? Keine Ahnung was du machst, find ich aber grundsätzlich verdächtig.
    - Die ganzen getter sollten wohl auf jeden Fall const sein
    - Schon wieder lauter inkonsistente und ungewöhnliche Namen, z.B. get_ip. Bei den meisten wäre das wohl getIp() const.
    - zu viele friends, und auch noch ziemlich sicher falsch rum. Warum sollte eine Klasse "Textboxes" (schon wieder ein komischer Name, wenn es mehrere Textboxen sind, sollte es halt eine Liste von Textboxen sein) eine Klasse "Windowclan" kennen? Macht zu 99% keinen Sinn.
    - Ich verwende grundsätzlich nur englische Bezeichner, aber Inkonsistenzen mag ich noch weniger. Wo du anscheinend schon weißt, dass Farbe auf englisch color heißt, warum schreibst du dann noch rot und gruen hin?
    - My_This?



  • Hallo,
    Vielen Dank für deine Antwort.
    Ich hätte wahrscheinlich gleich den Code Spalten sollen (einmal nur die Windows Funktionen in diesem Thread und im c++ Forum den Rest).

    Trotzdem konnte ich schon einige Verbesserungen dank deiner Hinweise vornehmen: getter sind jetzt alle const, setter bekommen nur noch Referenzen, Parameter sind nun alle groß geschrieben (waren nur die Farben klein, ungewollt...), die Friends sind neu sortiert (deutlich wenigere), bei den Statics waren tatsächlich 2 unnötige dabei und es gibt nur noch strings (Windows verlangt char*, werden nun an entsprechender Stelle erst mit c_str() konvertiert).

    Zu den Windows-Funktionen hast du ja schon einiges geschrieben, wobei nicht wirklich meine Fragen beantwortet sind (ich habe die ja auch nicht deutlich formuliert;-)

    In Hinsicht auf was?

    Ob der Aufbau der Klassen korrekt ist?
    Ob die Ausgabefunktion ( 'a()' ) korrekt aufgebaut ist, und somit auch alle Teile die zu ihr gehören?

    Die Idee hinter dem Aufbau:
    Der Benutzer legt ein Windowclan-Objekt an, über Funktionen dieses Objekts kann er den "Aufbauplan" für mehrere Fenster erstellen und diese ausgeben lassen
    In dem Clan-Objekt wird also ein Vektor aus Window-Objekten erzeugt
    Die Window Objekte speichern die Fensterfarbe, Position, Größe usw, und erzeugen Vektoren welche aus Textbox-Objekten, Figure-Objkten usw bestehen, und sie Speichern auch ihr jeweiliges Handle zum Fenster und ihre LRESULT CALLBACK
    Die LRESULT CALLBACK kann über die Vektoren den Fensterinhalt erzeugen
    Die Texbox/Figure-Objekte speichern jeweils ihre Farbe, Position usw

    Auch wenn Klassenaufbau eher zu C++ gehört, denke ich man muss die WinAPI kennen um meinen aufbau beurteilen zu können, daher dieses Forum...

    Ich habe nochmal die Header etwas eingekürzt, jetzt ist fast nur noch der reine Windows-Teil übrig.

    Ich hoffe auf Feedback, Schonmal vielen Dank!
    MFG John.

    Edit: Programm ist kompilierbar und Funktionsfähig, die Ausrufezeichen dienen nur als Hinweis an mich wo ich noch was ändern möchte...

    #include <iostream>
    #include "wdlcWindows.h"
    
    int main(int argc, char *argv[]) {
    
    	Windowclan w1("Clan1");	//Windowclan anlegen
    
    	w1.f("Window1");	//Fenster zum Clan hinzufügen 
    	w1.t("Text1");		//Text zum Fenster hinzufügen
    	w1.t("Text2");
    
    	w1.f("Window2");
    	w1.t("Text3");
    	w1.t("Text4");
    
    	w1.a();
    
    	Windowclan w2;		//Zweiter unbenannter Clan
    
    	w2.f("Window1");
    	w2.t("Text1");
    	w2.t("Text2");
    
    	w2.f("Window2");
    	w2.t("Text3");
    	w2.t("Text4");
    
    	w2.a();
    
    	return 0;
    }
    
    #ifndef wdlc_WINDOWS_H
    #define wdlc_WINDOWS_H
    
    #include<vector>
    #include<memory>
    #include<string>
    
    #include"wdlcWindow.h"
    
    class Window;
    
    class Windowclan{	
    private:
    	friend class Window;
    
    	static int Calls;
    
    	static bool Is_registrate; 
    
    	std::vector<std::unique_ptr<Window>> windows;
    
    	std::string IP;
    	std::string Class_name;
    
    	int Window_number;
    
    	POINT SPosition;
    	RECT SSize;
    	HBRUSH SBackground;
    
    public:
    	Windowclan();
    	Windowclan(const std::string& Name);
    
    	void f(const std::string& Fenstername); 	//Fenster anlegen
    
    	void t(const std::string& Text);		//Text anlegen
    
    	void a();	//Ausgeben der Fenster
    };
    
    #endif
    
    #include <iostream>
    
    #include "wdlcWindows.h"
    #include "wdlcWindow.h"
    
    int Windowclan::Calls=1;
    
    Windowclan::Windowclan(): 
    		Window_number(1), IP(std::to_string(Calls*100000000)), Class_name("Unbenannt"), SSize({0,0,800,600}), SPosition({400,20}), 
    		SBackground(CreateSolidBrush(RGB(255,255,255))){
    	Calls++;
    	std::cout<<"newWindowverbund - "<<Class_name<<" IP: "<<IP<<"\n";
    }
    
    Windowclan::Windowclan(const std::string& Name): 
    		Window_number(1), IP(std::to_string(Calls*100000000)), Class_name(Name), SSize({0,0,800,600}), SPosition({400,20}),
    		SBackground(CreateSolidBrush(RGB(255,255,255))){
    	Calls++;
    	std::cout<<"newWindowverbund - "<<Class_name<<" IP: "<<IP<<"\n";
    }
    
    void Windowclan::f(const std::string& Fenstername){		//Fenster anlegen
    	windows.push_back(std::unique_ptr<Window>(new Window(this, /*stoi(get_ip())+(Window_number)*100000,*/ 
    																Class_name+" - "+Fenstername, SPosition, SSize, SBackground)));
    	Window_number++;
    }
    
    void Windowclan::t(const std::string& Text){	//Text anlegen
    	if(Window_number>=1){
    		windows.back()->setString(Text);
    	}
    	else std::cout<<"t - Noch kein Fenster erstellt! \n";
    }
    
    bool Windowclan::Is_registrate=FALSE;
    
    void Windowclan::a(){	//Ausgabe der Fenster
    	if(Window_number>=1){
    		if(Is_registrate!=TRUE){
    			Window::Registrate_wndclass();
    			Is_registrate=TRUE;
    		} 
    
    		int a=0;//!!!
    		for(auto &Counter : windows){
    
    			Counter->MyHandle=CreateWindowEx(0, "Fenster", Counter->Name.c_str(), WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,
    								 				Counter->Position.x+a*10/*!*/, Counter->Position.y+a*20/*!*/, Counter->Size_old.right, Counter->Size_old.bottom,
    										 		0, 0, GetModuleHandle(NULL), Counter->Window_this);
    			if(Counter->MyHandle==NULL){
      	 			std::cout<<"\n-----Fenster konnte nicht erzeugt werden!\n-----";
     	  			exit(0);
     	  		}
    			else std::cout<<Counter->Name<<" - Kreiert \n";
    
    			ShowWindow(Counter->MyHandle, SW_SHOW);
    			UpdateWindow(Counter->MyHandle);
    
    			if(Counter->Default_position){//!!!
    				a++;
    			} 
    		}
    
    		MSG msg;
    		while(GetMessage(&msg,0,0,0)){
     	  	    TranslateMessage(&msg);
     	  	    DispatchMessage(&msg);
     	  	}
    	}
    	else std::cout<<"a - Noch kein Fenster erstellt! \n";
    }
    
    #ifndef wdlc_WINDOW_H
    #define wdlc_WINDOW_H
    
    #include<windows.h>
    #include<vector>
    #include<memory>
    #include<string>
    
    #include"wdlcWindows.h"
    #include"wdlcTextbox.h"
    
    class Windowclan;
    
    class Window{
    	friend class Windowclan;
    
    	Windowclan *pwindowclan;
    
    	static void Registrate_wndclass();
    	static LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
    	LRESULT CALLBACK MyWindowProc(UINT msg,WPARAM wParam,LPARAM lParam);
    
    	std::vector<std::unique_ptr<Textbox>> textboxes;
    
    	HWND MyHandle; 
    	Window *Window_this;
    
    	std::string IP;	
    	std::string Name;
    
    	int Textbox_number;
    
    	bool Default_position;
    	POINT Position;
    	RECT Size_old, Size;
    	HBRUSH Background;
    
    	POINT STextposition;
    	COLORREF STextcolor;
    	COLORREF STextbackground;
    
    	Window(Windowclan* PWindowclan, /*const int& IP,*/ const std::string& Name, const POINT& SPosition, const RECT& SSize, const HBRUSH& SBackground);
    
    	void setString(const std::string& String);
    };
    
    #endif
    
    #include<iostream>
    
    #include "wdlcWindow.h"
    
    Window::Window(Windowclan* PWindowclan, /*const int& IP,*/ const std::string& Name, const POINT& Position, const RECT& Size, const HBRUSH& Background): 
    		pwindowclan(PWindowclan), Textbox_number(1), /*IP(std::to_string(IP)),*/ Window_this(this), Name(Name), Position(Position), Size(Size), Size_old(Size), 
    		Background(Background), Default_position(TRUE), STextposition({50, 50}), STextcolor(RGB(0, 0, 0)), STextbackground(RGB(255, 255, 255)){
    }
    
    void Window::Registrate_wndclass(){
    	WNDCLASSEX wcx;
       	wcx.cbClsExtra=0;
       	wcx.cbSize=sizeof(WNDCLASSEX);
       	wcx.cbWndExtra=0;								
       	wcx.hbrBackground=CreateSolidBrush(RGB(255, 255, 255));		
       	wcx.hCursor=LoadCursor(GetModuleHandle(NULL),IDC_ARROW);
       	wcx.hIcon=LoadIcon(GetModuleHandle(NULL),NULL);
       	wcx.hIconSm=wcx.hIcon;
       	wcx.hInstance=GetModuleHandle(NULL);
       	wcx.lpfnWndProc=WndProc;
       	wcx.lpszClassName="Fenster";
       	wcx.lpszMenuName=NULL;
       	wcx.style=CS_HREDRAW|CS_VREDRAW;
    
       	if(!RegisterClassEx(&wcx)){
           	std::cout<<std::endl<<"-----Registrierung der Fensterklasse fehlgeschlagen!\n-----";
           	std::cin.get();
           	exit(-1);
       	}
    }
    
    LRESULT CALLBACK Window::WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam){ 
        if(Message == WM_CREATE) {
        	   ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)((CREATESTRUCT*)lParam)->lpCreateParams); 
       	} 
    
        Window* pReceiver = (Window*)GetWindowLongPtr(hWnd, GWLP_USERDATA); 
    
        if (!pReceiver) {
               	return ::DefWindowProc(hWnd, Message, wParam, lParam); 
        } 
        return pReceiver->MyWindowProc(Message, wParam, lParam); 
    } 
    
    LRESULT CALLBACK Window::MyWindowProc(UINT msg,WPARAM wParam,LPARAM lParam){
        switch(msg){
        	case WM_DESTROY:{
        		for(auto &Counter : pwindowclan->windows){
        			DestroyWindow(Counter->MyHandle);
    			}
    			PostQuitMessage(0);
           	}break;
    
            case WM_CREATE:{
            }break;
    
    		case WM_SIZE:{
    			Size.right=LOWORD(lParam);
           		Size.bottom=HIWORD(lParam);
    		}break;
    
        	case WM_PAINT:{
         	    PAINTSTRUCT ps;
    			HDC hdc=BeginPaint(MyHandle, &ps);
    
    			FillRect(hdc, &Size, Background);
         	    int Counter_lines=0;//!!!
    
         	    for(auto &Counter : textboxes){
               		SetTextColor(hdc, Counter->Textcolor);
               		SetBkColor(hdc, Counter->Background);
         	   		if(Counter->Default_position){
         	   			TextOut(hdc, Counter->Position.x, Counter->Position.y+19*Counter_lines/*!*/, 
    								Counter->getString().c_str(), strlen(Counter->getString().c_str()));
    					Counter_lines+=1;//!!!
         	      	} 
         	      	else TextOut(hdc, Counter->Position.x, Counter->Position.y, Counter->getString().c_str(), strlen(Counter->getString().c_str()));	
         	    }
    			EndPaint(MyHandle, &ps);	     	       
         	}return 0;
       	}
        return ::DefWindowProc(MyHandle,msg,wParam,lParam);
    }
    
    void Window::setString(const std::string& String){
    	textboxes.push_back(std::unique_ptr<Textbox>(new Textbox(/*stoi(getIP())+Textbox_number,*/ String, STextposition, STextcolor, STextbackground)));
    	Textbox_number++;
    }
    
    #ifndef wdlc_TEXTBOX_H
    #define wdlc_TEXTBOX_H
    
    #include<windows.h>
    #include<string>
    
    class Textbox{
    	friend class Windowclan;
    	friend class Window; 
    
    	std::string IP;
    	std::string String;
    
    	bool Default_position;
    	POINT Position;
    	COLORREF Textcolor;
    	COLORREF Background;
    
    	Textbox(/*const int& IP,*/ const std::string& String, const POINT& Position, const COLORREF& Textcolor, const COLORREF& Background);
    
    	std::string getString() const;
    };
    
    #endif
    
    #include<iostream>
    
    #include "wdlcTextbox.h"
    
    Textbox::Textbox(/*const int& IP,*/ const std::string& String, const POINT& Position, const COLORREF& Textcolor, const COLORREF& Background): 
    		/*IP(std::to_string(IP)),*/ String(String), Default_position(TRUE), Position(Position), Textcolor(Textcolor), Background(Background){		
    }
    
    std::string Textbox::getString() const{
    	return String;
    }
    


  • John1 schrieb:

    Die Window Objekte speichern die Fensterfarbe, Position, Größe usw

    Soweit schon mal ok.
    Den Rest kann ich noch so nicht ganz nachvollziehen bzw. seh erstmal keinen Grund, das so aufzubauen. Kennst du andere GUI Frameworks? Alle anderen Frameworks arbeiten mit irgendwelchen Basisklassen, z.B. Window oder Widget. Nennen wir das mal Widget, ist eine Recht geläufige Bezeichnung (in Qt und Gtkmm gibts Widgets, MFC hat als Basisklasse CWnd). Eine Textbox wäre demnach ein Widget, genauso wie ein Fenster und wahrscheinlich auch eine "Figur".
    Warum machst du das nicht so? Wenn du eine Basisklasse hättest, könnten Widgets weitere Widgets verwalten, ohne sich darum kümmern zu müssen, was das ist. Ein Widget hätte dann eine Liste von weiteren Widget Zeigern, und ob das jetzt Textboxen, Buttons, Labels, Slider oder sonst was sind, ist dem Widget völlig egal. Genauso wären natürlich spezialisierte Funktionen wie f oder t nicht nötig, ein Widget verwaltet nur weitere Widgets und du würdest dann sowas aufrufen: window->addChild(new TextBox());
    Dass ein Widget dabei Eigenschaften wie Handle, Farbe, Position usw. speichert wäre jetzt auch wieder für alle Widgets in Ordnung. Wobei du das unter Windows evtl. nicht mal speichern müsstest, sondern über API Funktionen abfragen könntest. Kommt aber natürlich auch wieder drauf an, was du alles machen willst. Viele GUI Frameworks haben ein Layout Konzept und verwalten die Position der Widgets selber, deswegen müssen sie die Position und Größe dann doch in irgendeiner Form selber verwalten.
    Du hast diesen Ansatz schon mal nicht verwendet, deswegen fällt es mir schwer, über die Sinnhaftigkeit von deinem Klassenaufbau nachzudenken. Die Widgethierarchien haben sich einfach bewährt, daran vorbeizuprorgammieren macht keinen Sinn.

    Parameter schreibt man üblicherweise klein 😉

    Auch die restlichen Friends stören mich noch. Window ist immer noch ein Friend von Windowclan. Es sieht so aus, als ob Window eine völlig grundlegende Basisklasse wäre, die überhaupt nichts über irgendwelche übergeordneten Klassen wie Windowclan wissen darf.

    Der Sinn der a Funktion erschließt sich mir auch nicht. Ich würde die richtigen Windows Fenster hinter deinen Fensterklassen nicht sofort rekursiv erstellen, sondern on demand. Wenn ein Window oder Widget dargestellt werden muss, kann es ja ein richtiges Windows Fenster mit CreateWindow erzeugen. Das sollte aber alles versteckt sein und nicht von auße aufrufbar, so in der Art, jetzt hab ich meine Fensterhierarchie definiert und jetzt lass ich die erzeugen.



  • Hallo.

    Mechanics schrieb:

    Eine Textbox wäre demnach ein Widget, genauso wie ein Fenster und wahrscheinlich auch eine "Figur".
    Warum machst du das nicht so?

    Da ich mich bewusst gegen Vererbung, und vielmehr gegen Polymorphie entschieden habe. Natürlich macht Polymorphie vieles einfacher, man hat weniger Schreibaufwand und man muss gar weniger nachdenken (weil man beim Erweitern nur noch an einer Stelle was ändern muss). Mir liegt es aber am Herzen, dass meine Programme auch auf Low-Level Rechnern laufen. Ich finde es außerordentlich bedenklich, dass immer mehr Programmierer sinnvolle Ressourcennutzung hinter die eigene Bequemlichkeit stellen. Ich habe kein Verständnis dafür, dass man aller 3 Jahre sich einen neuen Rechner kaufen muss, weil die Updates der Programme (wo eigentlich nichts upgedatet wurde außer der Code dahinter) auf einmal immer mehr und mehr Ressourcen fressen. Und das Schlimme ist, dass das auch noch von den Entwicklern der Sprachen mehr und mehr unterstützt wird (natürlich bringen unique_ptr und Co mehr Sicherheit, sie führen aber vordergründig dazu, dass der Programmierer immer weniger denkt -> "ich kann ja nichts falsch machen, der Compiler oder irgendetwas anderes kümmert sich schon darum, oder gibt eine Fehlermeldung" (in der dann auch noch idiotensicher erklärt ist, was man falsch gemacht hat und wie man das lösen kann))...

    Genauso wären natürlich spezialisierte Funktionen wie f oder t nicht nötig, ein Widget verwaltet nur weitere Widgets und du würdest dann sowas aufrufen: window->addChild(new TextBox());

    Dann müsste der Benutzer jedesmal 29 oder mehr zusätzliche Zeichen eintippen um seinen Text im Fenster auszugeben, und obendrein noch wissen wie die Klassen heißen. Das mir die Position dieser "unüblichen" Funktionen selbst stört hatte ich ja schon geschrieben (vielleicht eine eigene "Verwaltungs-Klasse", die selbstständig eine Liste der Clans anlegt und die unüblichen Funktionen vom Rest "abschottet", dann müsste der Benutzer nicht einmal mehr eigene Objekte anlegen). Das ganze soll ja kein Framework werden, sondern nur eine Möglichkeit mit relativ kleinem Wissensstand seine Konsolenprogramme durch eine schönere Ausgabe nachträglich zu erweitern.

    Auch die restlichen Friends stören mich noch. Window ist immer noch ein Friend von Windowclan. Es sieht so aus, als ob Window eine völlig grundlegende Basisklasse wäre, die überhaupt nichts über irgendwelche übergeordneten Klassen wie Windowclan wissen darf.

    Der einzige Grund hierfür ist, dass in der Proc bekannt sein muss, wie viele Fenster es gibt, um nach dem Schließen aller Fenster die Message Queue, beenden zu können, damit der Konsolenteil weiterarbeiten kann, und der verctor dieser Fenster ist nun einmal im Windowclan. Wobei ich da für Ideen offen bin, ich fand es einfach am performantesten einen Zeiger auf das Clan-Objekt abzuspeichern? Eventuelle einen getter dafür im Windowclan anlegen, wobei der dann auch wieder Public währe, ich möchte ja den Zugriff des Benutzers auf derartige Dinge vermeiden?

    Der Sinn der a Funktion erschließt sich mir auch nicht. [...] so in der Art, jetzt hab ich meine Fensterhierarchie definiert und jetzt lass ich die erzeugen.

    Wahrscheinlich verstehe ich dich gerade völlig falsch, aber tut die a-Funktion nicht genau das? Wobei ich das Erstellen wahrscheinlich lieber als Funktion in der Window-Klasse anlegen sollte, dann erspare ich mir auch die ganzen Zeiger auf Fenstername, Größe, Handle usw?

    Also wenn es dir Fordergründig um das fehlen von Vererbung geht, dann werde ich das wohl nicht umsetzen, wenn du etwas anderes meintest, dann habe ich dich völlig falsch verstanden 🙂
    MFG und einen schönen Sonntag, John.



  • John1 schrieb:

    Da ich mich bewusst gegen Vererbung, und vielmehr gegen Polymorphie entschieden habe.

    Das hättest du gleich dazuschreiben können 😉 Oder vielleicht hab ichs einfach übersehen.
    Wobei deine Argumentation an der Stelle keinen Sinn macht. Bei "Low Level" hätte man ja noch denken können, dass du deine API auch für C Programmierer zugänglich machen willst. Aber Performance als Argument ist hier völlig fehl am Platz. Vererbung oder Polymorphie machen überhaupt nichts langsamer. Im Endeffekt optimiert der Compiler das sowieso alles komplett weg (es gibt im Maschinencode natürlich keine Klassen), und wahrscheinlich kann er das noch besser optimieren, wenn ihm die Zusammenhänge über Klassenbeziehungen klar sind, als bei vielen ähnlichen Klassen, wie du das machst.
    Ich kann das Argument aber auch irgendwie nachvollziehen. Als ich angefangen habe zu programmieren, hatte ich auch eine unbegründete Abneigung gegen Vererbung und Klassen überhaupt. Hatte irgendwie so eine Ahnung, die würden mein Programm aufblähen oder langsamer machen, ohne dass ich verstanden hätte, wie das alles funktioniert und das ich keine Ahnung hatte.
    Wenn du mit Polymorphie explizit auf "virtual" hinauswillst, mach dir nichts vor, ein virtual ist immer noch mindestens genauso schnell wie ein if, und davon wirst du viel mehr brauchen, wenn du auf Polymorphie verzichtest. Außerdem wird es ganz einfach nicht funktionieren.

    Dass man alle paar Jahre einen neuen Rechner braucht, stimmt auch schon seit mindestens 5 Jahren nicht mehr. Ich hab mir dieses Jahr einen neuen Rechner gekauft, hauptsächlich wollte ich endlich mal eine SSD haben und bei der Gelegenheit halt auch gleich einen komplett neuen Rechner gekauft, weil der alte schon über 5 Jahre alt war. Aber der hat mir auch völlig gereicht, sowohl zum Entwickeln als auch zum Spielen. Und bei sowas geht es eh nicht um irgendwelche 0815 Programme, sondern um "Hardcore" Anwendungen. Für Textverarbeitung würde auch ein 20 Jahre alter Rechner reichen, aber wenn du z.B. ein sehr großes Programm kompilieren willst, wird es mit einem schnelleren Rechner halt schneller gehen.

    Auch die anderen Aussagen von dir sind eher bedenklich. Da du dir anscheinend vieles selber beibrigst, musst du mit sowas vorsichtig sein. Man kann viele Vorurteile aufschnappen, aber vieles ist davon ist völlig belanglos oder stamm aus den 80ern und wird ohne Verstand nachgeplappert. Ich hab schon vor über 15 Jahren, als ich angefangen habe, haufenweise ganz ähnliche Aussagen gelesen. Das sind einfach Aussagen, auf die man komplett verzichten kann. Zum einen wird der Compiler den unique_ptr in 99% der Fälle komplett wegoptimieren. Schau mal in den Assemblercode oder miss mal nach. Bin mir nicht ganz sicher, aber mag sein, dass es irgendwelche Sonderfälle gibt, in denen das nicht geht. Aber selbst in den Fällen wird es dir schwerfallen, irgendeinen halbwegs sinnvollen Fall zu konstruieren, bei dem der Performanceoverhead mehr als paar Prozentbruchteile beträgt. Wie gesagt, vergiss es einfach.
    Aussagen, dass die Sprachen irgendwie dazu führen, dass der Programmierer weniger nachdenkt, habe ich auch schon tausend mal gesehen. Der Programmierer kann sich dann eben auf wichtigere Sachen konzentrieren, als auf Speicherverwaltung. Genauso kann man auch argumentieren, dass man eigentlich nur in Assembler programmieren darf und jedesmal selber aufpassen, dass jedes pop zu dem push passt. DANN denkt man richtig mit. Nein, tut man nicht, ich hab schon genug Assembler programmiert und alles was man sinnlos von Hand macht lenkt nur vom eigentlichen Programm ab. Das sind Aussagen von irgendwelchen Scriptkiddies, die sich unter "Programm" etwas mit grob 100 Lines of Code vorstellen und nicht nachvollziehen können, warum man dafür aufgeblähte Sprachen wie C++ braucht. Es ist praktisch unmöglich, in einem größeren Programm ohne Hilfsmittel wie smart pointer oder Objektorientierung auszukommen. Und selbst mit diesen Hilfsmitteln wirst du Memory Leaks nicht vermissen 😉 Wir kämpfen auch noch genug mit Speicherproblemen, obwohl wir smart pointer benutzen, langweilig wird einem in der Hinsicht nicht. Hier zusätzliche Komplexität durch manuelle Speicherverwaltung reinzubringen wär einfach nur hirnrissig.

    John1 schrieb:

    Dann müsste der Benutzer jedesmal 29 oder mehr zusätzliche Zeichen eintippen um seinen Text im Fenster auszugeben, und obendrein noch wissen wie die Klassen heißen.

    Das ist irrelevant. Ich würd hier auch nichts "verstecken". Jemand, der den Code benutzen will, muss eben wissen, wie die Klassen heißen. Da ist es auch nicht besser, wenn er weiß, dass er ein "t" für Textbox braucht.

    John1 schrieb:

    Das ganze soll ja kein Framework werden, sondern nur eine Möglichkeit mit relativ kleinem Wissensstand seine Konsolenprogramme durch eine schönere Ausgabe nachträglich zu erweitern.

    Das kann so nicht funktionieren. Was du dir unter schön vorstellst, muss nicht dem entsprechen, was ein Benutzer deines nicht-frameworks sich vielleicht vorstellt. Sowas muss entsprechend flexibel sein, damit man damit das aufbauen kann, was man will. Was nützt es einem, wenn du ihm Textboxen und Figuren anbietest? Was ist, wenn er noch einen Knopf, ein DropDown Feld und eine Baumansicht haben will?

    John1 schrieb:

    Wahrscheinlich verstehe ich dich gerade völlig falsch, aber tut die a-Funktion nicht genau das?

    Ich hätts dynamischer gemacht. Ein Benutzer muss nicht wissen, dass er jetzt alle Fenster erzeugen muss. Er baut seine Fenster auf, und irgendwann macht er halt eins auf. Dann muss das Fenster wissen, dass es jetzt wirklich ein Windows Objekt erzeugen muss. Und wenn das Fenster gar nicht sichtbar ist und man es nocht nicht braucht, dann braucht man das auch noch nicht erzeugen. Du verschwendest gleich mal auf Verdacht einen Haufen Ressourcen, die man vielleicht nie brauchen wird.

    Also, es kann sein, dass das alles so wie du dir das vorstellst auch so reicht, aber ich kann so nicht mitreden. Irgendwann gewöhnt man es sich an, Probleme "richtig" anzugehen, und ohne Vererbung wird das hier nicht funktionieren, oder das was funktioniert ist auch meiner Sicht irrelevant.



  • N´Nabend,

    Mechanics schrieb:

    Das hättest du gleich dazuschreiben können 😉 Oder vielleicht hab ichs einfach übersehen.

    Ich habe einiges schon dazugeschrieben (wahrscheinlich zu viel, wodurch du es nur übersehen konntest;-)

    John schrieb:

    Die Funktionsnamen in dieser Klasse sollen ein schnelleres Konstruieren der Fenster ermöglichen (Beispiel ist in der Main), ob man keine Kürzel verwenden sollte, darüber kann man sich streiten, ist ja kommentiert was die machen, ansonsten sind in allen anderen Klassen die Namen natürlich eindeutig.
    Ich habe mich bemüht keinen "Missbrauch" zu gestatten (z.B. negative Farbwerte), wobei der ctor noch fehlt, der kommt zu späterem Zeitpunkt. Auf Vererbung habe ich absichtlich verzichtet.

    Aber Performance als Argument ist hier völlig fehl am Platz. Vererbung oder Polymorphie machen überhaupt nichts langsamer. Im Endeffekt optimiert der Compiler das sowieso alles komplett weg[...]
    Wenn du mit Polymorphie explizit auf "virtual" hinauswillst, mach dir nichts vor, ein virtual ist immer noch mindestens genauso schnell wie ein if, und davon wirst du viel mehr brauchen, wenn du auf Polymorphie verzichtest.

    OK, da ich jemand bin der sich meist umfangreich über das informiert was er benutzt, hatte ich auch sehr viel über "virtual" und die Virtuelle-Methoden-Tabelle gelesen. und aus dem was ich gelesen habe, hatte ich geschlussfolgert, dass es inperformanter sein muss, als wenn man sich lieber selbst mehr "Schreibarbeit" macht. If-Abfragen benutze ich ja nicht, da für jede Methode eine eigene Funktion vorliegt, was man über eine virtuelle setColor, setPosition usw machen würde. Wobei mich hierbei tatsächlich interessieren würde was nun schneller ist/ weniger Rechnerleistung braucht...

    Ansonsten gebe ich tatsächlich relativ wenig auf das "Wissen" das viele unbedingt "teilen" müssen, gibt leider viel zu viel Unsinn im Netz. Aber mehr als viele verschiedene Meinungen zu einem Thema lesen kann ich letztlich auch nicht, wodurch dann sicher auch mal falsches Wissen hängen bleibt, aber wem geht es nicht so. 🙂

    Da du im allgemeinen über mein Gesamtes System und weniger über die konkreten Dinge deine Bedenken geäußert hast, werde ich hoffentlich nicht völlig am OOP vorbei geschossen sein, das ganze ist tatsächlich mein erstes größeres Projekt (natürlich nur für mich als Übung), und die von mir gewählte Zielgruppe, weiß im Zweifelsfall wohl nicht einmal was eine Klasse ist, wodurch mir das nicht egal sein darf;-) Und wenn jemand Knöpfe mit einbauen möchte, dann soll der gleich selbst sich mit API`s und Co beschäftigen (ich habe nicht vor eine neue Erfindung oder ein neues Framework zu schreiben, dass gibt es ja schon), ich habe es ja auch hinbekommen...

    Dementsprechend nochmal Vielen Dank für deine Anregungen, einige fließen bestimmt mit ein (einige sind schon), und wer weiß, vielleicht gibt es ja in einem Jahr tatsächlich ein "Virtual-Update" von dem Ganzen.

    Ach, und ich habe nichts gegen Smart-ptr, nur was gegen Menschen die das was sie vor die Nase gesetzt bekommen benutzen ohne auch nur eine geringste Ahnung zu haben was dahinter steckt.

    MFG John.



  • John1 schrieb:

    OK, da ich jemand bin der sich meist umfangreich über das informiert was er benutzt, hatte ich auch sehr viel über "virtual" und die Virtuelle-Methoden-Tabelle gelesen. und aus dem was ich gelesen habe, hatte ich geschlussfolgert, dass es inperformanter sein muss, als wenn man sich lieber selbst mehr "Schreibarbeit" macht.

    Es ist praktisch vernachlässigbar. Ein virtual Aufruf an sich ist nichts was irgendwie "Zeit kosten" würde, da gehts um paar Taktzyklen. Ein virtual Aufruf ist im Gegensatz zu einem normalen Funktionsaufruf ein indirekter Sprung. Das ist etwas schwieriger für die Branch Prediction vom Prozessor. Aber wenn du die Funktion paar mal aufrufst, dann sind es wie gesagt vielleicht paar Taktzyklen Unterschied. Und wenn du die Funktion paar Milliarden mal aufrufst, dann kriegt es die Branch Prediction wahrscheinlich auch auf die Reihe. Und normalerweise fällt sowas im Vergleich zu der Funktion, die du aufrufen willst, in keinster Weise ins Gewicht.
    SetColor, SetPosition usw. hättest du doch gar nicht virtuell machen brauchen. Um das alles kann sich die Basisklasse kümmern, das muss nicht virtuell sein. Was virtuell sein müsste wäre sowas wie eine "create" Methode, die sich dann drum kümmert, das Objekt wirklich zu erstellen. Und jetzt stell dir vor, die wäre wegen virtual 20 Taktzyklen langsamer. Ruft dann aber CreateWindowEx auf usw., verbrät also insgesamt wahrscheinlich zig Millionen Taktzyklen. Das reicht nicht als Argument, um deswegen eine sehr ungewöhnliche und unflexible Softwarearchitektur aufzuziehen 😉


Anmelden zum Antworten