[C++]Callback-Funktion als Member einer Klasse

Spartaner117

Lt. Commander
Registriert
Feb. 2005
Beiträge
1.299
Hi,

wie man sich schon denken kann, würde ich gerne eine Callback-Funktion in eine Klasse packen. Der Code:

Code:
class EnumWinClass
{
private:

public:

    BOOL CALLBACK EnumWinProc(HWND hWnd, LPARAM lparam);


};

BOOL CALLBACK EnumWinClass::EnumWinProc(HWND hWnd, LPARAM lparam)
{
    if(IsWindowVisible(hWnd)&& GetParent(hWnd) == NULL)
    {
        char buffer[1024];
        GetWindowText(hWnd, buffer, 1024);
        /*if (buffer && buffer != "Sox")
        SendDlgItemMessage((HWND)lparam, IDC_MAIN_ADDKEY, LB_ADDSTRING, 0, (LPARAM)buffer);*/
    }
    return true;
}
Eine neue Klasseninstanz:
Code:
EnumWinClass BEWCI;
Und hier die Funktion:
Code:
EnumWindows(BEWCI.EnumWinProc, 0);

Der Compiler sagt:
error C2664: 'EnumWindows' : cannot convert parameter 1 from 'BOOL (HWND,LPARAM)' to 'WNDENUMPROC'
None of the functions with this name in scope match the target type

Mir war schon klar, dass das wohl nicht so einfach geht, aber das Inet spuckt nix dazu aus und ehrlichgesagt hab ich auch keine Idee wie sowas zu lösen ist.

Thx für eure Hilfe.
 
Ich würde es etwa so machen:

Code:
class EnumWinClass
{
private:
	int m_membervariable;

public:

	static BOOL CALLBACK EnumWinProc(HWND hWnd, LPARAM lparam);
	void ListWindows();
};

void EnumWinClass::ListWindows()
{
	EnumWindows(EnumWinProc, this);
}


BOOL CALLBACK EnumWinClass::EnumWinProc(HWND hWnd, LPARAM lParam)
{
	EnumWinClass* thisptr = (EnumWinClass*)lParam;
	if(IsWindowVisible(hWnd) && (GetParent(hWnd) == NULL))
	{
		char buffer[1024];
		GetWindowText(hWnd, buffer, 1024);
		/*if (buffer && buffer != "Sox")
		SendDlgItemMessage((HWND)lparam, IDC_MAIN_ADDKEY, LB_ADDSTRING, 0, (LPARAM)buffer);*/
	}
	return true;
}

Erklärung:
damit du die Callback Funktion in der Klasse deklarieren kannst, musst du static vornedran schreiben (kann man eingentlich genausogut außerhalb deklarieren, da man mit static nicht mehr auf die Member-Variablen und -Funktionen der Klasse zugreifen kann)
 
Hi,

das geht leider nicht so einfach. Enum Windows erwartet als Parameter einen Funktionszeiger im Format:
Code:
BOOL (*)(HWND, LPARAM);
Aber was in deinem Beispiel übergeben würde, ist ein
Code:
BOOL (EnumWinClass::*)(HWND, LPARAM);
"Würde", weil noch ein Syntaxfehler drin ist, denn auf die Adressen von Memberfunktionen kann man nur mit &Klasse::Methode zugreifen, also bei dir &EnumWinClass::EnumWinProc.

Einen Zeiger auf eine Memberfunktion kannst du nicht übergeben, weil eine Memberfunktion immer auf einem bestimmten Objekt arbeitet, in deinem Fall BEWCI. Wenn man sich den Zeiger auf eine Memberfunktion beschafft, ist das konkrete Objekt dabei nicht enthalten und damit könnte EnumWindows auch nie die Methode deines Objekts aufrufen, weil es das Objekt garnicht kennt. Stell dir mal die Methode deiner Klasse in der Signatur als das hier vor:
Code:
BOOL EnumWinClass_enumWinProc( EnumWinClass* this, HWND, LPARAM);
Im Prinzip funktioniert so ein Methodenaufruf und ich hoffe dir ist klar, warum das ganze so nicht gehen kann.


Was kann man tun um das zu lösen: Eine static-Memberfunktion - aber davon hat man nix, da man genauso eine freie Funktion schreiben könnte. Es kommt drauf an, die allgemeingültig und wie sauber du das ganze brauchst. Das kann man nämlich beliebig kompliziert machen ;)

EnumWindows macht es ziemlich einfach, wie Parallan schon gezeigt hat. Du kannst den Pointer auf die Klasse an EnumWindows übergeben als zweiten Parameter und bekommst ihn als lparam bei jedem Aufruf des Callbacks wieder zurück. Das ist schon die halbe Miete.

Anstatt der Memberfunktion registrierst du eine kleine Hilfsfunktion:
Code:
BOOL helper( HWND hwnd, LPARAM lparam)
{
   EnumWinClass* this = reinterpret_cast<EnumWinClass*>( lparam);
   return this->EnumWinProc( hwnd, 0); // den this-Pointer müssen wir hier nicht mehr weiter durchschleusen
}

Aufrufen tust du das ganze dann so:
Code:
EnumWindows(helper, reinterpret_cast<LPARAM>(&BEWCI));

(dabei sei aber anzumerken, dass das eine etwas schmuddelige Lösung ist)
 
Zuletzt bearbeitet:
Wof, hätt nicht gedacht, dass das so ein Oschi wird. :D
Danke für eure Antworten, und ich glaub ich weiß jetzt ein ganzes Stück mehr über Member- und Callbackfunktionen. ;)

Für meine bescheidenen Zwecke lass ich die Callback Funktion doch lieber draußen.
 
Zurück
Oben