Grafikus C# – Windows Forms tanfolyam › 2.3 lecke

Windows Forms · 2.3 lecke

SaveFileDialog – dokumentum mentése RTF-ként

A MiniWord már meg tud nyitni fájlokat, de ami benne készül, az eddig elveszett, amint bezárod. Most megtanítjuk menteni: a felhasználó megadja a fájl nevét és helyét, a program pedig RTF fájlba írja a dokumentumot, formázással együtt.

  • kb. 45–60 perc
  • kezdő szint
  • fájlmentés
Diáklány C# programot készít laptopon

A lecke végére

  • elhelyezel egy SaveFileDialog komponenst, és beállítod a szűrőjét;
  • a DefaultExt és az AddExtension segítségével gondoskodsz róla, hogy a fájl végén ott legyen a .rtf;
  • a SaveFile() metódussal elmented a dokumentumot formázással együtt;
  • kezeled, ha a mentés nem sikerül;
  • ellenőrzöd, hogy a mentett fájl megnyitható a MiniWordben és a Wordben is;
  • tudod, mit tartalmaz egy RTF fájl, ha szövegként nyitod meg.

Mielőtt elkezded

Ehhez a leckéhez kell a MiniWord a 2.2 lecke után, vagyis a működő Megnyitas() metódussal. A mentés ugyanazt a mintát követi, mint a megnyitás.

2.2 OpenFileDialog – RTF és TXT megnyitása →

A SaveFileDialog komponens

A mentés párbeszédablaka a megnyitáséhoz hasonlóan működik, ezért ugyanazokat a lépéseket követjük:

  1. Húzz az ablakra egy Button-t: (Name): btnMentes, Text: Mentés. Tedd a Megnyitás gomb mellé.
  2. A Toolbox Dialogs csoportjából húzd az ablakra a SaveFileDialog elemet. Alul, a komponenssávban fog megjelenni.
  3. Állítsd a (Name) tulajdonságát sfdMentes-re. Az sfd a SaveFileDialog rövidítése.
📷 Képernyőkép helye

Mit tegyél ide: a MiniWord Designer nézete. Fent a Megnyitás és a Mentés gomb egymás mellett, alul a komponenssávban az ofdMegnyitas és az sfdMentes ikon.Javasolt fájlnév: winforms-2-3-savefiledialog-komponens.webp · Alt szöveg: A SaveFileDialog komponens a Visual Studio tervezőjének komponenssávjában

Te jössz!

Add hozzá a Mentés gombot és az sfdMentes komponenst. Készíts a gombhoz Click eseménykezelőt dupla kattintással, de a kódot még ne írd meg.

Szűrő és kiterjesztés

A felhasználó megadja a fájl nevét, de a program felel azért, hogy a fájl RTF legyen. Ehhez négy tulajdonságot állítunk be:

FilterA fájltípusok listája. Mentésnél csak egy kell: RTF dokumentum (*.rtf)|*.rtf.
DefaultExtAz alapértelmezett kiterjesztés, pont nélkül: rtf.
AddExtensionHa true, a program hozzáteszi a kiterjesztést, ha a felhasználó elfelejtette begépelni.
FileNameA javasolt fájlnév, például dokumentum. A felhasználó átírhatja.

Ha például a felhasználó azt írja a névmezőbe, hogy level, és az AddExtension be van kapcsolva, akkor a fájl neve level.rtf lesz.

Jósolj!

Mi történik, ha a felhasználó ugyanolyan nevet ad meg, amilyen fájl már létezik a mappában?

Jóslat ellenőrzése

A Windows megkérdezi, hogy felülírja-e a meglévő fájlt. Ezt az OverwritePrompt tulajdonság vezérli, amely alapból be van kapcsolva, így nem kell kódot írnunk hozzá.

A dokumentum mentése: SaveFile

A mentés lényege egyetlen sor. A SaveFile() a szövegdoboz tartalmát a megadott fájlba írja. A második paraméter, a RichTextBoxStreamType.RichText azt mondja meg, hogy RTF formátumban, a formázással együtt kell menteni.

Form1.csC#
rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.RichText);
sfdMentes.FileNameA felhasználó által megadott teljes elérési út, például C:\Teszt\level.rtf.
RichTextBoxStreamType.RichTextRTF formátum: a félkövér, dőlt és egyéb formázás is bekerül a fájlba.

