Speichern von Dokument abbrechen



  • Hallo zusammen!

    Mein Problem:

    Bevor in meiner MDI-Anwendung ein Dokument gespeichert wird, muss ich prüfen, ob nicht bereits ein Dokument mit dem selben Namen geöffnet ist. Ist dies der Fall soll das speichern abgebrochen werden.

    Soweit kein Problem. Gelöst hab ich das ganze so:

    BOOL CxxxDoc::OnSaveDocument(LPCTSTR lpszPathName)
      {
      CString fileName = lpszPathName;
    
      // Dateinamen aus Pfad herausfiltern
      fileName = fileName.Right(fileName.GetLength() - fileName.ReverseFind('\\') - 1);
    
      // Prüfen, ob bereits Dokument mit selben Namen offen ist
      // ...
    
      if (bAlreadyOpen)
        {
        AfxMessageBox("Dokument mit selben Namen bereits geöffnet!");
        return FALSE;
        }
    
      return CDocument::OnSaveDocument(lpszPathName))
      }
    

    Das funktioniert soweit, nur bin ich gerade auf folgendes Problem gestoßen, welches ich am besten mit einem kleinen Szenario beschreibe:

    - Dok1.xxx existiert an 2 Orten (zB. C:\Dok1.xxx und C:\foo\Dok1.xxx)

    -> C:\Dok1.xxx wird geöffnet
    -> Ein neues Dokument wird geöffnet
    -> Benutzer möchte neues Dokument unter C:\foo\Dok1.xxx speichern
    -> Natürlich wird er gefragt, ob die Datei überschrieben werden soll (mit Ja bestätigt)
    -> Oben angeführter Code wird ausgeführt und meldet, dass bereits ein Dokument mit diesem Namen offen ist
    -> OnSaveDocument wird mit FALSE abgebrochen und Dokument wird natürlich nicht gespeichert
    -> !!!! C:\foo\Dok1.xxx ist von der Festplatte verschwunden, da das überschrieben ja gestattet wurde, danach das speichern jedoch abgebrochen wurde !!!!

    Dieser Zustand ist natürlich absolut inakzeptabel, weshalb ich hier nun nachfrage, wie man das abbrechen des Speicherns besser gestallten könnte, damit die alte Datei in so einem Fall nicht mehr gelöscht wird?

    danke, mfg



  • Kannst du nicht mit totalen Pfaden statt mit Dateinamen arbeiten? 🙂



  • Nulltens: Ist das ein theoretisches Szenario oder hast du das praktisch ausprobiert?

    Erstens: Das Überschreiben der Datei passiert erst in der CDocument::OnSaveDocument() - wenn du den Vorgang bereits vorher abbrichst, passiert mit deinen Daten überhaupt nichts.

    Zweitens: Normalerweise sollte diese Überprüfung, ob ein Dokument schon offen ist, den gesamten Pfad mit einbeziehen (die beste Lösung ist, die Datei exklusiv zu öffnen, während du sie verwendest, dann wird der Versuch, sie zu überschreiben, direkt erkannt). Wenn die C:\Dok1.xxx Probleme macht, wenn du woanders eine gleichnamige Datei anlegen willst, ist deine Überprüfung fehlerhaft.



  • estartu schrieb:

    Kannst du nicht mit totalen Pfaden statt mit Dateinamen arbeiten? 🙂

    Nein, kann ich nicht. Im Programm wird ein Baum mit allen offenen Dokumenten angezeigt (Dateiname ist immer der Root-Knoten).
    Hier kommt es dann im weitern verlauf zu Problemen, wenn mehrere Dokumente mit dem selben Namen geöffnet sind.

    CStoll schrieb:

    Nulltens: Ist das ein theoretisches Szenario oder hast du das praktisch ausprobiert?

    Das hab ich so ausprobiert, bzw. ist es mir eher zufällig aufgefallen.

    CStoll schrieb:

    Erstens: Das Überschreiben der Datei passiert erst in der CDocument::OnSaveDocument() - wenn du den Vorgang bereits vorher abbrichst, passiert mit deinen Daten überhaupt nichts.

    Davon bin ich anfangs auch ausgegangen. Leider wird die Datei trotzdem gelöscht, ohne dass CDocument::OnSaveDocument aufgerufen wird...

    CStoll schrieb:

    Zweitens: Normalerweise sollte diese Überprüfung, ob ein Dokument schon offen ist, den gesamten Pfad mit einbeziehen (die beste Lösung ist, die Datei exklusiv zu öffnen, während du sie verwendest, dann wird der Versuch, sie zu überschreiben, direkt erkannt). Wenn die C:\Dok1.xxx Probleme macht, wenn du woanders eine gleichnamige Datei anlegen willst, ist deine Überprüfung fehlerhaft.

    Wie oben bereits erwähnt kann ich nicht den ganzen Pfad miteinbeziehen, da schlicht und einfach keine 2 Dokumente mit dem selben Namen geöffnet sein dürfen (egal, wo sie gespeichert sind).
    Das exklusiv öffnen hilft mir hier auch nichts, da die 2. Datei, welche überschrieben bzw. gelöscht wird, ja nicht geöffnet ist (oder hab ich dich nicht richtig verstanden?)...

    Bin übrigens gerade beim Debuggen auf jenen Code in der MFC gestoßen, welcher das löschen auslöst:

    doccore.cpp
    Methode BOOL CDocument::DoSave(LPCTSTR lpszPathName, BOOL bReplace)
    Zeile 329 - 346:

    if (!OnSaveDocument(newName))
    	{
    		if (lpszPathName == NULL)
    		{
    			// be sure to delete the file
    			TRY
    			{
    				CFile::Remove(newName);
    			}
    			CATCH_ALL(e)
    			{
    				TRACE(traceAppMsg, 0, "Warning: failed to delete file after failed SaveAs.\n");
    				DELETE_EXCEPTION(e);
    			}
    			END_CATCH_ALL
    		}
    		return FALSE;
    	}
    

    Somit ist klar, dass das gewählte File gelöscht wird, wenn der Speichervorgang fehlschlägt.
    Dann werde ich wohl DoSave überschreiben müssen...

    Werde mich da mal probieren und hier wieder melden!



  • Gesagt ... getan:

    DoSave überschrieben und nun funzt das ganze wie ich es mir vorstelle!

    danke, mfg


Anmelden zum Antworten