SaveDialog gecancelt/geschlossen?



  • Seltsam, für die Button zum Canceln uns Schließen der SaveDialoge gibt es keine Methoden - nur das OnClose, das mir hier aber nichts nützt. Konnte auch in den Threads/FAQ nichts dazu finden.

    Ich möchte feststellen können, wenn ein Savedialog via Cancel-Button oder Close-Button geschlossen wurde, also ohne daß der file gespeichert wurde. In dem Fall bleibt die Datei ja ggf. modified. Ein Schließen-Versuch des Fensters/der App soll also in solchen Fällen (wieder) eine Message-Anfrage bringen.

    Wer weiß Rat? (Meine App (Maltool :p ) ist dank eurer großartigen Hilfe und gar mancher Knobelkur in der ersten Stufe mal fertig, hab aber keine Lust, das Toolchen mit solchen Halbheiten weiter zu geben. Auch OnCloseQuery will ich fachlich richtig aufbauen können).



  • Du willst wissen, ob der Button "Speichern gedrückt wurde? Dann musst Du bei SaveDialog->Execute() den Rückgabewert auswerten.

    Phips



  • [ ]Ja, ich habe in der hilfe zum Thema TSaveDialog::Execute() nachgeschlagen.

    -junix



  • *Well*! Dank euch. Ihr helft super schnell und super präzise! Etwas [um][weiter]denken, und es scheint zu gehen:

    if (SaveDialog->Execute() == true)
        {
        Image->Picture->SaveToFile(SaveDialog->FileName);
        BildModified = false;
        }
      else
        BildModified = true;
      // BildModified wird im OnCloseQuery nur dann richtig ausgewertet,
      // wenn ich nachfolgende Messages aufrufe.
      if (BildModified == true)
        ShowMessage("BildModified = true");
      else if (BildModified == false)
        ShowMessage("BildModified = false");
    

    Offenbar erfährt OnCloseQuery nur aufgrund der Message, welchen Zustand BildModified hat. Die bool-Variable ist aber privat declariert, deren aktueller Wert solte überall innerhalb der Unit bekannt sein. Also hier steh ich total auf dem Schlauch. Was vergleichbares hatte ich noch nicht. Wo ist mein Denkfehler?

    Hier auch mal das OnCloseQuery:

    void __fastcall TPixi::FormCloseQuery(TObject *Sender, bool &CanClose)
    {
      if (BildModified == false)
       CanClose = true;
        else
        {
        CanClose = false;
        int cm;
            cm = MessageDlg("Bild wurde geändert.\nSpeichern vor dem Schließen des Fensters?",
                mtConfirmation, TMsgDlgButtons() << mbYes << mbNo <<
                mbCancel,0);
        if (cm == mrYes)
          FileSaveAsClick(Sender);
          else if (cm == mrNo)
            CanClose = true;
        else if (cm == mrCancel)
          CanClose = false;
      }
    }
    


  • Es bleibt makaber. Nach Debugger ist erst mal alles klar. Beim Verlassen der SaveAs-Function ist BildModified = false. (Hab für den Test gespeichert, es ist also richtig).

    Dann geht er ins OnCloseQuery rein, liest die erste Bedingung:

    if (BildModified == false)

    und geht ans Ende der Function. Der Cursor über "BildModified" sagt aber "false". Er sagt zu "CanClose" allerdings auch "false" (obwohl ich hier "true" explizit befehle).

    Wenn ich den Cursor jetzt wieder an den Functionsanfang setz und F4 benutz (gehe zu Cursorposition), wird die App sofort geschlossen, wie es in der Testsituation sein soll.

    Warum kann das nicht klappen, wenn ich den Cursor nicht nachsetz? Meine App soll bitte berücksichtigen, eine Hebamme kann ich ihr nicht beipacken - (denn ich kenn leider das API für sie nicht. 😃 ).

    Weiterer Hinweis: Die beiden fallweisen Messages hab ich auf ein Button-OnClick gelegt und kann derzeit den Zustand von BildModified abrufen. Nach dem Verlassen der SaveAs-Function ist der Wert erst mal falsch, denn die Meldung ist nach dem Speichern "true". Trotzdem wird der Wert beim Zurücksetzen des Cursors an den Anfang von OnCloseQuery dann richtig, die App wird folgerichtig sofort geschlossen.

    Was könnte den Krompfler reinbringen und ihn dann wieder korrigieren? Hat jemand 'ne Idee? Ansonsten: *Der_ich_kopfschüttelnd_verzweifelt_sei*. 😉



  • *Bin fäddisch midde Nävve, fäddisch midde Welt*, hab "den Hammer" genommen. :p

    Am Ende von OnCloseQuery:

    if (FileSaveAs->Tag == 0 && CanClose == false)
      {              
        FileSaveAs->Tag = 1;
        FormCloseQuery(Sender, CanClose);
      }
    

    Also genau eine Wiederholung der Fuction. Und

    void __fastcall TPixi::SaveDialogClose(TObject *Sender)
    {
      FileSaveAs->Tag = 0;  
    }
    

    Kurz und schmerzhaft, Stilbruch, undel und... funzt. (Wer sich für Speichern entschließt, dann aber SaveAs abbricht und das immer wieder, ist selbst schuld, wenn er den Dialog nie los wird. 😉 Rest klappt.

    Bin natürlich nicht zufrieden mit dem krampf. Wenn jemand eine Idee hat, ein Omega-X ist immer ein dankbarer Abnehmer. :p



  • wann wird den dein SaveAs-Dialog aufgerufen?
    wo wird BildModified überall verwendet?



  • Oha, jetzt komm ich endlich wieder dran.

    @Sunday, bin bei den Punkten nicht fündig geworden. Aber ich muß was übersehen haben.

    FileSaveAs wird durch FileSave aufgerufen, wenn die Datei noch nicht besteht. Ansonsten nur via MenuItem bzw. Tatsakombi.

    In der Situation auch im OnCloseQuery, wenn der user speichern möchte:

    if (cm == mrYes)
          FileSaveAsClick(Sender);
    

    Sonst kein weiterer Aufruf.

    BildModified:

    private:
        bool BildModified;
    
    __fastcall TPixi::TPixi(TComponent* Owner)
        BildModified = false;
    
    void __fastcall TPixi::FormCloseQuery(TObject *Sender, bool &CanClose)
        if (BildModified == false)
            CanClose = true;
    
    // Dialogauswertung (Modal)
    void __fastcall TPixi::BildEinpassen(TObject *Sender)
        BildModified = true;
    // dto.
    void __fastcall TPixi::BildVerkleinern(TObject *Sender)
        BildModified = true;
    // dto.
    void __fastcall TPixi::BildNichtAnp(TObject *Sender)
        BildModified = true;
    
    // nach Zeichenvorgängen
    void __fastcall TPixi::ImageMouseUp(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
        // Markieren und Farbabgriff via Pipette zählt nicht als Modifizierung
        // ansonsten jede Operation.
        // Hier auch die Definition genau da, wo die Modifizierung erfolgt
        if (!MarkBtn->Down && PipetteBtn->Tag != 1)
            BildModified = Image->Picture->Graphic->Modified;
    
    // alle ÖffnenWege münden in
    void __fastcall TPixi::Open(TObject *Sender)
        // ein geöffnetes Bild ist noch nicht modifiziert
        BildModified = false;
    
    // nach dem Speichern Bild nicht mehr modifiziert
    void __fastcall TPixi::FileSaveClick(TObject *Sender)
        BildModified = false;
    // dto.
    void __fastcall TPixi::SaveAsFormat(TObject *Sender)
        // für jeden Dateityp nach dem Speichern
        BildModified = false;
    // wenn SaveAs-Dialog abgebrochen wurde
    void __fastcall TPixi::FileSaveAsClick(TObject *Sender)
        if (SaveDialog->Execute() == true)
            // User speichert, s.o.
            if (cm == mrYes || FileExists(SaveDialog->FileName) == false)
                SaveAsFormat(Sender);
            // oder bricht den Vorgang ab
            else
                BildModified = true;
    

    Das war's, bin mit Strg+F/F3 alles durchgegangen. Leider, alles scheint richtig zu sein. Seh ich des Pudels kern nicht oder doch ggf. ein Optimierungsfehler?



  • ich würde FormCloseQuery wenn dann so machen. naja eigentlich müsstes funktionieren... *grübel*

    schon mal probiert das ganze in FormClose zu packen und dort Action zu befummeln???

    void __fastcall TPixi::FormCloseQuery(TObject *Sender, bool &CanClose)
    {
      CanClose = BildModified == false;
    
      if (BildModified)
      {
        int cm = MessageDlg("Bild wurde geändert.\nSpeichern vor dem Schließen des Fensters?", 
                            mtConfirmation, TMsgDlgButtons() << mbYes << mbNo << mbCancel, 0);
    
        switch(cm)
        {
          case mrYes : FileSaveAsClick(Sender); return;
          case mrNo  : CanClose = true;         return;
          default    : CanClose = false;        return;
        }
      }
    }
    

    [ Dieser Beitrag wurde am 07.05.2003 um 11:23 Uhr von Sunday editiert. ]



  • > CanClose = BildModified == false;

    Uff, solche verkürzte Schreibweise hätt ich schon öfter brauchen können. Doppelgleich geht nicht aber eine verkürzte Bedingungsanweisung geht. Nie gesehen, wär sicher nie drauf gekommen, @Sunday, dafür dank ich dir sehr. 🕶

    Und...? Ja, ich bin ein Nili! Mal mit switch klare Verhältnisse schaffen, das hätte ich selbst mal probieren sollen.

    Eigenartig bleibt für mich nur, der Debugger ging nach der ersten Zeile dann glatt über die gesamte restliche Funktion weg. Schon die erste Bedingung war für ihn erst mal false. Die jetzige erste Zeile versteht er einwandfrei.

    Jau, ich sagte, "in der ersten Stufe fertig". Das meinte, jetzt geht es erst mal richtig an die Codeoptimierungen. Ich staun da immer wieder, was tatsächlich an Optimierung möglich ist - wenn man nur die Wege findet. Egal wieviel ich dazu pack, über 2000 Zeilen komm ich eher nie. :p

    Noch mal ganz dicken Dank an die Helpers. Das war Präzision pur... und der ich konnte einiges lernen. 🕶

    PS: @Sunday, OnClose würde genauso gehen (Action caNone und caFree). (Bei MDI-Childs brauch ich die Action caFree, weil mir ja der Default caMinimize nichts nützt (find den Default dort falsch, weil der user ja explizit das Schließenkreuz gewählt hat und der Minimize-Button per Default vorhanden ist)). Hier liegt mir OnCloseQuery automatisch in den Fingern, weil das ja das prüfende Ereignis ist. Und klappt auch wunnebar. Hatte diesen komischen Fall bisher noch nicht... und jetzt auch nicht mehr 😉 🕶 .


Anmelden zum Antworten