Modales Popup-Window

Zurück Zum Inhaltsverzeichnis Weiter

Fangen wir mit der Erklärung des Begriffs 'modales Popup-Window' an. Was ein Popup-Window ist sollte Ihnen in der Zwischenzeit geläufig sein. Ein Popup-Window ist ein untergeordnetes Fensters das sich frei auf dem Desktop verschieben lässt. Alle Eigenschaften die für ein normales Popup-Window gelten, gelten generell auch für ein modales Popup-Window. Der Unterschied zwischen den beiden Typen liegt in der Verarbeitung der Nachrichten. Wenn Sie ein normales Popup-Window erstellen können Sie trotzdem mit dem Hauptfenster der Anwendung arbeiten, d.h. Sie können es z.B. verschieben oder auch in seiner Größe verändern. Erstellen Sie dagegen ein modales Popup-Window, so wird die Nachrichtenbearbeitung für das Hauptfenster solange ausgesetzt, bis die Modalität des Popup-Window wieder aufgehoben wird. Das 'Wie' und 'Wann' kommt gleich. Durch dieses Verhalten eignen sich modale Popup-Window zum Beispiel sehr gut um beim Programmstart ein Logo oder die Lizenzbedingungen anzuzeigen. Solche Fenster werden auch als Splash-Screens bezeichnet. Die MFC bietet für die Anzeige von Logos zwar auch eine Komponente an, diese besitzt jedoch einen eingeschränkten Leistungsumfang.

Um ein Fenster in den modalen Zustand zu versetzen wird nach der Erstellung des Fensters dessen CWnd-Methode RunModalLoop(...) aufgerufen. Die Methode kehrt erst dann wieder zurück, wenn die Modalität des Fensters beendet wird.

Standardmäßig sendet die MFC während der Modalität des Fensters zyklisch die Nachricht WM_KICKIDLE an das Fenster. Wollen Sie in Ihrer Anwendung auf diese Nachricht reagieren, so müssen Sie die Nachricht von Hand in die Nachrichtentabelle des Fensters mittels des Makros ON_MESSAGE(...) eintragen (was wir gleich auch tun werden). Der Klassen-Assistent unterstützt diese Nachricht nicht.

Um die Modalität des Fenster zu beenden, rufen Sie in der OnClose(...) Methode des Fensters die Methode EndModalLoop(...) auf.

ACHTUNG! Vergessen Sie in der OnClose(...) Methode den Aufruf der Methode EndModalLoop(...), so wird zwar das Popup-Window geschlossen, die RunModalLoop(...) Methode jedoch trotzdem nicht verlassen. Sie haben damit ein Programm nicht mehr regulär beendet werden kann!
Es gibt noch eine weitere Methode ContinueModal(...) mit der Sie testen können, ob sich das Fenster noch im modalen Zustand befindet. Wenn Sie diese Methode überschreiben sollten Sie trotzdem immer die Basismethode aufrufen und auch deren Returnwert zurückliefern. Liefert die überschriebene Methode den Wert '0' zurück, so erhalten Sie im Debug-Fall eine Assert-Fehler.

Sehen wir uns nun einmal an wie mit Hilfe eines modalen Popup-Window ein Splash-Screen dargestellt werden kann. Das Popup-Window wird in der OnCreate(...) Methode des Rahmenfensters zunächst genauso erstellt, wie Sie es in der Lektion Untergeordnete Fenster erfahren haben. Direkt nach der Erstellung wird dann die Methode RunModalLoop(...) des Popup-Window aufgerufen.

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    ....

    m_CWndModal.Create(NULL,"My splash!",WS_VISIBLE|WS_SYSMENU,CRect(0,0,0,0),this,0,NULL);
    m_CWndModal.RunModalLoop(MLF_NOIDLEMSG);

    ....
}

Soll die WM_KICKIDLE Nachricht verarbeitet werden, müssen Sie die Nachrichtentabelle des Popup-Window von Hand um den entsprechenden Eintrag erweitern.

BEGIN_MESSAGE_MAP(CWndModal, CWnd)
    //{{AFX_MSG_MAP(CWndModal)
    ON_WM_CLOSE()
    ON_WM_PAINT()
    //}}AFX_MSG_MAP
    ON_MESSAGE(WM_KICKIDLE,OnKickIdle)
END_MESSAGE_MAP()

Als nächstes gilt es den Nachrichtenverarbeiter für diese Nachricht zu definieren. Im Beispiel ist dies Methode OnKickIdle(...). Der Splash-Screen im Beispiel soll 3 Sekunden lang dargestellt werden und sich danach selbständig schließen. Während der Splash-Screen angezeigt wird gibt dieser in seiner Titelzeile die aktuelle Uhrzeit aus.

LONG CWndModal::OnKickIdle(UINT, LONG lCount)
{
    // Nur jedes 4096-mal Uhrzeit ausgeben
    if ((lCount&0xFFFL) == 0)
    {
        static char acBuffer[15];
        SYSTEMTIME strSysTime;
        GetLocalTime(&strSysTime);
        wsprintf(acBuffer,"%02d:%02d:%02d",strSysTime.wHour,
        strSysTime.wMinute, strSysTime.wSecond);
        SetWindowText(acBuffer);
    }
   
// Falls seit dem Start mehr als 3 sec vergangen
    if (GetTickCount()-m_dwStartTime >= 3000)
        // Fenster schließen, fuehrt zum Aufruf
        // der OnClose(...) Methode!

        PostMessage(WM_CLOSE,0,0);
    return 1L;
}

So, fehlt zum Schluss nur noch das Beenden der Modalität des Splash-Screen. In der OnKickIdle(...) Methode wird nach 3 Sekunden durch den Aufruf der Methode PostMessage(...) eine WM_CLOSE Nachricht abgesandt. Also fügen wird über den Klassen-Assistenten den entsprechenden Nachrichtenbearbeiter OnClose(...) zum Fenster hinzu. In der Methode OnClose(...) braucht jetzt nur noch die Methode EndModalLoop(...) aufgerufen werden.

void CWndModal::OnClose()
{
    // TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen....

    // Ganz wichtig!!!
    // Zuerst modalen Zustand beenden
    EndModalLoop(0);
    // und dann Fenster schliessen
    CWnd::OnClose();
}

Und fertig ist unser Splash-Screen, wenigsten im Prinzip. In der Praxis werden Sie selbstverständlich zum modalen Popup-Window noch eine OnPaint(...) hinzufügen müssen. Sie wollen ja schließlich Ihr Firmen-Logo dort anziegen.

Das fertige Beispiel zu diesem Thema finden Sie unter 03EPMMFC\ModalWnd.

Zurück Zum Inhaltsverzeichnis Weiter


Copyright © 2004

Senden Sie Emails mit Fragen oder Kommentaren zu dieser Website an: mailto:info@cpp-tutor.de
 Wolfgang Schröder, Lerchenweg 23, D-72805 Lichtenstein. Tel: +49 7129 6470