Eigener WINAPI Wrapper
-
Hallo C++ler,
Ich versuche meinen eigenen WINAPI Wrapper zu programmieren, er funktioniert auch schon, jetzt habe ich jedoch einen Bug gefunden, dessen Ursache mir nach 2 Stunden Debugging immernoch unklar ist :O... Ich bin mir sicher, dass ich einfach nur zu dumm bin den Fehler jetzt zu finden
Der Fehler ist der folgende:
Ich erstelle ein Fenster, bei einem Linksklick verschwindet das Fenster für eine Sekunde, und erscheint dann wieder, bei einem Rechtsklick ensteht ein zweites Fenster. Wenn man jetzt jedoch auf dem zweiten Fenster einen Linksklick macht pausiert das Programm einfach nur ne Sekunde, der Rechstklick funktioniert aber
Ich poste hier einfach mal den Sourccode, und was ich rausgefunden habe:#pragma once #include <Windows.h> namespace PProgram{ class PApplication { private: WNDCLASSEX WndClassEx; HINSTANCE GethInstance(); HWND WindowHandle; char* Title; public: static LRESULT CALLBACK MsgRouter( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void Exec(); void Hide(); void Show(); PApplication(); PApplication(char* ClassName); ~PApplication(); }; };
#include "PApplication.h" int ClassName; bool AlreadyRunning = false; void MsgLoop(){ if (!AlreadyRunning){ AlreadyRunning = true; MSG msg; int status; while( status = GetMessage( &msg , NULL, NULL, NULL) > 0 ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } } } HINSTANCE PProgram::PApplication::GethInstance() { return (HINSTANCE) GetModuleHandle(NULL); } LRESULT CALLBACK PProgram::PApplication::MsgRouter( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ PProgram::PApplication *This = 0; if (msg == WM_NCCREATE){ SetWindowLong (hWnd, GWL_USERDATA, long((LPCREATESTRUCT(lParam))->lpCreateParams)); } This = (PProgram::PApplication *) GetWindowLong(hWnd, GWL_USERDATA); if(This){ return This->WndProc(hWnd, msg, wParam, lParam); } } LRESULT CALLBACK PProgram::PApplication::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ PProgram::PApplication s; switch( msg ){ case WM_DESTROY: DestroyWindow(hWnd); break; case WM_CLOSE: break; case WM_LBUTTONDOWN: this->Hide(); Sleep(1000); this->Show(); break; case WM_RBUTTONDOWN: s.Exec(); break; default: return DefWindowProc(hWnd, msg, wParam, lParam); break; } } PProgram::PApplication::PApplication() { Title = "Window"; } PProgram::PApplication::PApplication(char* Title) { this->Title = Title; } PProgram::PApplication::~PApplication() { } void PProgram::PApplication::Exec(){ char buf[5]; itoa(ClassName, buf, 10); ClassName++; WndClassEx.cbSize = sizeof(WndClassEx); WndClassEx.style = NULL; //Style WndClassEx.lpfnWndProc = PProgram::PApplication::MsgRouter; WndClassEx.cbClsExtra = NULL; //Später WndClassEx.cbWndExtra = NULL; //Später WndClassEx.hInstance = GethInstance(); // HInstance WndClassEx.hIcon = NULL; //Später nach Iconb fragen WndClassEx.hCursor = NULL; //Später nach Cursor fragen WndClassEx.hbrBackground = (HBRUSH) COLOR_BACKGROUND + 1; //Backgroundcolor fragen WndClassEx.lpszMenuName = NULL; //Später nach menü fragen WndClassEx.lpszClassName = (LPCSTR) buf; WndClassEx.hIconSm = NULL; if( !RegisterClassEx( &WndClassEx ) ){ MessageBox(0, "RegisterClassEx failed!", "Error", MB_OK | MB_ICONERROR); exit(1); } WindowHandle = CreateWindowEx( WS_EX_CLIENTEDGE, //Window ExStyle! (LPCSTR) buf, Title, //Titel des Fensters WS_OVERLAPPEDWINDOW, //Styles! CW_USEDEFAULT, //X CW_USEDEFAULT, //Y CW_USEDEFAULT, //Breite CW_USEDEFAULT, //Höhe NULL, //PARENT NULL, //MENU GethInstance(), this); if( WindowHandle == INVALID_HANDLE_VALUE){ MessageBox(0, "CreateWindowEx failed!", "Error", MB_OK | MB_ICONERROR); exit(1); } ShowWindow( WindowHandle, SW_NORMAL ); MsgLoop(); } void PProgram::PApplication::Show(){ ShowWindow(WindowHandle, SW_NORMAL); } void PProgram::PApplication::Hide(){ ShowWindow(WindowHandle, SW_HIDE); }
Was ich schon weiß:
Bei dem zweiten Fenster, an der Stelle wo das Objekt vom Fenster wiederhergestellt wird, wird das Fensterhandle nicht wieder ausgelesen, alles andere stimmt
Vielen Dank
-
Ouch, ziemlich frickelig.
In WndProc erstellst du eine lokale Variable s, rufst dann Exec() auf welches ein Fenster erzeugt, dann kehrt WndProc zurück und s ist tot, und somit auch das WindowHandle. Bei return This->WndProc(hWnd, msg, wParam, lParam); müsste es dann eig. crashen.
-
Vielen Dank!
Ich dachte schon, ich bin verrückt!
Warum es nicht crash ist klar, solange die Speicherposition nicht erneut beschrieben wurde, ist dort meines Wissens nach noch der alte Wert.
Pseudo