Dialogklasse schreiben



  • Hallo,

    ich versuche gerade, eine kleine Klassenbibliothek zu schreiben, welche es mir erlaubt, eine Dialoganwendung zu initialisieren und (mehrere) Dialoginstanzen einzuhängen.

    Dazu schrieb ich eine Klasse Dialog und eine Klasse Application, letztere stellt quasi die Hauptschleife der Anwendung dar.

    Ich habe jetzt nur das Problem, dass das Message Handling offenbar nicht korrekt funktioniert. Der Dialog wird nicht angezeigt und es passiert nichts. Der WinAPI Befehl GetMessage scheint zu blocken, zumindest verschwindet mein Single-Step-Debugger immer im Niavana, wenn ich drübersteppen will.

    Ich möchte hier nicht mit dem ganzen Code langweilen, daher nur die relevanten Parts, in denen ich das Problem vermute:

    Zuerst wird eine Dialog-Instanz erstellt und .Create darauf aufgerufen:

    BOOL Dialog::Create() {
    	// Create dialog
    	this->handle = CreateDialogParam(inst, MAKEINTRESOURCE(GetDlgResourceName()), 0, (DLGPROC)Dialog::DlgProc, 0);
    	Dialog::msgRec.push_back(this);
    
    	ShowWindow(this->handle, 0);
    
    	return TRUE;
    }
    

    Wie man sieht, speichert jede Klasseninstanz das HWND-Handle als Attribut. Dann gibt es noch einen statischen STL-Vektor, in der ich nochmal die Instanz ablege. Diese wird jetzt in der statischen Methode Dialog::DlgProc gebraucht, die ja oben in CreateDialogParam verankert wird:

    INT_PTR CALLBACK Dialog::DlgProc(HWND dlg, UINT msg, WPARAM wp, LPARAM lp) {
    	for(unsigned int i = 0; i < msgRec.size(); i++) {
    		if(msgRec[i]->GetHandle() == dlg) {
    			return msgRec[i]->ProcessMessage(msg, wp, lp);
    		}
    	}
    	return FALSE;
    }
    

    Was ich hier versuche, ist denke ich klar: Ich iteriere über die erstellten Dialoge und schau, ob die eingegangene Nachricht für die jeweilige Dialog-Instanz ist. Wenn ja, wird für die Instanz ProcessMessage aufgerufen. Somit hat jede Klasseninstanz ihre eigene Dialog-Proc.

    Meine Vermutung ist, dass sich das nun irgendwie mit meiner Hauptschleife in der Klasse Application beist. Diese hat zwei relevante Methoden:

    RegisterDialog(Dialog*) nimmt eine Dialoginstanz entgegen und speichert sie schlicht in einen STL-Vektor:

    void Application::RegisterDialog(Dialog *dlg) {
    	this->dialogs.push_back(dlg);
    }
    

    In Run() ist nun die Hauptschleife implementiert. Diese versucht, Nachrichten für die Dialoge herauszufiltern und entsprechend weiterzuleiten. Wie oben beschrieben klappt das aber nicht.

    BOOL r;
    	MSG msg;
    	while((r = GetMessage(&msg, 0, 0, 0)) != 0) {
    
    		if(r < 0)
    			return false;
    
    		bool found = false;
    		for(it = this->dialogs.begin(); it != this->dialogs.end(); it++) {
    
    			if(IsDialogMessage((*it)->GetHandle(), &msg))
    				found = true;
    		}
    
    		if(!found) {
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    
    	}
    	return true;
    

    Dialog::GetHandle liefert das HWND der jeweiligen Dialog-Instanz.

    Kann mir jemand helfen? Ich vermute, ein zentrales Konzept missverstanden zu haben. 🙄



  • Lasse soviel wie möglich mit WinApi das System machen. Du kriegst die Dialog-Handles als Returnwert. Der Rest könnte (für nicht-modale Dialoge) so aussehen:

    while (GetMessage(&msg,0,0,0))
    {
       if(!IsDialogMessage(hDlg1,&msg) &
          !IsDialogMessage(hDlg2,&msg) &
          !IsDialogMessage(hDlg3,&msg) &
          !IsDialogMessage(hDlg4,&msg) &
          !IsDialogMessage(hDlg5,&msg))
          {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
          }
    }
    

    Wo und wie du die Dialoge einrichtest, bleibt dir überlassen.



  • Hi,

    genau so mach ich das doch, nur in der Schleife?
    Verstehe deine Antwort nicht.


  • Mod

    Was soll der ShowWindow(..., 0)?

    Da kann doch nichts angezeigt werden. Entweder dem Template ein WS_VISIBLE geben oder SW_NORMAL auch verwenden.

    Schlechter Stil, wenn man keine WinAPI defines verwendet.
    Blockieren kan da nicts wenn das alles aus einem Thread aufgerufen wird.



  • Ja, das war das Problem, danke.


Anmelden zum Antworten