MDI und Callback Funktion
-
das programm macht nicht mehr weiter, wenn ich auf F1 drücke.
STICK.

-
PAD[wParam]das dürfte in einen Speicherbereich zeigen, der nicht zu Deinem Prozess gehört.
Blackbird
-
Du drückst dich nicht gerade präzise aus. Wie genau sieht der Fehler aus? Zugriffsverletzung? Wenn ja, wo tritt diese auf (in welcher Zeile)?
-
ja. hast ja recht, damit kann man als aussenstehender ohne quellcode vor augen nicht viel anfangen. darum hier jetzt mehr informationen:
fehlermeldung:
unbehandelte ausnahme in api6.exe: 0*C000000005 access violation
an folgender stelle:
if (pMDData->hTab == (HWND)lParam && PAD[wParam] == TRUE)
dazu muss ich aber sagen, dass ich zuvor, also bevor ich die callbackfunktion angenfangen habe zu verändern für viele childwindows, folgenden code hatte und da gab es keine access violation meldung bei F1 betätigung. soll heissen, dass es da keine problem mit dem speicherzugriff geben müsste.
case WM_KEYDOWN: { PAD[wParam] == TRUE; return 0; }okay. lasst mich bitte wissen, wenn ihr noch mehr infos zu meinem code braucht.
DANKE!STICK

-
Hast du mal pMDData->hTab == (HWND)lParam oder PAD[wParam] == TRUE weggelassen`- dann sollte ja zumindest in einem Fall die Fehlermeldung ja weg sein.
PAD[wParam] == TRUE;Was soll das tun

-
Hast du mal pMDData->hTab == (HWND)lParam oder PAD[wParam] == TRUE weggelassen`
JA. das habe ich gerade gemacht. die fehlermeldung verschwindet dann auch. aber das problem ist dann, dass natürlich bei einer betätigung der F1 taste kein zoomen mehr ermöglicht wird. denn in einer while schleife, die u.a. auch meine OpenGL scene zeichnet, befindet sich auch folgender code:
if (PAD[VK_F1]) zoom +=0.2f; if (PAD[VK_F2]) zoom -=0.2f;was soll ich denn nun machen?
STICK.
-
Ich hatte eigentlich nicht gemeint, dass du das ganz weglässt, sondern wollte nur den Fehler einschränken, also ob es an
pMDData->hTab == (HWND)lParamoder an
PAD[wParam] == TRUEliegt....
Aber ich denke, dass am ehesten PAD[wParam] den Fehler verursacht, also dass wParam vielleicht manchmal ein ungültiger Index ist
Du kannst ja mal über den Debugger schauen, ob es bei jedem WM_KEYDOWN dort abstürzt und was für Werte die einzelnen Variablen dort haben...
-
HALLO.
ich habe nun deinen ratschlag befolgt und herausgefunden, wo der fehler liegt. deine vermutung, dass es dabei an PAD[wParam] == TRUE liegt, hat sich nicht bestätigt. wenn ich nur diesen befehl in der if-bedingung lasse, stürzt das programm nicht mehr ab, führt aber auch nicht die gewünschte ZOOM funktion aus.
bleibt nur pMDData->hTab == (HWND)lParam in der if-bedingung, dann stürzt das programm ab und gibt wieder die FEHLERMELDUNG "unbehandelte ausnahme etc.".
über den wert von "pMDData->hTab" wird gesagt:CXX0017: FEHLER: Symbol "" nicht gefunden.
ich kann damit aber leider nicht so viel anfangen.

STICK.
-
pMDData = (PMDDATA) GetWindowLong (hWnd, 0);Bekommst du hier was gültiges zurück?!
-
wenn ich mir den wert von "pMDData" anschaue, nachdem ich F1 gedrückt habe, wird folgendes ausgegeben:
Name: Wert: pMDData 0x000000000 -hTab CXX0030: Fehler: Ausdruck kann nicht ausgewertet werdenSTICK.
-
Soetwas hatte ich schon fast erwartet - offenbar ist hWnd (ich nehme mal an, dass das einen vernünftigen Wert hat) nicht das Fensterhandle, zu dem du Werte zuvor gespeichert hast...
Das Problem sitzt also wohl an einer anderen Stelle bzw. du liest eben zu einem falschen Fensterhandle den Wert aus

