[gelöst] Klassen vor deklarieren? && WindowProc() deklarationsfähig machen?
-
Hallo

es gibt zwei mögliche lösungen für mein Problem, aber ich würde gerne beide kennen lernen da sie mich beide Interessieren.
1. Kann man Klassen einer funktionen bekannt machen ohne das man sie erstellen muss?
im Codebeispiel unten sieht man das ich Control ctrl vor dem WindowProc außerhalb der Mainfunction erstelle und dann unten pointer der anderen Objekte "nachreiche". kann ich Control irgendwie vordeklarieren so das WindowProc nicht sagt das ctrl.bla nicht deklariert ist?2. Kann ich die WindowProc() funktion irgendwo anders stehen haben als vor der Main funktion?
Dann müsste ich meine Klassen nicht außerhalb der mainfunktion erstellen.Beispielcode:
Control ctrl; // <-- Um dieses Objekt geht es. // Es muss leider hier vor der WindowProc function stehen LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_KEYDOWN: ctrl.key_Down(wParam); break; return DefWindowProc (hWnd, message, wParam, lParam); } int WINAPI WinMain() { //Windowclass here - für übersichtszwecke abgespeckt. DirectX_Device dxdv(&hInstance, hWnd); Hexapod hexa(dxdv.get_view()->get_CamPtr()); GUI3D gui(&dxdv, &hexa, &ctrl); ctrl.set_objects(&hexa, dxdv.get_view(), &gui); // das frühe deklarieren endet leider damit das ich Pointer nicht im Konstruktor übergeben kann, // sondern wie hier nachreichen muss. }viele Grüße,
Chris
-
WindowProc ist einfach nur irgendeine Funktion, die kannst du definieren wo du willst. Eine Klasse kann man so deklarieren:
class MyClass;Solange du sie aber nicht definierst, kannst du auch nur mit Pointern/Referenzen arbeiten, der Compiler weiß hier ja noch gar nicht wie groß ein Objekt vom Typ "MyClass" ist.
Das mit der globalen Variable solltest du dir allerdings noch mal überlegen, Shade Of Mine hatte da mal etwas gutes zu geschrieben:
http://www.c-plusplus.net/forum/301786
-
1. Normalerweise solltest du einen Header haben, der die Control class/struct/union deklariert. Bsp:
//control.h class Control{ void key_Down(WPARAM); void set_objects(...); };Später reichst du die Definition nach per
//control.cpp void Control::key_Down(WPARAM wParam){ //Todo: tu was schlaues hier }//main.cpp #include "control.h" Control ctrl; // <-- Um dieses Objekt geht es. // Es muss leider hier vor der WindowProc function stehen LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ...2. Genau gleich. Es gibt die Deklaration und die Definition.
//Deklaration, kann beliebig oft im Code stehen und muss vor Verwendung von WindowProc einmal gemacht werden LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); //Definition, darf nur einmal gemacht werden, egal wo, zählt auch als Deklaration LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ ... }In der Main muss also die Definition von WindowProc nicht stehen, die Deklaration aber schon, bzw. du kannst die Deklaration in die main.h oder so schreiben und am Anfang der main.cpp #include "main.h" schreiben.
Ich weiß nicht wie man entscheidet, ob man die WindowProc und die Control class in verschiedene Dateien splittet. Wenn man zu viel splittet hat man schnell endlos viele Dateien, in denen fast nichts drin steht und hat keinen Überblick mehr, wenn man zu wenig splittet, dann hat man einzelne endlos große Dateien und auch keinen Überblick mehr. Der Mittelweg ist wohl am besten.
-
Danke für die vielen Antworten