Ne a PlainText típust használd!

Ha RichTextBoxStreamType.PlainText típussal mentesz, a fájlban csak a nyers szöveg lesz, a formázás elvész. Ráadásul a kiterjesztés .rtf marad, ezért a Word és a MiniWord is megpróbálja RTF-ként megnyitni.

A teljes Mentes() metódus

Ugyanazt a szerkezetet építjük fel, mint a megnyitásnál: saját metódus, DialogResult ellenőrzés és try–catch. A mentés is meghiúsulhat: ha a fájl éppen meg van nyitva a Wordben, vagy a mappába nincs írási jogosultságod, a SaveFile hibával áll meg.

Form1.csC#
private void btnMentes_Click(object sender, EventArgs e)
{
Mentes();
}

private void Mentes()
{
sfdMentes.Title = "Dokumentum mentése";
sfdMentes.Filter = "RTF dokumentum (*.rtf)|*.rtf";
sfdMentes.DefaultExt = "rtf";
sfdMentes.AddExtension = true;
sfdMentes.FileName = "dokumentum";

if (sfdMentes.ShowDialog() == DialogResult.OK)
{
try
{
rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.RichText);
MessageBox.Show("A dokumentum mentve.");
}
catch (Exception ex)
{
MessageBox.Show("Nem sikerült menteni a fájlt: " + ex.Message);
}
}
}
📷 Képernyőkép helye

Mit tegyél ide: a futó MiniWord Mentés másként ablaka. A típuslistában „RTF dokumentum (*.rtf)”, a fájlnév mezőben a „dokumentum” javaslat látszik, a címsorban pedig „Dokumentum mentése”.Javasolt fájlnév: winforms-2-3-mentes-ablak.webp · Alt szöveg: A MiniWord mentés ablaka RTF típussal és javasolt fájlnévvel

Működik!

Nyiss meg a Megnyitás gombbal egy formázott RTF fájlt (például a teszt.rtf-et), írj hozzá egy mondatot, majd kattints a Mentés gombra, és adj meg egy új fájlnevet. A Megnyitas() ugyanezt a fájlt visszatölti.

Mi van valójában az RTF fájlban?

Az RTF szöveges formátum, ezért Jegyzettömbbel is megnyithatod. Kattints jobb gombbal a mentett fájlra, és válaszd a Megnyitás ezzel → Jegyzettömb lehetőséget.

Jósolj!

Mit fogsz látni, ha egy Szia szót tartalmazó dokumentum mentett fájlját Jegyzettömbben nyitod meg? Csak a Szia szót?

Jóslat ellenőrzése

Nem. A fájl elején formázási kódok állnak, például {\rtf1\ansi ...}, és csak valahol közöttük látod a Szia szót. Ezt kapod meg a 2.1 leckében megismert Rtf tulajdonságból is: a SaveFile lényegében ezt a szöveget írja a fájlba.

📷 Képernyőkép helye

Mit tegyél ide: a MiniWord által mentett .rtf fájl Jegyzettömbben megnyitva. Látszódjanak a kapcsos zárójeles RTF kódok az elején, és közöttük a mentett szöveg.Javasolt fájlnév: winforms-2-3-rtf-jegyzettombben.webp · Alt szöveg: Egy mentett RTF fájl tartalma Jegyzettömbben: formázási kódok és a szöveg

📷 Képernyőkép helye

Mit tegyél ide: ugyanaz a mentett fájl a Wordben megnyitva, normál szerkesztőnézetben. Így látható, hogy a MiniWord által mentett fájlt más program is érti.Javasolt fájlnév: winforms-2-3-rtf-wordben.webp · Alt szöveg: A MiniWordben mentett RTF dokumentum megnyitva a Wordben

Jósolj, aztán futtasd!

Minden feladatnál először írd le, mit vársz, és csak utána próbáld ki.

1. Kiterjesztés nélküli név

A névmezőbe azt írod, hogy level, és kattintasz a Mentés gombra. Hogy hívják a létrejött fájlt?

Jóslat ellenőrzése

level.rtf. A DefaultExt és az AddExtension hozzátette a kiterjesztést.

2. Mégse

Megnyitod a mentés ablakot, majd a Mégse gombra kattintasz. Keletkezik fájl? Megjelenik üzenet?

