Timer und PostMessage



  • Hi

    Ich hab mal ein altes Thema von mir aufgegriffen mit dem SplashScreen.
    Eigentlich gehts mir aber nur um die Schliessung der Dialogfelder.

    Ich hab ein Dialog namens HauptDlg und einen Namens TestDlg.
    Eigentlich möchte ich, dass der TestDlg nach 5 Sekunden automatisch geschlossen und erst danach der HauptDlg erscheint.

    Im TestDlg unte OnPaint hab ich den Code SetTimer(0,0,NULL); hinter OnPain() (in der Else-Schleife) hingeschrieben.

    Ok, starte ich das Programm wird TestDlg zwar 5 Sekunden angzeigt, aber danach das ganze Programm beendet, anstatt der HauptDlg geöffnet wird. Wo liegt der Fehler?

    //...
    void CTestprojekt2Dlg::OnPaint() 
    {
    	if (IsIconic())
    	{
    		CPaintDC dc(this); // device context for painting
    
    		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
    
    		// Center icon in client rectangle
    		int cxIcon = GetSystemMetrics(SM_CXICON);
    		int cyIcon = GetSystemMetrics(SM_CYICON);
    		CRect rect;
    		GetClientRect(&rect);
    		int x = (rect.Width() - cxIcon + 1) / 2;
    		int y = (rect.Height() - cyIcon + 1) / 2;
    
    		// Draw the icon
    		dc.DrawIcon(x, y, m_hIcon);
    	}
    	else
    	{
    		CDialog::OnPaint();
    		SetTimer(0,0,NULL);
    
    	}
    }
    
    // The system calls this to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CTestprojekt2Dlg::OnQueryDragIcon()
    {
    	return (HCURSOR) m_hIcon;
    }
    
    void CTestprojekt2Dlg::OnTimer(UINT nIDEvent) 
    {
    	// TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen
    	Sleep(5000);
    	KillTimer(TRUE);
    	CTestprojekt2Dlg::PostMessage(WM_CLOSE);
    	CHauptDlg dlg;
    	dlg.DoModal();
    	CDialog::OnTimer(nIDEvent);
    }
    //....
    

    Hoffe es kann mir jemand helfen?
    Freundliche Grüsse
    Wolf



  • Auf keinen Fall SetTimer in OnPaint verwenden, denn OnPaint wird immer aufgerufen, wenn der Dialoginhalt neu gezeichnet werden muss.
    Z.B. wenn ein fremdes Fenster über deinem Dialog liegt (also verdeckt) und das fremde Fenster geschlossen oder verschoben wird, dann wird in deinem Dialog OnPaint() aufgerufen.

    Leg in deinem Dialog die Funktion OnInitDialog an (über ClassWizard -> WM_INITDIALOG), dort SetTimer rein.

    Alles etwa so hier:

    #define ID_TIMER_5S   1000;
    
    SetTimer(ID_TIMER_5S, 5000, NULL); //nach 5s wird OnTimer aufgerufen!
    
    void CTestprojekt2Dlg::OnTimer(UINT nIDEvent)
    {
     if (ID_TIMER_5S == nIDEvent)
     {
        KillTimer(ID_TIMER_5S);
        EndDialog(0);
     }
    
     CDialog::OnTimer(nIDEvent);
    }
    

    Update:
    Das Erstellen des CHauptDlg am besten nach CTestDlg.DoModal().
    Also irgendwo muss ja stehen ( eventuell in CTestprojekt2::InitInstance() )

    CTestDlg dlg;
    dlg.DoModal();
    dahinter:
    CHauptDlg dlg2;
    dlg2.DoModal();
    


  • Vielen Dank für den Anstoss.

    Ich habs jetzt folgendermassen geschafft:

    In OnInitDialog vom Testprojekt2Dlg:

    //....
    {
    	CDialog::OnInitDialog();
    
    	// Add "About..." menu item to system menu.
    
    	SetTimer(1000, 5000, NULL); /
    //....
    

    In WM_TIMER von Testprojekt2Dlg:

    void CTestprojekt2Dlg::OnTimer(UINT nIDEvent) 
    {
    	// TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen
    
     if (1000 == nIDEvent)
     {
        KillTimer(1000);
    	CTestprojekt2Dlg::PostMessage(WM_CLOSE);
        CHauptDlg *pDlg = new CHauptDlg;
        pDlg->DoModal();
        EndDialog(0);
     }
    
    	CDialog::OnTimer(nIDEvent);
    }
    

    Thx. 🙂
    lG
    Wolf



  • Das ist bestimmt nicht ganz optimal:

    CTestprojekt2Dlg::PostMessage(WM_CLOSE);
      CHauptDlg *pDlg = new CHauptDlg;
      pDlg->DoModal();
      EndDialog(0);
    

    Besser:
    Du hast wahrscheinlich eine dialogbasierende Anwendung ertstellt.
    In der InitInstance() von CTestprojekt2App wird sicherlich dein CTestDlg erstellt und aufgerufen (DoModal).
    Durch EndDialog in OnTimer() bist du nach 5s genau nach diesem DoModal().
    Dort folgt normalerweise die Auswertung ob Dialog mit Ok oder Cancel beendet.
    Davor schreibst du einfach:

    CHauptDlg dlg2;
    dlg2.DoModal();
    


  • Ach so.. Ok das ist auch ne super Idee. Thx.

    Nun ein weiteres Problem:

    In CHauptDlg kann ich net auf AboutDlg zugreifen?

    Ich hab dort geschrieben:

    CAboutDlg dlgAbout;
    dlgAbout.DoModal();
    

    allerdings hab ich auch die Testprojekt2.h und Testprojekt2Dlg.h eingebunden, aber es kommt immer wieder der gleiche Fehler. Woran liegt das?



  • Es wäre wohl besser du "tauscht" die beiden Dialoge.
    Dein CHauptDlg sollte der bei Projekterstellung automatisch angelegte Dialog sein (Name kann bei Projekterstellung geändert werden). Den CTestDlg legst du dann in InitInstance an.

    Ansonsten:
    Die Klasse CAboutDlg wird in der cpp definiert. Eine Möglichkeit ist:
    Datei neu: C++-Header: "AboutDlg.h", dort den Abschnitt "class CAboutDlg : public CDialog ..." hineinkopieren. Dann wo benötigt

    #include "AboutDlg.h"
    

    .



  • Ich gebe zu zum "tauschen" bin ich ein wenig zu faul *g*
    Hab des nun in eine AboutDlg2.h reingepackt.

    Allerdigns hab ich nun zwei AboutDlg-Klassen bei der Klassenansicht. Aber das passt schon, es gibt beim Debug 0 Warnings und 0 Errors. 🙂


Anmelden zum Antworten