Ich hab jetzt versucht die WindowProc Funktion zu bearbeiten und einzubinden.
Jetzt bekomme ich einen weiteren Kompilierfehler was mein WindowProc betrifft.error C2440: '=': 'LRESULT (__stdcall *)(HWND,UINT,WPARAM,LPARAM,DirectX_Device *,Control *)' kann nicht in 'WNDPROC' konvertiert werden 1> Diese Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformatbei folgendem Code:
// win_api.h: // LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, DirectX_Device* dxdv, Control* ctrl); // win_api.h end; // Die win_api.cpp hat die ganze funktion dann deklariert. #include "win_api.h" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { DirectX_Device dxdv(&hInstance, hWnd); Hexapod hexa(dxdv.get_view()->get_CamPtr()); GUI3D gui(&dxdv, &hexa, &ctrl); Control ctrl(&hexa, dxdv.get_view(), &gui); HWND hWnd; WNDCLASSEX wc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; // <<-- neues Problem wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszClassName = "WindowClass"; RegisterClassEx(&wc); hWnd = CreateWindowEx(NULL, "WindowClass", "Lua-Engine", WS_OVERLAPPEDWINDOW, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); }
-
Wo ist dein Problem? Verstehst du den Fehler nicht oder weißt du nicht wie du ihn reparierst?
-
offensichtlich beides nicht.
anscheinend erwartet wc.lpfnWndProc eine funktion windowProc ohne die beiden zusätzlichen Parrameter. aber wie einer funktion 2 parameter übergeben wenn nicht über den funktionskopf?
-
Dieses wc.lpfnWndProc ist vom Typ LRESULT CALLBACK (*)(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam). Das ist von Windows vorgegeben, da kommst du nicht dran vorbei. Deine Funktion hat andere Parameter, deswegen funktioniert die Zuweisung nicht.
Du kannst allerdings einfach eine Windowskonforme Funktion schreiben, die deine Funktion aufruft.
Beispiel:
LRESULT CALLBACK wrapper(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, DirectX_Device* dxdv, Control* ctrl); } ... wc.lpfnWndProc = wrapper;Bleibt noch die Frage, woher wrapper die korrekten DirectX_Device* und Control* bekommt. Eine Möglichkeit ist es einfach diese 2 Objekte per WinAPI an das Fenster dranzuhängen:
struct DXC{ DirectX_Device* dxdv; Control* ctrl; }; LRESULT CALLBACK wrapper(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ if (uMsg == WM_CREATE){ //Erstelle irgendwie DirectX_Device* dxdv und Control* ctrl DXC *dxc = new DXC; dxc.dxdv = ...; dxc.ctrl = ...; SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG)dxc); } //TODO: bei WM_QUIT dxc und seine attribute wieder freigeben DXC *dxc = (DXC *)GetWindowLongPtr(hwnd, USERDATA); WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, dxc->dxdv, dxc->ctrl); }Der C++igere Weg wäre sowas hier:
struct DXC{ DirectX_Device* dxdv; Control* ctrl; }; LRESULT CALLBACK wrapper(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ std::map<HWND, DXC> windowNutzdatenMapper; if (uMsg == WM_CREATE){ //Erstelle irgendwie DirectX_Device* dxdv und Control* ctrl windowNutzdatenMapper[hwnd].dxdv = ...; windowNutzdatenMapper[hwnd].ctrl = ...; } //TODO: bei WM_QUIT windowNutzdatenMapper.erase(hwnd) aufrufen WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, windowNutzdatenMapper[hwnd].dxdv, windowNutzdatenMapper[hwnd].ctrl); }
-
Bei den Funktionsaufrufen dürfen die Variablentypen nicht stehen, bin müde -.-
-
Ok das sieht super aus, bzw hilft es mir das ganze zu verstehen.
ich hab versucht ein Objekt zu schreiben das die Wrapper funktion und die WindowProc funktion hat, und dazu die beiden Objekte dxdv und ctrl. leider klappt das nicht weil der kompiler mault das "LRESULT" kein typname ist.
Wenn nicht in einer Klasse, wie kann ich dann dem restlichem Programm einen Pointer geben?WindowProc soll ja einen Pointer auf die beiden Objekte besitzen, aber der rest des Programms macht ja noch viel mehr mit den beiden Objekten, wie krieg ich den Pointer, von den dort erstellten Objekten, aus dem Wrapper herraus?
-
LRESULT sollte bei #include <Windows.h> oder WinDef.h mit kommen. Wenn er weiter mault teste Zeichen für Zeichen ob du dich nicht vertippt hast.
Der Rest des Programms wird von WindowProc aufgerufen und bekommt die Pointer dabei übergeben.
-
Ok danke dir
nun gehts