CDocument aufräumen und Messagebox ausgeben können
-
Um was für Arten von Fehlern handelt es sich denn? Also in welchen Fällen willst du so eine Message-Box anzeigen?
-
Wir haben das Dokumentensystem umgestellt. Vorher wurden Dateien von einer Netzwerkfreigabe geöffnet. Die wurde derart umgestellt, dass die Dateien jetzt in einer Art Cloud liegen und man nur mit einem Link (https) drauf zugreifen kann. Das Programm läd jetzt in ein temporäres Verzeichnis diese Dateien. Beim Beenden des Programms muss ich dieses Verzeichnis wieder löschen bzw. leeren. Diese Routine signalisiert über Messageboxen, wenn z.B. eine Datei nicht gelöscht werden kann weil sie warum auch immer z.B. noch geöffnet ist. Weder AfxMessageBox noch MessageBox funktionieren, egal ob ich NULL übergebe oder nicht. Es wird direkt nach dem Aufruf der Messagebox eine Exception geworfen. Nehme ich den Aufruf in einen Bereich rein wo das Fenster noch nicht zerstört wird dann geht das komischerweise. Sonst dachte ich auch immer das man Messageboxen immer anzeigen kann.
-
Was für eine Exception wird denn da geworfen?
Und zeige mal den Code.
-
So, ich konnte jetzt feststellen, dass es eine CFileException in einer DLL war, die ich im Programm benutzen muss. Das ist fremder Code, den ich nicht kenne. Vermutlich bewirkt der Aufruf das Löschen einer Datei, die schon gelöscht ist. Jetzt hab ich mal testweise in den Konstruktor eine Messagebox gesetzt:
CMyAppDoc::~CMyAppDoc() { CMyAppDoc::Speichere_Daten(Datendatei); AfxMessageBox(_T("Test")); }
Diese wird nicht aufgerufen.
-
Naja... die einfachste und beste Lösung wäre vermutlich das Löschen im
WM_CLOSE
Handler des top-level Fensters zu machen. Dort kannst du noch ganz normal die MessageBox anzeigen - und wenn du willst sogar das Schliessen des Fensters verhindern (indem du dieWM_CLOSE
Message ignorierst).Alternativ könntest du einen Hilfs-Thread starten der die Message-Box anzeigt, und dann auf die Beendigung des Hilfs-Threads warten. Das geht wirklich überall
-
@hustbaer sagte in CDocument aufräumen und Messagebox ausgeben können:
Naja... die einfachste und beste Lösung wäre vermutlich das Löschen im
WM_CLOSE
Handler des top-level Fensters zu machen. Dort kannst du noch ganz normal die MessageBox anzeigen - und wenn du willst sogar das Schliessen des Fensters verhindern (indem du dieWM_CLOSE
Message ignorierst).Alternativ könntest du einen Hilfs-Thread starten der die Message-Box anzeigt, und dann auf die Beendigung des Hilfs-Threads warten. Das geht wirklich überall
Der erste Ansatz war das, was mir auch gleich eingefallen ist. Hat nicht funktioniert. Gleiches Problem. Ich denke aber ich hab das Problem einkreisen können. Die Routinen, die ich für das Aufräumen brauche, kommen aus einer MFC-Erweiterungs-DLL. Das Problem scheint zu sein, dass zum Zeitpunkt des Aufrufs die DLL schon entladen ist und es deshalb knallt. Warum das aber jetzt in dem Beispiel von vorhin nicht klappt weiß ich auch nicht. Das klappt aber grundsätzlich nicht.
-
Wie, gleiches Problem? Du meinst du kannst in
WM_CLOSE
keineMessageBox
anzeigen? Doch, das geht. Sicher. Ganz sicher.EDIT: Nur sicherheitshalber, du musst natürlich zwei Dinge beachten:
- Du musst
ON_WM_CLOSE()
in der Message-Map haben
BEGIN_MESSAGE_MAP(CMyWindow, CWnd) //{{AFX_MSG_MAP(CMyWindow) ON_WM_CLOSE() //}}AFX_MSG_MAP END_MESSAGE_MAP()
- Du solltest in deiner
CMyWindow::OnClose
Funktion dieMessageBox
anzeigen bevor du dieOnClose
Funktion der Basisklasse aufrufst.
/EDIT
Die Routinen, die ich für das Aufräumen brauche, kommen aus einer MFC-Erweiterungs-DLL. Das Problem scheint zu sein, dass zum Zeitpunkt des Aufrufs die DLL schon entladen ist und es deshalb knallt.
Wieso sollte in
WM_CLOSE
des top-level Fensters schon etwas entladen sein? Verstehe ich nicht.
- Du musst
-
@hustbaer sagte in CDocument aufräumen und Messagebox ausgeben können:
- Du solltest in deiner
CMyWindow::OnClose
Funktion dieMessageBox
anzeigen bevor du dieOnClose
Funktion der Basisklasse aufrufst.
Die Routinen, die ich für das Aufräumen brauche, kommen aus einer MFC-Erweiterungs-DLL. Das Problem scheint zu sein, dass zum Zeitpunkt des Aufrufs die DLL schon entladen ist und es deshalb knallt.
Wieso sollte in
WM_CLOSE
des top-level Fensters schon etwas entladen sein? Verstehe ich nicht.Das erste ist klar und das zweite verstehe ich auch nicht. Folgendes hab ich jetzt und es wird nicht angesprungen:
BEGIN_MESSAGE_MAP(CMFCApplication12View, CFormView) ON_WM_CONTEXTMENU() ON_WM_RBUTTONUP() ON_WM_CLOSE() END_MESSAGE_MAP() void CMFCApplication12View::OnClose() { // TODO: Fügen Sie hier Ihren Meldungsbehandlungscode ein, und/oder benutzen Sie den Standard. AfxMessageBox(_T("Test")); CFormView::OnClose(); }
Wenn ich einen Breakpoint in die OnClose setzte wird das nicht angesprungen. Hingegen:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx) ON_WM_CREATE() ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook) ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook) ON_COMMAND(ID_VIEW_CAPTION_BAR, &CMainFrame::OnViewCaptionBar) ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTION_BAR, &CMainFrame::OnUpdateViewCaptionBar) ON_COMMAND(ID_TOOLS_OPTIONS, &CMainFrame::OnOptions) ON_WM_CLOSE() END_MESSAGE_MAP() void CMainFrame::OnClose() { // TODO: Fügen Sie hier Ihren Meldungsbehandlungscode ein, und/oder benutzen Sie den Standard. AfxMessageBox(_T("Test")); CFrameWndEx::OnClose(); }
funktioniert.
- Du solltest in deiner
-
Dass es in der View nicht geht ist klar, da die View kein
WM_CLOSE
bekommt. DieWM_CLOSE
Message teilt dem top-level Fenster mit dass jemand es bitte gerne schliessen möchte. z.B. wenn man auf den "X" Button klickt oder Alt-F4 drückt. Das Fenster muss dieser Bitte nicht nachkommen. Wenn es der Bitte nachkommen möchte, dann zerstört es sich imWM_CLOSE
Handler selbst indem esDestroyWindow
aufruft. Im MFC Framework wird das gemacht indem man dieOnClose
Funktion der Basisklasse aufruft, also z.B.CFrameWndEx::OnClose()
. Duch denDestroyWindow
Aufruf werden dann auch alle Child-Fenster mit zerstört.Daher würde es auch keinen Sinn machen
WM_CLOSE
an ein Child-Fenster zu schicken. Die Entscheidung trifft immer das top-level Fenster, das Child-Fenster hat da nix mitzureden.
-
@hustbaer
Vielen Dank, so direkt war mir das nicht klar. Dachte immer das der Weg über die View zum Mainframe geht. Aber noch mal ne Frage zur Messagebox. Was wird mindestens benötigt um die anzuzeigen? Wenn das View-Objekt nicht existiert müsste es ja noch gehen. Wie sieht es da mit Mainframe und Anwendungsobjekt aus?
-
@AndyDD
Es wird eigentlich überhaupt nichts benötigt, zumindest nicht beiMessageBox
aus der WINAPI. Was derAfxMessageBox
Aufruf genau braucht kann ich nur vermuten, vielleicht wird da das Parent-Fensterhandle über das Hauptfenster der Anwendung geholt. Wenn das dann schon zerstört wurde (also das komplette Objekt, nicht nur die Windows-Resourcen), dann geht einCWnd->GetSafeHwnd()
Aufruf natürlich in die Hose.
Im Grunde kann einAfxMessageBox
Aufruf nicht wesentlich viel mehr machen als einMessageBox
Aufruf. Wenn das so ein Timing Problem und man nicht genau feststellen kann, welches Objekt wann noch lebt, dann istMessageBox
mit 0 als Parent vielleicht eine Lösung.
-
Ich bin bei meiner Aussage auch von der Standard-WinAPI Funktion MessageBox ausgegangen und nicht einer speziellen Funktion.
-
@Th69
Jau, hab ich auch grad gesehen, dass du das schon vor 2 Tagen vorgeschlagen hast. Ist offensichtlich auch am TE vorbeigegangen.
-
Ich habe sowohl
MessageBox
mit NULL undAfxMessageBox
probiert im Destructor der Dokumentenklasse aufzurufen. Bei letzterem kommt zumindest noch ein Warnton, bei ersterm passiert gar nichts. Ich hab das schon hinbekommen Messageboxen beim Programmstart anzuzeigen, ohne das ein Fenster sichtbar war. Jedoch heißt das ja nicht, dass davon nicht schon eine Instanz existieren kann.
-
Ich weiss nicht ob es in allen Situationen möglich ist eine Message-Box anzuzeigen. Mag sein dass es da ein paar Sonderfälle gibt wo es nicht geht. Kann auch sein dass es vom OS aus ginge aber die MFC es nicht in allen Situationen verkraftet.
Das Anzeigen einer Message-Box führt ja dazu dass alle möglichen Messages "gesendet" werden (beim Erzeugen/Anzeigen des Message-Box Fensters) und danach wird eine Message-Schleife für das Message-Box Fenster ausgeführt. Dabei wird vermutlich auch das gerade aktive Fenster eine Message bekommen, nämlich z.B. dass es jetzt nicht mehr aktiv ist. Was passiert wenn z.B. gerade eine
WM_DESTROY
Handler für dieses Fenster "aktiv" ist (also wenn manMessageBox
aus demWM_DESTROY
heraus aufruft), weiss ich nicht. Jetzt nur als ein Beispiel wo ich mir vorstellen könnte dass es evtl. Probleme gibt. Hab's aber nicht ausprobiert, kann auch gut sein dass es in dem beschriebenen Fall eh funktioniert.
-
Wenn noch eine WM_QUIT Message in der Queue ist, beendet sich die MessageBox automagisch.
PostQuitMessage(0); MessageBox(NULL, TEXT("Text"), TEXT("Titel"), MB_OK); // Wird nicht angezeigt
-
@servus_ sagte in CDocument aufräumen und Messagebox ausgeben können:
Wenn noch eine WM_QUIT Message in der Queue ist, beendet sich die MessageBox automagisch.
PostQuitMessage(0); MessageBox(NULL, TEXT("Text"), TEXT("Titel"), MB_OK); // Wird nicht angezeigt
Ich glaub sowas wird wohl der Grund sein. Wie gesagt ich habe das jetzt in CMainFrame::OnDestroy() platziert und da funktioniert es zumindest so, wie ich es brauche.