Jóslat ellenőrzése

Nem keletkezik fájl, és üzenet sem jelenik meg, mert a ShowDialog() eredménye Cancel, ezért az if blokk nem fut le.

3. Kerek út

Elmented a dokumentumot, bezárod a MiniWordöt, újraindítod, majd megnyitod ugyanazt a fájlt. Mit látsz?

Jóslat ellenőrzése

Ugyanazt a szöveget, ugyanazzal a formázással. Ez az újranyitási teszt: ha ezt meg tudod csinálni, a mentés és a megnyitás együtt működik.

Hibakeresés: te vagy a hibadetektív

Hibavadászat

Jósold meg, hogy fordítási hiba, futás közbeni hiba vagy rossz működés lesz-e. Csak utána nyisd le a megoldást.

1. Elveszett formázás

rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.PlainText);
Hiba és javítás

Rossz működés: a félkövér és a többi formázás nem kerül a fájlba. Javítás: RichTextBoxStreamType.RichText.

2. Kiterjesztés nélküli fájl

sfdMentes.Filter = "RTF dokumentum (*.rtf)|*.rtf";
// DefaultExt és AddExtension nincs beállítva
Hiba és javítás

Ha a felhasználó csak annyit ír, hogy level, a fájl kiterjesztés nélkül jöhet létre, és a Windows nem tudja, melyik programmal nyissa meg. Javítás: sfdMentes.DefaultExt = "rtf"; és sfdMentes.AddExtension = true;

3. Üres elérési út

sfdMentes.ShowDialog();
rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.RichText);
Hiba és javítás

Futás közbeni hiba, ha a felhasználó a Mégse gombot választja: nincs fájlnév, a SaveFile pedig mégis megpróbál menteni. Javítás: ellenőrizd a ShowDialog() eredményét az if (... == DialogResult.OK) szerkezettel.

4. Nyitva lévő fájl

A mentendő fájl éppen meg van nyitva a Wordben, a MiniWord pedig összeomlik a mentéskor.

rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.RichText);
// IOException: a fájlt másik folyamat használja
Hiba és javítás

Futás közbeni hiba (IOException): a Word zárolja a fájlt. Ilyenkor a program nem tud rá írni. Javítás: tedd a mentést try blokkba, a catch pedig mutasson érthető üzenetet a felhasználónak.

5. Két külön mentési kód

// btnMentes_Click-ben is és később a menüben is ugyanaz a hosszú kód
Hiba és javítás

Ha ugyanaz a mentési kód két helyen van, a javítást mindkét helyen el kell végezni, és előbb-utóbb eltér a kettő. Ezért tettük a kódot a Mentes() metódusba: a gomb és a File menü is csak meghívja.

Mini projekt: a MiniWord ment

Bővítsd a MiniWordöt a Mentés gombbal. A Megnyitas() metódus és a többi rész változatlan marad, a következőket add hozzá a Form1 osztályhoz. Először próbáld meg önállóan megírni, és csak utána nyisd meg a megoldást.

Megoldás és ellenőrzés megnyitása
Form1.cs – új részekC#
private void btnMentes_Click(object sender, EventArgs e)
{
Mentes();
}

private void Mentes()
{
sfdMentes.Title = "Dokumentum mentése";
sfdMentes.Filter = "RTF dokumentum (*.rtf)|*.rtf";
sfdMentes.DefaultExt = "rtf";
sfdMentes.AddExtension = true;
sfdMentes.FileName = "dokumentum";

if (sfdMentes.ShowDialog() == DialogResult.OK)
{
try
{
rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.RichText);
MessageBox.Show("A dokumentum mentve.");
}
catch (Exception ex)
{
MessageBox.Show("Nem sikerült menteni a fájlt: " + ex.Message);
}
}
}

Az újranyitási teszt: nyiss meg egy RTF fájlt a Megnyitás gombbal, írj hozzá egy mondatot, mentsd el új néven, majd nyisd meg az új fájlt a Wordben is. Ha mindhárom helyen ugyanazt látod, a mentés és a megnyitás együtt működik.

Önálló gyakorlófeladatok

Először készíts saját megoldást. A lenyitható rész csak ellenőrzéshez van.

1. A mentett fájl neve az üzenetben

A sikeres mentés után az üzenet mondja meg, melyik fájlba mentett a program.