-
das fensterhandle hWnd hat folgenden wert:
hWnd 0x000b07f8 -unused CXX0030: Fehler: Ausdruck kann nicht ausgewertet werdendas heisst meines erachtens, dass hWnd keinen vernünftigen wert hat und damit auch nicht das richtige fensterhandle ist ??

STICK.
p.s.1: wo kann ich dazu informationen im netz finden? da muss doch irgendwo was darüber geschrieben sein.
p.s.2: ich poste hier noch einmal meinen code, vielleicht kann man daran sehen, wo etwas nicht stimmt.global:
typedef struct tagMDDATA { HWND hTab; } MDDATA, *PMDDATA;in der CALLBACK FUNKTION:
PMDDATA pMDData; case WM_CREATE: { SET_OPENGL(hWnd); pMDData = (PMDDATA) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof (MDDATA)); SetWindowLong (hWnd, 0, (long) pMDData); pMDData->hTab = hWnd; } break; case WM_KEYDOWN: { pMDData = (PMDDATA) GetWindowLong (hWnd,0); if (pMDData->hTab == (HWND)lParam && PAD[wParam] == TRUE) MessageBox (pMDData->hTab, "F1 down", "Eingabebox", MB_OK); return 0; } case WM_CLOSE: pMDData = (PMDDATA) GetWindowLong (hWnd, 0); HeapFree (GetProcessHeap (), 0, pMDData); break; case WM_SIZE: pMDData = (PMDDATA) GetWindowLong (hWnd, 0); break;
-
Wie hast du deine Fensterklasse registriert?
nIndex
[in] Specifies the zero-based offset to the value to be set. Valid values are in the range zero through the number of bytes of extra window memory, minus the size of an integer.Bin mir gerade zwar nicht ganz sicher, aber ich denke, es wäre das beste bei Set-/GetWindowLong GWL_USERDATA anstelle von 0 zu verwenden...
-
meine fensterklasse habe ich in etwa so registriert:
// DAS IST DAS FENSTER DER HAUPTANWENDUNG wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)DialogMainWnd; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_3DSHADOW+1); wc.lpszMenuName = MAKEINTRESOURCE(IDM_MYMENU); wc.lpszClassName = MainFrame; wc.hIconSm = NULL; RegisterClassEx(&wc); // DAS IST DAS OPENGL-CHILD-FENSTER wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; wc.lpfnWndProc = (WNDPROC)DialogMDIOpenGL; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_3DSHADOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = g_szChildClassName; wc.hIconSm = NULL; RegisterClassEx(&wc);In der CALLBACK-FUNKTION des HAUPTFENSTERS steht dann irgendwo:
// SO WERDEN DIE OPENGL-CHILD-FENSTER ERZEUGT case WM_COMMAND: switch(LOWORD(wParam)) { case IDM_OPENGL: { HWND hChild; MDICREATESTRUCT cs; ZeroMemory(&cs, sizeof(CREATESTRUCT)); hChild = CreateWindowEx(WS_EX_MDICHILD,g_szChildClassName,buf, WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0,0,400,400,g_hMDIClient,NULL,GetModuleHandle(NULL),&cs); if(!hChild) MessageBox(NULL,"Child creation failed.","Error",MB_ICONEXCLAMATION | MB_OK); } }
-
//------------------------------------------------------------------------- // Callback-Routine vom Windows Childfenster //------------------------------------------------------------------------- LRESULT CALLBACK WndProcMD (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hwndClient, hwndFrame; HDC hdc; PAINTSTRUCT ps; RECT rect; PMDDATA pMDData = NULL; switch (message) { //#################################################################### case WM_CREATE: char szText[64]; wsprintf (szText, "0x%08x", hwnd); MessageBox (hwnd, szText, "Handle:", MB_OK); // nur Testausgabe // Platz für individuelle Daten pMDData = (PMDDATA) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof (MDDATA)); // Handle des Rahmen- und des Client-Fensters festhalten: hwndClient = GetParent (hwnd); hwndFrame = GetParent (hwndClient); break; //#################################################################### case WM_MDIACTIVATE: // Menü einsetzen if (lParam == (LPARAM) hwnd) SendMessage (hwndClient, WM_MDISETMENU, (WPARAM) wData.hMenuMD, (LPARAM) wData.hMenuMDWindow); else SendMessage (hwndClient, WM_MDISETMENU, (WPARAM) wData.hMenuMain, (LPARAM) wData.hMenuMainWindow); DrawMenuBar (hwndFrame); return 0; //#################################################################### case WM_PAINT: hdc = BeginPaint (hwnd, &ps); EndPaint (hwnd, &ps); break; //#################################################################### case WM_CLOSE: if (IDOK != MessageBox (hwnd, TEXT ("Fenster schließen?"), TEXT ("MD Recorder"), MB_ICONQUESTION | MB_OKCANCEL)) return 0; break; // -> weiter mit DefMDIChildProc //#################################################################### case WM_DESTROY: pMDData = (PMDDATA) GetWindowLong (hwnd, 0); HeapFree (GetProcessHeap (), 0, pMDData); return 0; } // Weitergabe an DefMDIChildProc (ersetzt DefWindowProc) return DefMDIChildProc (hwnd, message, wParam, lParam); }Hier ist ein gekuerztes Beispiel, bei case WM_MDIACTIVATE: sieht man die Verwendung vom Childfenster-Handle.
hwndClient und hwndFrame sind static!
Blackbird
-
HALLO BLACKBIRD.
danke für die antwort. ich werde mir das in ruhe anschauen, um es verstehen zu können.
GRÜSSE.
STICK.
-
hallo BLACKBIRD.
ich bin gerade dabei, deinen beispielcode zu verstehen. dabei ist mir die frage gekommen, woher du die informationen betreffs Childfenster-Handle hast? gibts da ein gutes buch dazu oder hast du's im netz gefunden?
ich habe das problem ja wie du weist schon ziemlich lange und würde darum wirklich gerne mal gute literatur dazu lesen, wie ich es beheben kann. mit deinem beispielcode kann ich leider auch nicht so viel anfangen

