MDI und Callback Funktion
-
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