Winapi Wrapper
-
Hallo, ich versuche ein paar Klassen zu erstellen, damit ich leichter GUIs erstellen kann. Ich schaffe es aber irgendwie nicht die Message Loop in eine Klasse zu kapseln.
class window { public: MSG Msg; WNDCLASSEX wc; HINSTANCE hInstance; HWND hwnd; virtual void OnCreate() { MessageBox(0,"Test","!!!",MB_OK); } LRESULT CALLBACK fu(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: OnCreate(); break; case WM_DESTROY: PostQuitMessage(0); return 0; case WM_CLOSE: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { window* he; he = new window; return he->fu(hwnd,msg,wParam,lParam); } void RegisterWindow(HINSTANCE hInstance,COLORREF color=RGB(255,255,255)) { this->hInstance = hInstance; memset(&wc,0,sizeof(wc)); wc.cbSize = sizeof(WNDCLASSEX); wc.lpfnWndProc = window::WndProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL,IDC_ARROW); wc.hbrBackground = CreateSolidBrush(color); wc.lpszClassName = "WindowClass"; wc.hIcon = LoadIcon(NULL,IDI_APPLICATION); wc.hIconSm = LoadIcon(NULL,IDI_APPLICATION); RegisterClassEx(&wc); } void create(string title,int xsize,int ysize,int xpos = CW_USEDEFAULT,int ypos = CW_USEDEFAULT) { hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass",title.c_str(),WS_VISIBLE|WS_CAPTION|WS_SYSMENU,xpos,ypos,xsize,ysize,0,0,hInstance,0); } int DoMsgLoop() { while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } };
Soweit funktioniert das, jetzt hab ich versucht die Klasse zu vererben, damit ich auch Code in die Eventfunktionen (z.B OnCreate() ) füllen kann :
class mywindow : public window { public: virtual void OnCreate() { MessageBox(0,"bla","bla",16); } };
Aber trotzdem kommt immer die MessageBox mit "Test" ?
Ich habe es mit dieser Seite http://www.gamedev.net/page/resources/_/technical/general-programming/creating-a-win32-window-wrapper-class-r1810 versucht, kapiere es aber nicht.
-
ehauser schrieb:
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
window* he;
he = new window;return he->fu(hwnd,msg,wParam,lParam);
}Achtung. Hier liegt dein Problemm. Du erzeugst jedes mal ein neues Window, dass dann natuerlich vom Typ window und nicht vom Typ mywindow ist; dementsprechend wird also auch nur die Methode von window aufgerufen. Viel schlimmer ist aber, dass du bei jeder Nachricht, die du empfeangst ein Memory-Leak erzeugst!
Auf der von dir verlinkten Seite steht ja, wie du es machen musst. "Nicht verstehen" ist aber ein dehnbarer Begriff, beschreib bitte genauer worans scheitert.
-
Also ich hab das nochmal bearbeitet (Memory-Leak behoben und jetzt wird mywindow anstatt window erzeugt) und es funktioniert immer noch nicht (Message Box mit "Test" anstatt "bla"):
class mywindow : public window { public: virtual void OnCreate() { MessageBox(0,"bla","bla",16); } static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { mywindow* he; he = new mywindow; LRESULT ret; ret = he->fu(hwnd,msg,wParam,lParam); delete he; return ret; } };
-
Noe, du hast das Leak nicht behoben. Du hast in mywindow eine statische Funktion definiert, die die Funtkion der Basisklasse ueberdeckt, aufgerufen wird innerhalb der Basisklasse dennoch die alte Version... und damit das Memoryleak.
Es gibt eigentlich keine andere Gute Moeglichkeit als mit SetWindwoLong* und GetWindowLong* in GWL_USERDATA einen mit der betreffenden Instanz deiner Klasse zu schreiben.
*Wenn du 64bit-kompatibel sein willst benutze entsprechend lieber Set und GetWindowLongPtr (Link in den Hinweiskaesten auf den beiden verlinkten Seiten)
EDIT: Warum erfindest du eig. das Rad neu anstatt MFC, ATL oder WTL zu benutzen
-
Es müsste aber so funktionieren, hat noch keiner so was selber schon mal gemacht?
-
Es müsste aber so funktionieren, hat noch keiner so was selber schon mal gemacht?
Zu den Erwähnten von OsDever füge ich noch Qt hinzu.
Ansonsten enpfehle ich sich die Grundlagen zur WinApi-Programmierung anzueignen:
Petzold
-
ehauser schrieb:
Es müsste aber so funktionieren, hat noch keiner so was selber schon mal gemacht?
Ja, ich hab das auch schonmal in kleinem Masse gemacht. Mir stellt sich halt nur die Frage was du machen willst. Wenn du das als Uebung machst, sei es um zu lernen wie man alte APIs wrappen kann, von mir aus auch um das WinAPI besser zu vertehen, oder einfach aus Spass an der Freude, dann ist das schon OK (naja, es ist dann ok, wenn du Set und GetWindowLong nimmst, nicht das was du Anfangs hattest
). Aber wenn du das machst, um wirklich ein GUI-Framework fuer den produktiven Einsatz bzw. fuer deine spaeteren Programme zu haben, dann wuerde ich wirklich lieber zu MFC, oder, wenn du dir VS Prof. nicht leisten kannst und auch kein Schueler bist um an Dreamspark teilzunehmen, zur kostenlosen WTL (von mir aus auch Qt, aber damit habe ich keine Erfahrung) raten.
Zum eigentlichen Thema: Bist du schon weitergekommen, was das Zeug mit GWL_USERDATA betrifft?
-
Naja ich glaub ich fang dann mal mit wxWidgets an, weils auch systemunabhängig ist.MFC und Windows Forms kann ich irgendwie nicht leiden.Aber ich lass das mal bleiben eine eigene GUI Bibliothek zu erstellen, einfach viel zu kompliziert!