Grafikus C# – Windows Forms tanfolyam › 4.2 lecke Windows Forms · 4.2 · önálló gyakorlás Ez a tanfolyam legnagyobb önálló feladata: egy Word-szerű szövegszerkesztőt építesz meg a 2. fejezet tudásával, időre. A leírás szerepel, a megoldás nem: csak támpontokat kapsz. Ha egy rész nehéz, a megfelelő lecke ott részletesen megoldja, de a program összeállítása a te munkád.Önálló feladat II.: MiniWord – grafikus szövegszerkesztő

A feladat végére
- önállóan megtervezel és felépítesz egy többfunkciós szövegszerkesztőt;
- fájlt nyitsz meg és mentesz a felhasználó által választott néven, hibakezeléssel;
- a kijelölt szöveget formázod: stílus, betűtípus, betűméret, igazítás;
- keresel a szövegben, és kiemeled az összes találatot;
- menüt, névmezőt, About ablakot és karakterszámlálót építesz;
- a tesztlistával és az önértékeléssel ellenőrzöd a munkádat.
Mielőtt elkezded
Ehhez a feladathoz a 2. fejezet leckéire támaszkodsz. A munka közben használhatod a leckéket és a saját jegyzeteidet. A sorkizárt igazításhoz a 2.7 lecke segédosztálya használható.
A feladat leírása
Készíts MiniWord néven egy Windows Forms szövegszerkesztőt, amelynek tulajdonságai:
- A fő felület egy
RichTextBox, alatta vagy mellette egy címke mutatja a szövegben lévő karakterek számát, és ez gépelés közben azonnal frissül. - Az RTF fájlok megnyithatók egy fájlválasztóval. A típusszűrő felsorolja az RTF, a DOCX és az összes fájl lehetőségét. (A DOCX megnyitását a program nem tudja, ilyenkor érthető üzenet jelenik meg.)
- A szöveg RTF fájlba menthető, a felhasználó által megadott néven, az .rtf kiterjesztéssel.
- A kijelölt szöveg félkövér, dőlt és aláhúzott lehet, kapcsolóként működő gombokkal.
- A kijelölt szöveghez legalább három betűméret és három betűtípus választható legördülő listából.
- A bekezdések balra, jobbra, középre és sorkizártra igazíthatók.
- Egy keresőmezőbe beírt szöveg minden előfordulását a program megtalálja és kiemeli.
- Egy névmezőbe beírt nevet egy gomb egy felugró ablakban megjelenít.
- A File menü tartalmazza a Mentés, a Megnyitás és a Kilépés elemet. Az About menü felugró ablakban megmutatja, ki és mikor készítette a programot, majd egy Tanára: sort a névmezőbe beírt névvel.
Mit tegyél ide: egy példa a kész szövegszerkesztő ablakáról: menüsor, formázógombok, listák, keresősáv, névmező, a szöveges terület és a karakterszámláló.Javasolt fájlnév: winforms-4-2-minta.webp · Alt szöveg: A MiniWord szövegszerkesztő mintaablaka
Követelmények és pontozás
| Rész | Követelmény | Pont |
|---|---|---|
| Fájlműveletek (30) | Megnyitás fájlválasztóval, a típusszűrő RTF, DOCX és minden fájl lehetőséggel; az RTF fájl betöltődik. | 12 |
Mentés RTF-ként, a megadott néven, .rtf kiterjesztéssel; a Mégse gomb nem okoz hibát. | 12 | |
| Hibás, hiányzó vagy nem támogatott fájlnál érthető üzenet jelenik meg, a program nem omlik össze. | 6 | |
| Szövegkezelés (40) | Félkövér, dőlt és aláhúzott a kijelölt szövegre; a meglévő stílus nem vész el. | 10 |
| Legalább 3 betűtípus és 3 betűméret legördülő listából, a kijelölt szövegre. | 10 | |
| Balra, középre és jobbra igazítás; a sorkizárt igazítás külön megoldással. | 10 | |
| Keresés: minden előfordulás kiemelve; üres kereséskor nem fagy le a program. | 10 | |
| Menü és kiegészítők (30) | File menü: Mentés, Megnyitás, Kilépés, a megfelelő eseménykezelőkkel. | 10 |
| About: a készítő neve, a dátum és a Tanára: sor a névmező tartalmával. | 8 | |
| Névmező és gomb, felugró ablakban a beírt névvel; üres névnél figyelmeztetés. | 6 | |
| Élő karakterszámláló a szöveg alatt. | 6 |
Összesen: 100 pont. A fájlműveletek 30, a szövegkezelés 40, a menü és a kiegészítők 30 pontot érnek.
Készíts előbb ellenőrzőlistát
Az első 15 percben írd fel a követelményeket egy listára, és munka közben pipáld ki őket. A feladat sok kis részből áll, és könnyű elfelejteni valamit. A legvégén a lista alapján ellenőrizd a kész programot.
Időbeosztás (180 perc)
| Perc | Mit csinálj? |
|---|---|
| 0–15 | Írd fel az ellenőrzőlistát a követelményekből. Gondold végig az ablak elrendezését, és a vezérlők neveit. |
| 15–35 | Hozd létre a projektet, a RichTextBox-ot, a karakterszámláló címkét, és kösd be a TextChanged eseményt. |
| 35–60 | Megnyitás szűrővel (RTF, DOCX, minden fájl), mentés RTF-be. Próbáld ki a Mégse gombot és a rossz fájlokat. |
| 60–95 | Félkövér, dőlt, aláhúzott, betűtípus és betűméret, csak a kijelölt szövegen, a meglévő stílus megtartásával. |
| 95–115 | Balra, középre, jobbra igazítás; a sorkizárt igazítás külön megoldással. |
| 115–140 | Szövegkeresés: először az első találat, majd az összes előfordulás kiemelése. |
| 140–160 | File menü, About, névmező és felugró ablak. |
| 160–180 | Teljes tesztlista, hibás bevitel, Mégse gombok, üres szöveg, több bekezdés. Mentés és újranyitás teszt. |
Támpontok (kész megoldás nélkül)
Melyik tulajdonság, melyik metódus?
| Feladat | Amit használsz | Lecke |
|---|---|---|
| Karakterszám | Text.Length, TextChanged | 2.1 |
| Megnyitás | OpenFileDialog, Filter, LoadFile, try–catch | 2.2 |
| Mentés | SaveFileDialog, DefaultExt, SaveFile | 2.3 |
| Stílusok | SelectionFont, FontStyle, a ^ operátor | 2.4 |
| Betűtípus és méret | ComboBox, SelectedIndexChanged, new Font(...) | 2.5 |
| Igazítás | SelectionAlignment; a sorkizárthoz a segédosztály | 2.6, 2.7 |
| Keresés | IndexOf, while, Select, SelectionBackColor | 2.8 |
| Névmező és About | MessageBox.Show, MenuStrip, Environment.NewLine | 2.9 |
A kijelölés hiánya és a vegyes formázás
A formázó gombok eseménykezelőjében gondolj arra, mi történik, ha nincs kijelölt szöveg, vagy a kijelölés vegyesen formázott (a SelectionFont ilyenkor null). Az üzenetet a felhasználónak érthetően kell megfogalmazni.
A stílus megtartása betűváltáskor
Új Font létrehozásakor adj át minden korábbi jellemzőt: a betűméret váltásakor a régi család és stílus, a betűtípus váltásakor a régi méret és stílus maradjon. Különben a félkövér vagy dőlt formázás elvész.
A Mégse gomb a fájlválasztónál
A ShowDialog() eredményét ellenőrizd: csak az OK esetén dolgozz a fájllal. A fájlműveleteket tedd try–catch blokkba.
A keresés kiemelései
A kiemelés a dokumentum formázása, ezért az új keresés előtt töröld a régi kiemeléseket, és mentés előtt is érdemes. Védekezz az üres keresőszöveg ellen: végtelen ciklus lehet belőle.
Az About ablak dátuma
A mikor készítette adatot rögzített szövegként add meg (a program elkészítésének napját), ne az aktuális időt.
Mintamegoldás
Előbb oldd meg önállóan!
A mintamegoldás csak az ellenőrzésre való, és nem az egyetlen helyes megoldás. Előbb próbálkozz saját kóddal, és csak elakadásnál vagy a végén nyisd meg. A részletes magyarázat a 2.1–2.10 leckékben található.
Megoldás: a felület és a nevek
| Vezérlő | (Name) | Beállítás |
|---|---|---|
| RichTextBox | rtbDokumentum | HideSelection: False |
| Label | lblKarakterszam | karakterszám |
| OpenFileDialog, SaveFileDialog | ofdMegnyitas, sfdMentes | |
| Button | btnFelkover, btnDolt, btnAlahuzott | F, D, A |
| ComboBox | cmbBetutipus, cmbMeret | DropDownList; Items: Arial, Times New Roman, Courier New, Verdana és 10, 12, 16, 20, 28 |
| Button | btnBalra, btnKozep, btnJobbra, btnSorkizart | igazítás |
| TextBox, Button | txtKeres, btnKeres | keresés és kiemelés |
| TextBox, Button | txtTanar, btnNev | névmező és felugró ablak |
| MenuStrip | miMegnyitas, miMentes, miKilepes, miAbout | File: Megnyitás, Mentés, Kilépés; About |
Megoldás: RichTextBoxHelper.cs (a sorkizárthoz)
A sorkizárt igazítás segédosztálya a 2.7 leckében van, onnan másold a projektbe (Add → Class, a fájl neve RichTextBoxHelper.cs). A két használt metódus: RichTextBoxHelper.EngedelyezSorkizartot(rtbDokumentum) (a Form1_Load-ban) és RichTextBoxHelper.Sorkizart(rtbDokumentum) (a gombban).
Megoldás: Form1.cs (teljes kód)
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
namespace MiniWord
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
RichTextBoxHelper.EngedelyezSorkizartot(rtbDokumentum);
}
private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
lblKarakterszam.Text = $"Karakterek: {rtbDokumentum.Text.Length}";
}
private void Megnyitas()
{
ofdMegnyitas.Filter = "RTF dokumentum (*.rtf)|*.rtf|Word dokumentum (*.docx)|*.docx|Minden fájl (*.*)|*.*";
if (ofdMegnyitas.ShowDialog() != DialogResult.OK)
{
return;
}
string fajl = ofdMegnyitas.FileName;
string kiterjesztes = Path.GetExtension(fajl).ToLower();
try
{
if (kiterjesztes == ".rtf")
{
rtbDokumentum.LoadFile(fajl, RichTextBoxStreamType.RichText);
}
else if (kiterjesztes == ".txt")
{
rtbDokumentum.Text = File.ReadAllText(fajl);
}
else
{
MessageBox.Show("Ezt a fájltípust a MiniWord nem tudja megnyitni: " + kiterjesztes);
}
}
catch (Exception ex)
{
MessageBox.Show("Nem sikerült megnyitni a fájlt: " + ex.Message);
}
}
private void Mentes()
{
sfdMentes.Filter = "RTF dokumentum (*.rtf)|*.rtf";
sfdMentes.DefaultExt = "rtf";
sfdMentes.AddExtension = true;
if (sfdMentes.ShowDialog() != DialogResult.OK)
{
return;
}
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);
}
}
private void StilusValt(FontStyle stilus)
{
Font regi = rtbDokumentum.SelectionFont;
if (regi == null)
{
MessageBox.Show("A kijelölésben többféle formázás van. Jelölj ki egységes szövegrészt!");
}
else
{
rtbDokumentum.SelectionFont = new Font(regi, regi.Style ^ stilus);
}
rtbDokumentum.Focus();
}
private void cmbBetutipus_SelectedIndexChanged(object sender, EventArgs e)
{
Font regi = rtbDokumentum.SelectionFont;
if (regi == null || cmbBetutipus.SelectedItem == null)
{
MessageBox.Show("A kijelölésben többféle formázás van, vagy nincs betűtípus kiválasztva.");
}
else
{
rtbDokumentum.SelectionFont = new Font(cmbBetutipus.SelectedItem.ToString(), regi.Size, regi.Style);
}
rtbDokumentum.Focus();
}
private void cmbMeret_SelectedIndexChanged(object sender, EventArgs e)
{
Font regi = rtbDokumentum.SelectionFont;
float meret;
if (regi == null)
{
MessageBox.Show("A kijelölésben többféle formázás van. Jelölj ki egységes szövegrészt!");
}
else if (float.TryParse(cmbMeret.Text, out meret))
{
rtbDokumentum.SelectionFont = new Font(regi.FontFamily, meret, regi.Style);
}
rtbDokumentum.Focus();
}
private void btnFelkover_Click(object sender, EventArgs e) { StilusValt(FontStyle.Bold); }
private void btnDolt_Click(object sender, EventArgs e) { StilusValt(FontStyle.Italic); }
private void btnAlahuzott_Click(object sender, EventArgs e) { StilusValt(FontStyle.Underline); }
private void btnBalra_Click(object sender, EventArgs e) { rtbDokumentum.SelectionAlignment = HorizontalAlignment.Left; rtbDokumentum.Focus(); }
private void btnKozep_Click(object sender, EventArgs e) { rtbDokumentum.SelectionAlignment = HorizontalAlignment.Center; rtbDokumentum.Focus(); }
private void btnJobbra_Click(object sender, EventArgs e) { rtbDokumentum.SelectionAlignment = HorizontalAlignment.Right; rtbDokumentum.Focus(); }
private void btnSorkizart_Click(object sender, EventArgs e) { RichTextBoxHelper.Sorkizart(rtbDokumentum); rtbDokumentum.Focus(); }
private void TorolKiemeleseket()
{
rtbDokumentum.SelectAll();
rtbDokumentum.SelectionBackColor = rtbDokumentum.BackColor;
rtbDokumentum.Select(0, 0);
}
private void btnKeres_Click(object sender, EventArgs e)
{
string keresett = txtKeres.Text;
if (keresett.Length == 0)
{
MessageBox.Show("Írd be, mit keressek!");
return;
}
TorolKiemeleseket();
string szoveg = rtbDokumentum.Text;
int darab = 0;
int hely = szoveg.IndexOf(keresett, 0, StringComparison.OrdinalIgnoreCase);
while (hely >= 0)
{
rtbDokumentum.Select(hely, keresett.Length);
rtbDokumentum.SelectionBackColor = Color.Yellow;
darab = darab + 1;
hely = szoveg.IndexOf(keresett, hely + keresett.Length, StringComparison.OrdinalIgnoreCase);
}
rtbDokumentum.Select(0, 0);
MessageBox.Show($"Találatok száma: {darab}");
}
private void btnNev_Click(object sender, EventArgs e)
{
string nev = txtTanar.Text.Trim();
if (nev.Length == 0)
{
MessageBox.Show("Kérlek, írj be egy nevet!");
}
else
{
MessageBox.Show("A beírt név: " + nev);
}
}
private void miAbout_Click(object sender, EventArgs e)
{
string tanar = txtTanar.Text.Trim();
if (tanar.Length == 0)
{
tanar = "(még nincs megadva)";
}
MessageBox.Show("MiniWord szövegszerkesztő" + Environment.NewLine
+ "Készítette: Minta Anna" + Environment.NewLine
+ "Dátum: 2026. október 24." + Environment.NewLine
+ "Tanára: " + tanar, "About");
}
private void miMegnyitas_Click(object sender, EventArgs e) { Megnyitas(); }
private void miMentes_Click(object sender, EventArgs e) { Mentes(); }
private void miKilepes_Click(object sender, EventArgs e) { this.Close(); }
}
}Megoldás: a legfontosabb tervezési döntések
A gomb és a menü ugyanazt a metódust hívja (Megnyitas(), Mentes()), ezért a kódot egyszer kell megírni. A formázásnál az új Font a régi stílust vagy méretet is megkapja, így a félkövér nem vész el. A SelectionFont null értékét vegyes kijelölésnél külön kezeljük. A keresés előtt töröljük a régi kiemeléseket, és üres keresőszövegnél azonnal kilépünk, mert különben a while ciklus végtelen lenne. A DOCX fájlt a program felismeri a kiterjesztésből, és érthető üzenetet ad a LoadFile hibája helyett.
Tesztlista
| # | Teszt | Várt eredmény |
|---|---|---|
| 1 | Gépelés a szövegdobozba | A karakterszámláló azonnal frissül. |
| 2 | Megnyitás: a típusszűrő lenyitása | RTF, DOCX és minden fájl lehetőség látszik. |
| 3 | RTF fájl megnyitása | A szöveg formázással betöltődik. |
| 4 | DOCX vagy sérült fájl megnyitása | Érthető üzenet, a program nem omlik össze. |
| 5 | Megnyitás, majd Mégse | Nem történik semmi. |
| 6 | Mentés, majd újranyitás | A fájl .rtf kiterjesztésű, a formázás megmarad. |
| 7 | Mentés, majd Mégse | Nem történik hiba. |
| 8 | Félkövér, dőlt, aláhúzott egy szón, majd újra | Bekapcsol, majd kikapcsol, a többi stílus megmarad. |
| 9 | Betűtípus- és méretváltás félkövér szón | A szó félkövér marad. |
| 10 | Formázás kijelölés nélkül és vegyes kijelölésnél | Érthető üzenet, nem omlik össze. |
| 11 | Balra, középre, jobbra, sorkizárt gomb | A bekezdés ennek megfelelően igazodik. |
| 12 | Keresés olyan szóra, amely többször szerepel | Minden előfordulás kiemelt. |
| 13 | Üres és nem létező szó keresése | Üzenet, nem fagy le. |
| 14 | Névmező és gomb, üres névvel is | Felugró ablak a névvel, üres névnél figyelmeztetés. |
| 15 | About menüpont | A készítő neve, a dátum és a Tanára: sor a névvel. |
| 16 | File → Kilépés | Az ablak bezárul. |
Gyakori hibák és önértékelés
Ezeken szoktak elcsúszni
Gondold végig, nálad előfordul-e valamelyik.
1. Minden egyetlen eseménykezelőben
A megnyitás, a mentés és az összes formázás kódját egyetlen gomb eseménykezelőjébe írod, és a gombok összekeverednek. Minden felületi műveletnek legyen saját eseménykezelője (Ok és javítás
Click, SelectedIndexChanged, TextChanged), a közös kód pedig külön metódusokban álljon (Megnyitas(), Mentes(), StilusValt()). A gomb és a menü is ugyanazt a metódust hívja.
2. A stílus elvész
rtbDokumentum.SelectionFont = new Font("Arial", 14);Hiba és javítás
Rossz működés: az új Font nem kapja meg a régi stílust, ezért a félkövér vagy dőlt formázás elvész. Add át a régi stílust (regi.Style) is.
3. A fájlra mentés felülírja a nevet
A mentés mindig ugyanazt a nevet használja, és a felhasználó nem tud mást megadni. A felhasználónak Ok és javítás
SaveFileDialog segítségével kell megadnia a nevet. A DefaultExt = "rtf" és az AddExtension = true beállítás gondoskodik a kiterjesztésről.
4. A keresés lefagy
Üres kereséskor a program nem válaszol. Üres keresőszövegnél a Ok és javítás
while ciklus nem lép előre, ezért végtelen. Ellenőrizd a keresőszöveg hosszát a ciklus előtt (2.8 lecke).
5. A kiemelés bekerül a mentett fájlba
A mentett dokumentum szavai sárgák maradnak. A háttérszín formázás, ezért a fájlba is bekerül. Mentés előtt töröld a kiemeléseket.Ok és javítás
6. A DOCX miatt összeomlik
A DOCX fájl kiválasztásakor a program leáll. A Ok és javítás
RichTextBox nem tud DOCX fájlt betölteni. A kiterjesztés alapján ágazz el, és DOCX esetén mutass érthető üzenetet. A LoadFile hívást tedd try–catch blokkba.
Az értékeléshez ellenőrizd az alábbi szempontokat is:
Bővítési ötletek, ha kész vagy
Ha maradt időd, fejleszd tovább a programot:
- Mentetlen munka védelme: a bezárás előtt kérdezzen rá a program (2.14 lecke).
- Szerkesztés menü: visszavonás, újra, kivágás, másolás, beillesztés (2.12 lecke).
- Állapotsor: a sor és oszlop kijelzése, a gombok követik a kijelölést (2.11 lecke).
- Nyomtatás és előnézet (2.15 lecke).
- Gyorsbillentyűk: Ctrl+O, Ctrl+S, Ctrl+F.
Mit tudsz már?
- Önállóan felépítesz egy többfunkciós szövegszerkesztőt.
- Fájlt nyitsz meg és mentesz hibakezeléssel.
- Formázod a kijelölt szöveget, és megtartod a meglévő stílust.
- Keresel és kiemeled az összes találatot.
- Menüt, névmezőt és About ablakot építesz.
Következő feladat: önálló SQLite-os alkalmazás
A szövegszerkesztő kész. A következő önálló feladatban adatbázissal dolgozol.




