Modales Popup-Window
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.
|