Aus einer Dialogbox ein Fenster erzeugen?
-
Hallo liebe C++ Gemeinde!
Ich habe mit 2 weiteren Schülern einen Tetris-Clone unter Verwendung der Win32-API mit C++ programmiert.
Nach einem großem Beta-Test (Tetris selbst läuft einwandfrei, mir machen eigentlich nur die Controls Probleme) kam das große Dilemma - Tastaturbelegung...
Der User sollte praktisch jede Taste frei belegen können, am besten bequem per Dialog (die Eingaben werden gespeichert).
Kein Problem dachte ich mir (mit dem Petzold unter dem Arm) und schnell eine Dialogbox erzeugt... mit der Ernüchterung das Tastaturabfragen nicht möglich sind (..hier in einer FAQ gelesen).
Die Idee, aus einer Dialogbox heraus ein Fenster zu erzeugen um damit den Keycode zu holen, erschien mir nicht abwegig. Nun habe ich das Problem das ich kein Fenster öffnen kann, gilt das generell bei Verwendung der Dialogbox?
Der Ablauf ist folgender:
1. Im Spielleerlauf klickt der User ins Menü und wählt den Optionen-Eintrag
2. Es öffnet sich eine Dialogbox, darauf befindet sich
- ein Button
- ein Textfeld
3. Klickt der User auf den Button erscheint ein Fenster "Bitte Taste drücken"
um die individuelle Tastenbelegung für z.B. "Bewege Baustein nach links"
anzupassen.
4. Das Fenster schließt sich wieder und die Eingabe wird übernommen und im
Textfeld sichtbar gemacht.Naja, das wäre meine Wunschvorstellung...
Derzeit ist in C++ so umgesetzt:
1. In der _tWinMain wird das Anwendungsfenster geöffnet. Dort werden (wie üblich) alle Nachrichten ausgewertet (und der entsprechende Menüeintrag behandelt - OPTIONEN).2. Der User klickt jetzt auf des Menü "Optionen" und es öffnet sich eine Dialogbox.
case IDM_OPTIONEN: if( modus==SPIELMODUS_TITEL) { DialogBox(hInst, (LPCTSTR)IDD_OPTIONEN, hWnd, (DLGPROC)OptionSettings); InvalidateRect( hWnd, NULL, FALSE ); } break;
2. Danach springt er in den Handler der Box.
BTW: Ich hab jetzt einfach alles mal vor der eigentlichen Nachrichtenbehandlung gesteckt, davor war die Initialisierung des Fensters in WM_INIT...// Message handler für Options-Dialog LRESULT CALLBACK OptionSettings(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; HWND hwndOpt; WNDCLASSEX winOpt; char szClassNamePresskey[] = "Taste"; winOpt.hInstance = hInst; winOpt.lpszClassName = szClassNamePresskey; winOpt.lpfnWndProc = (WNDPROC)WndProc; winOpt.style = CS_DBLCLKS; winOpt.cbSize = sizeof(WNDCLASSEX); winOpt.hIcon = NULL; winOpt.hIconSm = NULL; winOpt.hCursor = LoadCursor(NULL, IDC_ARROW); winOpt.lpszMenuName = NULL; winOpt.cbClsExtra = 0; winOpt.cbWndExtra = 0; winOpt.hbrBackground = (HBRUSH)COLOR_BTNSHADOW; if(!RegisterClassEx(&winOpt)) return 0; wndOpt = CreateWindow ( szClassNamePresskey, TEXT ("Bitte Taste druecken..."), WS_CHILD | WS_DLGFRAME, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hDlg, NULL, hInst, NULL ); ShowWindow(hwndOpt,SW_SHOWNORMAL); UpdateWindow(hwndOpt); switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch (wmId) { case IDOK: // ToDo // ... speichern der Einstellungen EndDialog(hDlg, LOWORD(wParam)); return TRUE; case IDCANCEL: EndDialog(hDlg, LOWORD(wParam)); return TRUE; case IDC_OPT_BTN_LINKS: // Hier sollte das Fenster für die Tastatur-Abfrage // aufgerufen werden und die eingebene Taste an ein // static char geben break; case IDDEFAULT: break; } break; } return FALSE; }
3. Die Routine für das Fenster ist derzeit noch leer, es geht ja noch nicht mal das Fenster auf...
LRESULT CALLBACK WndPresskey(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // Alles noch leer, zuerst muss mal das Fenster aufgehen :-( switch (message) { case WM_SIZE: break; case WM_LBUTTONDOWN: break; case WM_PAINT: break; } return DefWindowProc(hWnd, message, wParam, lParam); }
Gibt es Abhilfe?
Viele Grüße
Torsten
-
Das kann ja nicht klappen, wenn du die Initialisierung des Fensters vor die Nachrichtenbearbeitung packst.
Dann wird das Fenster bei JEDER Nachricht neu erstellt.
Da die Fensterklasse aber bereits nach der ersten Nachricht registriert ist, müsste RegisterClassEx abbrechen und dazu führen, dass der Dialog auf gar nichts mehr reagiert.Sowas musst du in WM_INITDIALOG erledigen.
Dann kannst du einfach bei WM_COMMAND, wenn ein Button gedrückt wurde, das Fenster mit CreateWindow erstellen und anzeigen.
Bei der Nachrichtenbehandlung des neuen kleinen Fensters rufst du dann sowas in der Art auf:case WM_CREATE: EnableWindow(GetParent(hWnd), FALSE); return 0; case WM_DESTROY: EnableWindow(GetParent(hWnd), TRUE); return 0;
-
Vielen Dank!
Manchmal sieht man den Wald vor lauter Bäumen nicht... *grins*
Grüße
Torsten
-
Das Hot Key Control ist für dich vielleicht auch noch ganz interessant