Egy lehetséges megoldás
MessageBox.Show("Mentve ide: " + sfdMentes.FileName);

2. Üres dokumentum

Ha a dokumentum üres, a program ne nyissa meg a mentés ablakot, hanem jelezze, hogy nincs mit menteni.

Egy lehetséges megoldás
private void Mentes()
{
if (rtbDokumentum.Text.Length == 0)
{
MessageBox.Show("Nincs mit menteni, a dokumentum üres.");
return;
}

// ... a többi kód változatlan
}

A return kilép a metódusból, a többi kód már nem fut le.

3. A fájl neve az ablak címében

Sikeres mentés után az ablak címsora legyen például MiniWord – level.rtf.

Egy lehetséges megoldás
rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.RichText);
this.Text = "MiniWord – " + Path.GetFileName(sfdMentes.FileName);

A Path használatához kell a using System.IO; sor, amelyet a 2.2 leckében már felvettél.

Gyakorlótár: 6 további feladat

Három szinten gyakorolhatsz: alap, közepes és kihívás. A feladatokhoz egy rtbDokumentum RichTextBox, egy sfdMentes SaveFileDialog és egy gomb kell. A fájl elejére tedd a using System.IO; sort, ha nincs ott. Csak a próbálkozás után nyisd le a megoldást.

Alap szint

1. Mentés RTF fájlba

A btnMent gomb kérdezzen nevet, és mentse a dokumentumot RTF fájlba formázással együtt.

Megoldás megnyitása

A SaveFile a megadott fájlba írja a tartalmat. A RichTextBoxStreamType.RichText RTF formátumot jelent, a formázással együtt.

Form1.csC#
private void btnMent_Click(object sender, EventArgs e)
{
sfdMentes.Filter = "RTF dokumentum (*.rtf)|*.rtf";

if (sfdMentes.ShowDialog() == DialogResult.OK)
{
rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.RichText);
}
}

2. Kiterjesztés és alapnév

A mentés ablak alapból a dokumentum nevet kínálja fel, és ha a felhasználó kiterjesztés nélkül ír be nevet, a program tegye hozzá az .rtf kiterjesztést.

Megoldás megnyitása

A FileName az alapértelmezett fájlnév, a DefaultExt az alapértelmezett kiterjesztés (pont nélkül), az AddExtension pedig igazra állítva automatikusan hozzáadja a hiányzó kiterjesztést.

Form1.csC#
sfdMentes.Filter = "RTF dokumentum (*.rtf)|*.rtf";
sfdMentes.FileName = "dokumentum";
sfdMentes.DefaultExt = "rtf";
sfdMentes.AddExtension = true;

Közepes szint

3. Mentés sima szövegként

A szűrő kínálja az RTF és a TXT formátumot is. TXT választásakor csak a szöveg kerüljön a fájlba, formázás nélkül.

Megoldás megnyitása

A FilterIndex megmondja, melyik szűrőt választotta a felhasználó (1-től számozva). Más megoldás: a fájl kiterjesztését vizsgáljuk. A TXT-hez a File.WriteAllText egyszerű szöveget ír.

Form1.csC#
private void btnMent_Click(object sender, EventArgs e)
{
sfdMentes.Filter = "RTF dokumentum (*.rtf)|*.rtf|Szöveges fájl (*.txt)|*.txt";
sfdMentes.AddExtension = true;

if (sfdMentes.ShowDialog() != DialogResult.OK)
{
return;
}

if (Path.GetExtension(sfdMentes.FileName).ToLower() == ".txt")
{
File.WriteAllText(sfdMentes.FileName, rtbDokumentum.Text);
}
else
{
rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.RichText);
}
}

4. Hibakezelés mentéskor

Védd a mentést try–catch blokkal: ha a fájl nem írható (például írásvédett mappa), a program mutasson érthető üzenetet, ne omoljon össze.

Megoldás megnyitása

Az UnauthorizedAccessException jellemzően írásvédett helyre mentéskor keletkezik. A sikerüzenet a try blokk végén van, így hibánál nem jelenik meg.

Form1.csC#
try
{
rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.RichText);
MessageBox.Show("A dokumentum mentve.");
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Ebbe a mappába nem menthetsz. Válassz másik helyet!");
}
catch (Exception ex)
{
MessageBox.Show("Nem sikerült menteni: " + ex.Message);
}

