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


Anmelden zum Antworten