WinAPI-Fenster in Klassen kapseln



  • Hallo zusammen,

    ich möchte gerne mit WinAPI-Funktionen erstellte Fenster in Klassen kapseln. Dazu hab ich die MainWnd-Klasse erstellt, die in ihrem Konstruktor ein Fenster aufbaut:

    MainWnd::MainWnd(HINSTANCE hInstance)
    {
        MSG msg;
        WNDCLASS wc;
    
        wc.style         =  CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc   =  MainWndProc;
        wc.cbClsExtra    =  0;
        wc.cbWndExtra    =  0;
        wc.hInstance     =  hInstance;
        wc.hCursor       =  LoadCursor(NULL,IDC_ARROW);
        wc.hIcon         =  LoadIcon(NULL,L"app.ico");
        wc.hbrBackground =  NULL;
        wc.hbrBackground =  (HBRUSH)COLOR_WINDOW;
        wc.lpszClassName =  L"MainWindow";
        wc.lpszMenuName  =  NULL;
        wc.lpszMenuName  =  NULL;
        RegisterClass(&wc);
    
        hThisWnd = CreateWindow(L"MainWindow",
    			L"MapViewer",
    			WS_OVERLAPPED|WS_SYSMENU,
    			CW_USEDEFAULT,
    			CW_USEDEFAULT,
    			CW_USEDEFAULT,
    			CW_USEDEFAULT,
    			NULL,
    			NULL,
    			hInstance,
    			NULL);
    
        GetClientRect(hThisWnd,&rect);
    
        hdc = GetDC(hThisWnd);
    }
    

    Die Übergabeparameter erhält der Konstruktor aus der WinMain, die eine Instanz dieser Klasse erstellt. Als Messagefunktion hab ich folgende Klassenmethode erstellt:

    LRESULT CALLBACK MainWnd::MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	return 0;
    }
    

    Ich bekomm beim Kompilieren jetzt folgende Fehlermeldung:

    error C2440: '=' : cannot convert from 'long (__cdecl MainWnd::*)(struct HWND__ *,unsigned int,unsigned int,long)' to 'long (__cdecl *)(struct HWND__ *,unsigned int,
    unsigned int,long)'
    There is no context in which this conversion is possible

    Er hat also Probleme in folgender Zeile:

    wc.lpfnWndProc   =  MainWndProc;
    

    Meine Frage ist jetzt: Hab ich im Code einen grundlegenden Fehler oder ist es einfach nicht möglich, die WinAPI-Funktionalität in Klassen zu kapseln? Muss also alles aus der WinMain heraus geschehen?

    Vielen Dank !



  • Öhm, jeden Monat aufs neue oder wie? 🙄 Diese Problematik wird hie rim Forum jeden monat aufs neue besprochen -> Forensuche.





  • static



  • Ich sag nur Thunk-Klasse, static Methoden sind nicht nötig 🙄



  • Trotzdem muss dafür eine Window Proc static sein.



  • Nö, es hängt aber auch davon ab welche Thunk-Klasse du benutzt...
    Schonmal das hier probiert: http://www.codeproject.com/cpp/thunk.asp?target=CThunk



  • Ich benutze auch eine solche Thunk-Klasse für Fenster.

    Wie willst du denn bei der WNDCLASS/EX Struktur den lpfnWndProc Member ausfüllen?
    Dafür muss man doch erstmal eine statische Methode bzw. globale Funktion haben. Ansonsten klappt die Zuweisung doch nicht.

    Und in der statischen Methode gehts dann auf zur richtigen Memberfunktion.



  • Mein Gott, guck dir die Klasse an. Es gibt eine Methode die GetStaticProc heißt. Na, geschnallt? Wenn nicht, übergibst der WNDCLASSEX Structur, dem lpfnWndProc Member Thunk::GetStaticProc(); Da die Klasse eine Template-Klasse ist, muss du auch noch die richtigen Template-Paremeter, beim Instantiieren übergeben. In deinem Fall

    CThunk<WNDPROC,pfnProc,Klasse> Proc;
    

    pfnProc ist der Zeiger auf die NICHT-statische Member Funktion deiner Klasse, usw. Auf der von mir geposteten Seite steht alles beschrieben und wie man schön sagt: wer lesen kann ist klar im Vorteil.



  • Danke 👍 👍

    Habs nun kappiert und werde es mal ausprobieren.

    Kannst du mir noch sagen wie ich das CALLBACK richtig in das typedef für F2 (class function) unterbringe? Hab es bisher noch nicht geschafft.



  • angenommen deine Klasse heißt Window:

    //Zeiger auf die Member-Funktion
    typedef LRESULT (Window::*m_pfnCallback) (HWND,UINT,WPARAM,LPARAM);
    //Objekt anlegen
    CThunk<WNDPROC,m_pfnCallback,Window> Proc;
    
    //Im Ctor initialisieren, Window::WndProc ist eine Member-Funktion mit dem
    //Funktionskopf Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM); nicht statisch!
    Proc.Init(WndProc,this);
    


  • Jo, so hatte ich es auch schon. Aber fehlt da nicht ein CALLBACK/__stdcall?

    Die Methode Window::WndProc hat doch die Signatur

    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM)

    Oder?



  • nein, fehlt nicht. Die Methode bleibt bei thiscall Calling Convention.



  • Ach ja, stimmt. Daran hab ich gar nicht gedacht. 🙄

    Es hat jedenfalls super geklappt. Danke für deine Hilfe. 😋

    Hatte es vorher etwas umständlicher, so wie es hier beschrieben ist:

    http://staff.develop.com/onion/Articles/cpprep0399.htm


Log in to reply