TLMDOpenDialog und TLMDSaveDialog verwenden
-
ich wollte die oben genannten Dialoge von LMD verwenden. Da ergeben sich ein paar Probleme. Zum einen der WideString. Ich wollte eine txt-Datei öffnen und in ein Memo schreiben lassen:
void __fastcall TForm1::B_OeffnenClick(TObject *Sender) { fstream f; if (OpenDialog->Execute()) { f.open(OpenDialog->FileName, ios::binary | ios::out); } }
Das bricht mit dem Fehlern:
[C++ Fehler] Unit1.cpp(74): E2034 Konvertierung von 'WideString' nach 'const char *' nicht möglich, [C++ Fehler] Unit1.cpp(74): E2342 Keine Übereinstimmung des Typs beim Parameter 's' ('const char *' erwartet, 'WideString' erhalten)
ab. Das ist ja auch klar, da ein C-String erwartet wird.
Wie wandel ich den WideString in einen C-String um? c_str() funktioniert hier nicht.
-
Warum der Umweg über fstream wenns mit VCL Mittel schneller geht?
void __fastcall TForm1::B_OeffnenClick(TObject *Sender) { if (OpenDialog->Execute()) { Memo1->Lines->LoadFromFile(OpenDialog->FileName); } }
-
weil das Memo nur testweise ist. Die Daten sollen später auch in andere Komponenten geladen.
-
Dann würde ich eine TStringList verwenden.
-
daran hab ich auch schon gedacht. Beim öffnen der Datei hab ich eine Stringliste verwendet. Wollt aber den Code fürs speichern evtl auch umschreiben für eine stringliste. Aber den SaveDialog würde ich gern verwenden.
-
kann man eine StringListe beim Speichern über das Objekt auch an eine Datei anhängen wie es bei ofstream ist? Ich möchte nämlich beim autospeichern nicht jedes Mal alles neu in die Datei schreiben sondern Inhalt nur hinzufügen.
2. Frage: Wie kann ich an eine Stringliste an den Anfang (also vor allen anderen Strings) etwas einfügen? --> hat sich bereits erledigt. Das funktioniert mit Insert.
3. Frage:
ich habe ein Speichern unter über ein TSaveDialog, der eine Stringliste speichert. Die bool Variable "gespeichert" wird hier auf true gesetzt damit die Speichern-Funktion weiss, dass Speichern unter schon ausgeführt wurde. Nun soll bei dem Button Speichern nur die Datei aktualisiert werden.
Hier meine Speichern unter:void __fastcall TForm1::B_SpeichernUnterClick(TObject *Sender) { TStringList* DateiSpeichernUnter = new TStringList(); AnsiString SaveFileName(E_AutosaveDateiname->Text + BE_AutosaveSpeicherziel->Path); //eine BrowseEditKomponente SaveDialog1->FileName = SaveFileName; if (SaveDialog1->Execute()) { DateiSpeichernUnter->SaveToFile(SaveDialog1->FileName); Data->SaveToFile(SaveDialog1->FileName); Data->Insert(0, E_Data1->Text); Data->Insert(1, E_Data2->Text); Data->Insert(2, "gespeichert: " + Now()); gespeichert = true; LMDStatusBar1->SimpleText = "Daten erfolgreich gespeichert: " + Now(); delete DateiSpeichernUnter; } }
und die Speichern:
void __fastcall TForm1::B_SpeichernClick(TObject *Sender) { if (!gespeichert) { B_SpeichernUnterClick(Form1); } else { //hier aktuellen Zustand speichern } }
eine autospeichern Funktion soll es dann auch noch geben
-
Eine TStringList kann man nicht einer bestehenden Datei hinzufügen.
Aber was spricht dagegen erst die Datei mit LoadFromFile einzulesen
zu bearbeiten (anhängen) und dann mit SaveToFile wieder zu speichern.zu 2.
Ja wie geschrieben kannst du mit Insert einfügen oder auch mitStringList->Text = AndereStringList->Text + StringList->Text;
zu 3.
Ich würde mir eine Private AnsiString FileName; variable erstellen
im Form Konstruktor FileName="";
Und bei Speichern unter mir den ausgewählen Dateinamen merkenvoid __fastcall TForm1::B_SpeichernClick(TObject *Sender) { if (FileName.IsEmpty()) //DateiName ist leer { //übergebe leeren DateiNamen = speichern unter DatenSpeichern(""); } else //Speichere in bestehende Datei { //übergebe DateiNamen = speichern in bestehende datei DatenSpeichern(FileName); } } void __fastcall TForm1::B_SpeichernUnterClick(TObject *Sender) { DatenSpeichern(""); } void TForm1::DatenSpeichern(AnsiString FName) { if (FName.IsEmpty()) //Dateiname ist nicht angegeben { if (SaveDialog1->Execute()) { FileName = SaveDialog1->FileName; } } if (!FileName.IsEmpty()) { //benötigt #include <memory> std::auto_ptr<TStringList> DateiSpeichernUnter(new TStringList()); //Fülle die StringList mit deinen Daten DateiSpeichernUnter->Text = "blah blah"; DateiSpeichernUnter->SaveToFile(FileName); } }
-
std::auto_ptr<TStringList> DateiSpeichernUnter(new TStringList());
Das ist neu für mich. Was passiert hier?
Ich muss noch dazu sagen, dass Data bei mir auch eine Stringliste ist. Die eigentlichen Messdaten stehen in einem Vektor, der über ein Timerereignis ständig gefüllt wird.
void TForm1::DatenSpeichern(AnsiString FileName) { if (FileName.IsEmpty()) //Dateiname ist nicht angegeben { if (SaveDialog1->Execute()) { FileName = SaveDialog1->FileName; } } if (!FileName.IsEmpty()) { Data->Insert(0, E_Data1->Text); Data->Insert(1, E_Data2->Text); Data->Insert(2, "gespeichert: " + Now()); for (unsigned int i=0; i<VMesswerte.size(); i++) { Data->Add(VMesswerte[i].GetMesswert1()); } Data->SaveToFile(FileName); LMDStatusBar1->SimpleText = "Daten erfolgreich gespeichert: " + Now(); } }
funktionieren will es so nicht. Auch wenn gespeichert wurde öffnet er immer wieder den SaveDialog.
-
nu weiss ich warum. Hab einfach mal die Funktion DatenSpeichern(AnsiString FileName) weggelassen. Das er immer wieder den SaveDialog öffnet ist klar. Beim Drücken des Speichernbuttons ruft er die Funktion auf und übernimmt immerwieder den leeren String der im Konstruktor der Form steht.
-
Habe extra eine andere Variable bei der Funktionsübergabe genommen FName
void TForm1::DatenSpeichern(AnsiString FName) {
Um das zu verhintern was du geschrieben hast:
void TForm1::DatenSpeichern(AnsiString FileName)
Du hast die Variable FileName neu erstellen im Scope so verhinterst du
das die private FileName Variable beschrieben wird.std::auto_ptr<TStringList> DateiSpeichernUnter(new TStringList());
Das erstellt einen Autopointer auf eine neue TStringList und wenn der Scope
verlassen wird, wird automatisch das Objekt gelöscht,
somit ist ein delete DateiSpeichernUnter; hinfällig.
-
alles klar. Verstehe. Jetzt funktioniert es. Vielen Dank
-
VergissEs schrieb:
std::auto_ptr<TStringList> DateiSpeichernUnter(new TStringList());
Das erstellt einen Autopointer auf eine neue TStringList und wenn der Scope
verlassen wird, wird automatisch das Objekt gelöscht,
somit ist ein delete DateiSpeichernUnter; hinfällig.Auch das obligatorische try/__finally wird überflüssig.