Kihívás szint

5. Üres dokumentum nem menthető

Ha a dokumentum teljesen üres, a program kérdezze meg: Üres dokumentumot mentesz. Folytatod? Csak Igen esetén jelenjen meg a mentés ablak.

Megoldás megnyitása

A kérdés a mentés ablak előtt jelenik meg. Nem esetén a return kilép, így a felhasználónak nem kell feleslegesen nevet adnia.

Form1.csC#
private void btnMent_Click(object sender, EventArgs e)
{
if (rtbDokumentum.Text.Length == 0)
{
DialogResult valasz = MessageBox.Show("Üres dokumentumot mentesz. Folytatod?", "Mentés", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

if (valasz == DialogResult.No)
{
return;
}
}

sfdMentes.Filter = "RTF dokumentum (*.rtf)|*.rtf";
sfdMentes.AddExtension = true;

if (sfdMentes.ShowDialog() == DialogResult.OK)
{
rtbDokumentum.SaveFile(sfdMentes.FileName, RichTextBoxStreamType.RichText);
}
}

6. Mentés–megnyitás ellenőrzése

Készíts egy gombot, amely a dokumentumot elmenti egy ideiglenes RTF fájlba, betölti egy második, rejtett rtbEllenor RichTextBoxba, és összehasonlítja a két szöveget. Írja ki, hogy a mentés hibátlan volt-e.

Megoldás megnyitása

Az ideiglenes fájl útvonalát a Path.GetTempFileName() adja. A két Text összehasonlítása megmutatja, hogy a szöveg ugyanaz maradt-e. A fájlt a finally blokkban töröljük: az akkor is lefut, ha közben hiba történt. A formázás megmaradását így nem ellenőrizzük, csak a szöveget.

Form1.csC#
private void btnEllenorzes_Click(object sender, EventArgs e)
{
string ideiglenes = Path.GetTempFileName();

try
{
rtbDokumentum.SaveFile(ideiglenes, RichTextBoxStreamType.RichText);
rtbEllenor.LoadFile(ideiglenes, RichTextBoxStreamType.RichText);

if (rtbDokumentum.Text == rtbEllenor.Text)
{
MessageBox.Show("A mentés hibátlan.");
}
else
{
MessageBox.Show("Eltérés van a mentett és az eredeti szöveg között!");
}
}
catch (Exception ex)
{
MessageBox.Show("Hiba az ellenőrzésnél: " + ex.Message);
}
finally
{
File.Delete(ideiglenes);
}
}

Gyors önellenőrzés

Válaszolj fejben, és csak utána nyisd le a választ.

1. Melyik két tulajdonság gondoskodik róla, hogy a fájl végén ott legyen a .rtf?

A DefaultExt (rtf) és az AddExtension (true).

2. Mit csinál a SaveFile?

A szövegdoboz tartalmát a megadott fájlba írja, a megadott formátumban.

3. Mit jelent a RichTextBoxStreamType.RichText mentéskor?

Azt, hogy a program RTF formátumban ment, a formázással együtt. PlainText esetén csak a nyers szöveg kerülne a fájlba.

4. Miért kell ellenőrizni a ShowDialog() eredményét?

Hogy Mégse gomb esetén ne próbáljon a program fájlt menteni.

5. Miért tettük a mentési kódot külön Mentes() metódusba?

Hogy a gomb és később a File menü is ugyanazt a kódot hívhassa, ne kelljen kétszer megírni.

6. Mi az újranyitási teszt?

Elmented a dokumentumot, majd újra megnyitod, és ellenőrzöd, hogy ugyanazt a tartalmat és formázást kapod-e.

Mit tudsz már?

  • Elhelyezel és beállítasz egy SaveFileDialog komponenst.
  • Gondoskodsz róla, hogy a mentett fájl kiterjesztése .rtf legyen.
  • A SaveFile metódussal formázással együtt mentesz.
  • Védekezel a mentési hibák ellen try–catch szerkezettel.
  • Tudod, hogy az RTF szöveges fájl, benne formázási kódokkal.
  • Elvégzed az újranyitási tesztet.

Következő lecke: félkövér, dőlt, aláhúzott

A MiniWord már nyit és ment. Most végre megtanítjuk formázni is: kijelölt szöveget félkövérré, dőlttté és aláhúzottá tenni.