WinApi - OOP
-
Ja, löschen und neu schreiben. Ernsthaft. Guck dir mal RAII an. Insbesondere Konstruktoren und Destruktoren. Eine Methode Init() weist so gut wie immer darauf hin, dass man das Prinzip nicht verstanden hat. Eine Methode die man vor Init aufrufen muss noch mehr. Nutze Initialisierungslisten. Höre auf auf Membervariablen mit this-> zuzugreifen wenn es nicht unbedingt nötig ist. Nimm Abstand von der ungarischen Notation. (Außer bei windowseigenen Typen vll.)
WNDCLASS ist kein Member eines Fensterobjekts. msg, title, Größe etc. musst du auch nicht speichern, das macht die WinAPI doch schon. Der einzige Member den du brauchst ist das Handle. (HWND) Was zum Henker macht isDone()? auf const correctness achten. int ist nicht der richtige Typ für Bildschirmkoordinaten oder Größenangaben, oder hast du da schon mal negative Werte gesehen? (std::uint16_t wäre der richtige Typ.)
Warum heißt deine Klasse überhaupt Application? Das ist so ziemlich der am wenigsten aussagekräftige Name den man sich vorstellen kann. Das ist eine Fensterklasse verdammt, nenn sie window oder so. Und so kannst du auch nicht mehrere Fenster erstellen. Guck dir mal den Beitrag von Shade Of Mine hier an.
-
darman96 schrieb:
hat jemand Vorschläge wie ich die Klasse noch verbessern könnte?
- Auf C-Präfix und generell auf UN verzichten (bei
hWndkann man noch darüber streiten, aber "i" und "n" vor Integers ist fragwürdig) - Leere Parameterlisten ohne
void - Konstruktor-Initialisierungsliste verwenden
- Const-Correctness bei Get-Methoden beachten
- Keine leeren Destruktoren definieren
Init()privat machen und direkt im Konstruktor aufrufen- Konsistente Namenskonvention (
isDonevs.SetTitle) - Konsistente Namen ("Befehle" wie
HandleMessagesstattMessageHandling) static_caststatt C-Casts verwenden- Sich überlegen, nach welchem Kriterium Funktionen inline sind (oder gleich alles in der .cpp-Datei definieren)
- Auf C-Präfix und generell auf UN verzichten (bei
-
cooky451 schrieb:
... int ist nicht der richtige Typ für Bildschirmkoordinaten oder Größenangaben, oder hast du da schon mal negative Werte gesehen? (std::uint16_t wäre der richtige Typ.)
Für Bildschirmangaben schon oder welchen Wert hat bei dir Top und Left, wenn du ein Fenster links bzw. oben teilweise außerhalb des sichtbaren Bereichs schiebst?
-
Th69 schrieb:
cooky451 schrieb:
... int ist nicht der richtige Typ für Bildschirmkoordinaten oder Größenangaben, oder hast du da schon mal negative Werte gesehen? (std::uint16_t wäre der richtige Typ.)
Für Bildschirmangaben schon oder welchen Wert hat bei dir Top und Left, wenn du ein Fenster links bzw. oben teilweise außerhalb des sichtbaren Bereichs schiebst?
Dabei auch nicht zu vergessen: Multimonitorsysteme...
-
Könnte mir denn jemand mal ein Beispiel für so eine Klasse geben?
-
Zum Beispiel
sf::Windowvon SFML, da ist WinAPI komplett weggekapselt. Kommt halt drauf an, was du genau machen willst... Wofür brauchst du das Fenster?
-
Ich hatte mir gedacht damit opengl Anwendungen zu machen und für die GUI awesowmium zu benutzen.
Edit: Wo in den SFML dateien ist denn die WinMain funktion
Edit 2: Habs gefunden.
-
So ein neuer Versuch:
main.cpp:
#include "stdafx.h" int WINAPI WinMain(HWND Handle, HINSTANCE Instance, HINSTANCE PrevInstance, LPCSTR CmdLine, int CmdShow) { Window window(Handle, Instance, "Test"); }Window.h:
#pragma once #pragma once #include "stdafx.h" class Window { public: Window(); Window(HWND Handle, HINSTANCE hInstance, std::string title); ~Window(); private: HWND Handle; HINSTANCE hInstance; void RegisterWindowClass(); static LRESULT CALLBACK WndProc(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam); };Window.cpp:
#include "Window.h" // static members const char* className = "MyClass"; Window::Window(HWND Handle, HINSTANCE Instance, std::string title) : Handle(Handle), Instance(Instance) { RegisterWindowClass(); Handle = CreateWindow(className, title.c_str(), WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, NULL, NULL, Instance, NULL); ShowWindow(Handle, SW_NORMAL); UpdateWindow(Handle); } Window::~Window(void) { } void Window::RegisterWindowClass() { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = Instance; wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = className; wcex.hIconSm = NULL; RegisterClassEx(&wcex); } LRESULT CALLBACK Window::WndProc(HWND Handle, UINT Message, WPARAM wParam, LPARAM lParam) { if(Message == WM_CREATE) { long This = reinterpret_cast<long>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams); SetWindowLongPtr(Handle, GWLP_USERDATA, This); } Window* window = reinterpret_cast<Window*>(GetWindowLongPtr(Handle, GWLP_USERDATA)); return DefWindowProc(Handle, Message, wParam, lParam); }Jetzt bekomm ich aber immer diese fehlermeldung:
Fehler 1 error C2731: 'WinMain': Überladen der Funktion nicht möglichPS: ich weiß das da noch einiges fehlt vor allem was message handling angeht aber ich will das jetzt erst mal so ans laufen kriegen

-
Das liegt daran, dass die Parameterliste deiner WinMain Mist ist...
-
Oh stimmt habs grad gesehen o.o sorry.
-
Btw: Ich kann nur sehr empfehlen, die englische Version von Visual Studio zu benutzen, allein schon weil google dir für deutsche Compilerfehler wesentlich weniger ausspucken wird...
-
Ich hab grad vs 2012 getestet und das war auf deutsch. die 2010er version hab ich auf englisch und mal sehen obs die 2012 auch in englisch gibt.
Kann mir jemand nen Tipp geben wie ich das Message Handling machen könnte ?
-
Woran genau scheitert's?
-
Also da ist einmal der Code in der wndproc, den hab ich aus der sfml Klasse "geklaut". Den versteh ich nicht so ganz. Und dann würde ich das Event handlingalso Tastatur Eingaben und so gerne in einer eigenen Klasse machen.
-
Th69 schrieb:
Deinen Ansatz gibt es schon und nennt sich MFC.
btw: Application developers should not write frameworks and toolkits
Es ist einfach "Write games not game engines" weitergefasst.
Guck dir mal RAII an. Insbesondere Konstruktoren und Destruktoren. Eine Methode Init() weist so gut wie immer darauf hin, dass man das Prinzip nicht verstanden hat.
Das ist zu pauschal und demnach falsch. Klingt mehr nach Religion, vielleicht magst du eine Sekte gruenden: Kirche des RAII. Ich habe beispielsweise gerade diese Methode mittels init fuer ein aktuelles Problem gewaehlt. Ist quasi ein einfachres placement new.
PS: Ja, ich konnte mir das nicht verkneifen.
-
knivil schrieb:
Guck dir mal RAII an. Insbesondere Konstruktoren und Destruktoren. Eine Methode Init() weist so gut wie immer darauf hin, dass man das Prinzip nicht verstanden hat.
Das ist zu pauschal und demnach falsch.
Ist es durch die Relativierung "so gut wie" gerade nicht.
knivil schrieb:
Ich habe beispielsweise gerade diese Methode mittels init fuer ein aktuelles Problem gewaehlt.
Ja, kann vereinzelt vorkommen. Dennoch stimmt cooky451s Aussage, erst recht auf diesen Thread bezogen. Es ist ziemlich offensichtlich, dass RAII für darman96s Problem eine bessere Lösung wäre.
Oder willst du unbedingt die Diskussion von letztem Mal wiederholen? Es gibt genug schlechte Buchautoren, die kein RAII vermitteln, du musst jetzt nicht noch einen persönlichen Feldzug dagegen antreten

-
knivil schrieb:
Ich habe beispielsweise gerade diese Methode mittels init fuer ein aktuelles Problem gewaehlt. Ist quasi ein einfachres placement new.
Interessant, kannst du das näher erleutern?
-
Leute das hatten wir doch alles schon.
1. Ich hab gar keine init function mehr.
2. Ich weiß das ich das nich machen MUSS und das es das schon gibt aber ich will es trotzdem machen und zu dem Satz "Write games not game engines" kann ich nur sagen: wenn alle sich daran halten würden hätten wir heute nicht sehr viele engines mit denen man spiele machen könnte
3. ich hatte nach dem Message/Event Handling gefragt.
Gruß darman96
-
darman96 schrieb:
2. Ich weiß das ich das nich machen MUSS und das es das schon gibt aber ich will es trotzdem machen und zu dem Satz "Write games not game engines" kann ich nur sagen: wenn alle sich daran halten würden hätten wir heute nicht sehr viele engines mit denen man spiele machen könnte

Stimmt. Dann hätten wir viele gute Engines, mit denen man Spiele machen könnte. Aber da sich leider nicht alle da dran halten, haben wie viele gute Engines, mit denen man Spiele machen könnte und Millionen von Schrottengines, mit denen man gar nichts machen kann.
Wenn es doch bloß eine Methode gäbe, Wissen von Generation zu Generation weiter zu geben, damit nicht jeder Neuling immer wieder die gleichen Fehler wiederholt
. Das wurde die Menschheit wirklich weit vorwärts bringen.
-
SeppJ schrieb:
Wenn es doch bloß eine Methode gäbe, Wissen von Generation zu Generation weiter zu geben, damit nicht jeder Neuling immer wieder die gleichen Fehler wiederholt
. Das wurde die Menschheit wirklich weit vorwärts bringen.http://www.ted.com/talks/aubrey_de_grey_says_we_can_avoid_aging.html