du schreibst, dass in WM_MDIACTIVATE das Childfenster-Handle verwendet wird. ich sehe aber nicht, dass "pMDData" irgendwo steht?
DANKE.
STICK.
-
Hallo @stick_thai,
... dabei ist mir die frage gekommen, woher du die informationen betreffs Childfenster-Handle hast? gibts da ein gutes buch dazu oder hast du's im netz gefunden?
Um ehrlich zu sein - ich habs vollstaendig aus der MSDN, also der Hilfe zum VC++6.0 "abgeschrieben" und angepasst.
... du schreibst, dass in WM_MDIACTIVATE das Childfenster-Handle verwendet wird. ich sehe aber nicht, dass "pMDData" irgendwo steht?
Du verwendest offenbar einen anderen Ansatz, den ich nicht kenne (oder verstehe). Der Code vom Parent und den Childs muss schon zueinander passen.
Mein Projekt ist aber ziemlich gross, psten laesst sich das nicht.Meine Methode, solche Probleme zu loesen, die WAEHREND eines Projektes auftreten, ist: Parallel zum laufenden Projekt mache ich noch kleine "Hilfs-"projekte auf, in denen ich bestimmte Details naeher untersuche.
Hier waere z.B. ein Mini-Windowsprojekt mit einem Parent und mehreren (zur Laufzeit erstellbaren) Childs angebracht, in denen nur die F1-Taste ausgewertet wird. Entweder durch "Strippen" des vorhandenen Projekts oder besser noch: von Grund auf ein Neues.Mehr faellt mir dazu auch nicht ein.
Blackbird
-
HALLO BLACKBIRD.
ich habe mir jetzt das BUCH von PETZOLD bestellt. vielleicht finde ich darin eine lösung.
deinen vorschlag, ein kleines extra programm zu schreiben, dort das problem zu lösen und dann wieder einzubauen, finde ich gut. ich handhabe das meistens auch so. habe aber bis jetzt noch nicht die zeit gefunden, es für diese problem durchzuführen, da ich parallel noch an einem anderen kleinen programm schreiben muss.
trotzdem danke.
STICK.
-
Probier es mal:
statt mit
SetWindowLong (hWnd, 0, (long) pMDData);
mit
SetWindowLong (hWnd, GWL_USERDATA, (long) pMDData);und statt mit
pMDData = (PMDDATA) GetWindowLong (hWnd,0);
mit
pMDData = (PMDDATA) GetWindowLong (hWnd,GWL_USERDATA);
.Andernfalls würde schon SetWindowLong() versagen, d.h. NULL zurückliefern, da die Fensterklasse, so wie sie in deinem Beispiel definiert wurde, keinen Bereich größer als 0 Bytes für Extradaten bereitstellt.
Walter Zorn