Grafikus C# – Windows Forms tanfolyam › 2.1 lecke Windows Forms · 2.1 lecke A tanfolyam második fejezetében egy Word-szerű szövegszerkesztőt építünk, a MiniWordöt. Most az első lépést tesszük meg: egy szövegmezőt és egy számlálót, amely mindig megmutatja, hány karakter van a dokumentumban. Közben megismered az ablakos programok legfontosabb gondolatát is: a program eseményekre reagál.RichTextBox és TextChanged – élő karakterszámláló

A lecke végére
- létrehozod a MiniWord nevű Windows Forms projektet;
- elhelyezel egy
RichTextBox-ot és egyLabel-t, és beszédes nevet adsz nekik; - érted, mi az esemény és mi az eseménykezelő;
- a
TextChangedeseménnyel élő karakterszámlálót készítesz; - tudod, miben különbözik a
Textés azRtf; - tudod, hogyan számolja a program a sortöréseket.
Mielőtt elkezded
Erre a leckére akkor állsz készen, ha már készítettél első Windows Forms projektet, tudsz vezérlőt elhelyezni az ablakon, és ismered a string hosszát (Length), valamint a szöveginterpolációt.
Új projekt: MiniWord
Ebben a fejezetben egyetlen programot építünk lépésről lépésre: egy Word-szerű szövegszerkesztőt. A következő leckék mindig ugyanezt a projektet bővítik, ezért érdemes külön, jól elnevezett projektet nyitni.
- Visual Studio → Create a new project, és válaszd a Windows Forms App sablont. A .NET Framework és az újabb .NET változat is jó ehhez a leckéhez.
- A projekt neve legyen
MiniWord, majd kattints a Create gombra. - Kattints az üres ablakra, és a Properties ablakban írd át a
TexttulajdonságotMiniWord-re. Ez lesz az ablak címsora.
Mit tegyél ide: a Visual Studio „Create a new project” ablaka, benne a Windows Forms App sablon kijelölve (a keresőmezőbe írd be: Windows Forms). Ha kényelmes, tegyél mellé egy második képet is a „Configure your new project” lépésről, a Project name mezőben a MiniWord névvel.Javasolt fájlnév: winforms-2-1-uj-projekt.webp · Alt szöveg: Új Windows Forms projekt létrehozása MiniWord néven a Visual Studióban
Te jössz!
Hozd létre a projektet, írd át az ablak címét, majd futtasd az F5 billentyűvel. Egy üres, MiniWord feliratú ablaknak kell megjelennie. Zárd be, és térj vissza a Visual Studióba.
Két vezérlő: RichTextBox és Label
Húzz a Toolboxból (View → Toolbox) egy RichTextBox-ot az ablakra, és alá egy Label-t. A RichTextBox a Common Controls csoportban található; ha nem látod, használd a Toolbox keresőmezőjét.
Miért nem a már ismert TextBox kell? A TextBox az egész szöveget egyetlen formátumban jeleníti meg. A RichTextBox formázott szöveget is kezel: az egyik szó lehet félkövér, a másik dőlt, a harmadik nagyobb betűméretű. Ráadásul RTF fájlokat is meg tud nyitni és el tud menteni. A szövegszerkesztőnknek pontosan erre van szüksége.
Állítsd be a Properties ablakban a két vezérlő tulajdonságait:
(Name): rtbDokumentumAnchor: Top, Bottom, Left, Right(Name): lblKarakterszamText: Karakterek: 0Anchor: Bottom, LeftAz Mit tegyél ide: a Form a Designerben. A nagy RichTextBox kitölti az ablak nagy részét, alatta a Label „Karakterek: 0” felirattal. A kép mellett vagy külön képen látszódjon a Properties ablak is: a (Name) mezőben az rtbDokumentum érték, és az Anchor legördülő listában mind a négy oldal kijelölve.Javasolt fájlnév: winforms-2-1-felulet.webp · Alt szöveg: A MiniWord ablak a Visual Studio tervezőjében RichTextBoxszal és karakterszámláló címkévelAnchor azt adja meg, melyik ablakszélhez „kapcsolódjon” a vezérlő, amikor átméretezed az ablakot. A szövegdoboz így együtt nő az ablakkal, a számláló pedig az alsó sarokban marad. A részletekről a 6.2 leckében lesz szó.
Miért rtbDokumentum és lblKarakterszam?
A név elé rövid előtagot teszünk: rtb = RichTextBox, lbl = Label. Később több tucat vezérlő lesz az ablakon, és az előtagból azonnal látod, melyik milyen típusú. A (Name) és a Text két külön tulajdonság: az egyik a programozónak, a másik a felhasználónak szól. A leckék kódjai az itt megadott nevekkel működnek.
Mi az esemény?
A konzolos programban a program döntötte el, mikor jön a felhasználó: a Console.ReadLine() megállt, és várt. Az ablakos program fordítva működik. Az ablak nyitva van, a felhasználó pedig bármikor bármit csinálhat: kattinthat, gépelhet, törölhet. Ezeket nevezzük eseményeknek.
Olyan ez, mint a csengő. Nem állsz folyamatosan az ajtónál, hanem akkor mész oda, amikor megszólal. Az eseménykezelő az a metódus, amely akkor fut le, amikor az esemény bekövetkezik. A metódus kódját mi írjuk meg.
A szövegdobozunk TextChanged eseménye minden alkalommal jelez, amikor a szöveg megváltozik. Így hozhatod létre az eseménykezelőt:
- Jelöld ki a RichTextBoxot a Designerben.
- A Properties ablakban kattints a villám ikonra (Events).
- Keresd meg a
TextChangedsort, és kattints duplán az üres mezőjére.
A Visual Studio elkészíti az üres eseménykezelőt, és megnyitja a Form1.cs fájlt:
private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
// Ide írjuk a kódot. Ez fut le minden szövegváltozáskor.
}Mit tegyél ide: a Properties ablak Events nézete (villám ikon) a TextChanged sorral, amelynek mezőjére duplán kattintanál. Ha tudsz, mutasd mellette a Form1.cs-t is, amelyben már megjelent az üres rtbDokumentum_TextChanged metódus.Javasolt fájlnév: winforms-2-1-textchanged-esemeny.webp · Alt szöveg: A TextChanged esemény létrehozása a Visual Studio Properties ablakában
Ne töröld kézzel az eseménykezelőt!
A Visual Studio a háttérben a Form1.Designer.cs fájlban összeköti az eseményt a metódussal. Ha csak a metódust törlöd, a program le sem fordul. Erről a hibavadászatnál lesz szó.
A karakterszámláló
Most már csak azt kell megmondanunk, mi történjen szövegváltozáskor: számoljuk meg a karaktereket, és írjuk ki az eredményt a címkére.
private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
lblKarakterszam.Text = $"Karakterek: {rtbDokumentum.Text.Length}";
}string típusként.string hossza: a karakterek száma a szóközökkel és sortörésekkel együtt.Jósolj, mielőtt futtatod!
Beírod a Szia szót, majd két szóközt. Mit fog mutatni a számláló?
Miért 6?
A Szia négy betű, a két szóköz is karakternek számít, ezért a Length értéke 6, és a címke Karakterek: 6 lesz.
Mit tegyél ide: a futó MiniWord ablak. A RichTextBoxban a „Szia” szó két szóközzel a végén, az ablak alján pedig a „Karakterek: 6” felirat.Javasolt fájlnév: winforms-2-1-karakterszamlalo-fut.webp · Alt szöveg: A futó MiniWord program, amely hat karaktert számol a szövegdobozban
Működik!
Az eseménykezelő minden szövegváltozáskor lefut: gépeléskor, törléskor, beillesztéskor is. A számláló ezért mindig naprakész.
Text vagy Rtf?
A RichTextBox kétféleképp adja vissza a tartalmát:
A formázási jelölések egy része így néz ki: {\rtf1\ansi ...}. Ezeket a Word is megérti, a felhasználónak viszont nem szabad látnia őket. Mentéskor az Rtf fog kelleni, a karakterszámláló viszont a Text-et használja.
Kísérlet
Írd át ideiglenesen a számláló sorát úgy, hogy rtbDokumentum.Rtf.Length szerepeljen a Text.Length helyén. Mit mutat üres dokumentumnál? 0-t?
Mi a tapasztalat?
Nem 0-t. Az Rtf már az üres dokumentumnál is tartalmazza a formázási jelöléseket, ezért az érték hosszú. A karakterszámlálóhoz tehát a Text.Length a jó megoldás. A kísérlet után állítsd vissza a kódot!
Mi számít karakternek?
Minden karakter számít: betű, szám, szóköz, írásjel és a sortörés is. Az Enter a RichTextBox.Text értékében egyetlen sortörés-karakter (\n). A sima TextBox ezzel szemben két karaktert használ (\r\n). Ez az egyik apró különbség a két vezérlő között.
Jósolj, aztán próbáld ki!
Beírod, hogy ab, megnyomod az Entert, majd beírod, hogy cd. Hány karaktert mutat a számláló?
Jóslat ellenőrzése
5: két betű, az Enter sortörése, majd még két betű. Ha mást látsz, ellenőrizd, hogy a Text.Length-et használod-e.
Jósolj, aztán futtasd!
Minden feladatnál először írd le a várható eredményt, és csak utána próbáld ki a programban.
1. Három betű és két szóköz
Beírod, hogy Karakterek: 5. A betűk és a szóközök is karakternek számítanak.abc, majd két szóközt. Mit mutat a számláló?Jóslat ellenőrzése
2. Két sor
Beírod: Karakterek: 9: 4 + 1 sortörés + 4. Az Enter egy karakter a Szia, Enter, Peti. Hány karaktert mutat?Jóslat ellenőrzése
RichTextBox.Text értékében.
3. Törlés gomb
Az ablakon van egy btnTorles gomb. Mit mutat a számláló, miután megnyomod?
private void btnTorles_Click(object sender, EventArgs e)
{
rtbDokumentum.Clear();
}Jóslat ellenőrzése
Karakterek: 0. A Clear() megváltoztatja a szöveget, ezért a TextChanged esemény ilyenkor is lefut, és a számláló automatikusan frissül.
Hibakeresés: te vagy a hibadetektív
Hibavadászat
Először jósold meg, hogy a hiba fordításkor, futás közben vagy a működésben jelentkezik. Csak utána nyisd le a megoldást.
1. Szám a szöveg helyén
lblKarakterszam.Text = rtbDokumentum.Text.Length;Hiba és javítás
Fordítási hiba (CS0029): a Label.Text szöveget vár, a Length viszont int. Javítás: lblKarakterszam.Text = $"Karakterek: {rtbDokumentum.Text.Length}";
2. Nem történik semmi
// A metódust kézzel gépelted be a Form1.cs-be
private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
lblKarakterszam.Text = $"Karakterek: {rtbDokumentum.Text.Length}";
}Hiba és javítás
A program lefut, de a számláló nem változik: a metódus nincs összekötve az eseménnyel. A név önmagában nem elég. Jelöld ki a RichTextBoxot, nyisd meg az Events nézetet, és a TextChanged sor legördülő listájából válaszd ki a metódust. A legegyszerűbb: töröld a kézzel írt metódust, és dupla kattintással generáltasd újra.
3. Ismeretlen név
lblKarakterszam.Text = $"Karakterek: {rtbDokumentum.Text.Length}";
// hibaüzenet: The name 'lblKarakterszam' does not exist in the current contextHiba és javítás
Fordítási hiba (CS0103). A kód rendben van, de a címke (Name) tulajdonsága még label1. Írd át a Properties ablakban lblKarakterszam-ra. A kódban szereplő név és a (Name) tulajdonság pontosan egyezzen, a kis- és nagybetűket is beleértve.
4. Törölt eseménykezelő
Kitörölted a rtbDokumentum_TextChanged metódust a Form1.cs fájlból, a program pedig nem fordul le.
// Form1.Designer.cs – hibaüzenet (CS1061):
// 'Form1' does not contain a definition for 'rtbDokumentum_TextChanged'Hiba és javítás
A Form1.Designer.cs még feliratkozik az eseményre, de a metódus már nincs meg. Két megoldás van: létrehozod újra az eseménykezelőt (dupla kattintás a TextChanged sorra), vagy az Events nézetben törlöd a TextChanged sor tartalmát, ezzel megszűnik a feliratkozás.
Mini projekt: a MiniWord alapja
Állítsd össze a MiniWord első változatát: egy átméretezhető ablak, amelyben a RichTextBox kitölti a helyet, alul pedig mindig látszik az aktuális karakterszám. Először próbáld meg önállóan megírni, és csak utána nyisd meg a megoldást. A fájl tetején lévő Mit tegyél ide: a kész MiniWord alapváltozat futás közben. A címsorban „MiniWord”, a szövegdobozban néhány mondat, alul a hozzá tartozó „Karakterek: …” felirat. Érdemes az ablakot kicsit átméretezni, hogy látszódjon, hogy a szövegdoboz együtt nő vele.Javasolt fájlnév: winforms-2-1-miniword-kesz.webp · Alt szöveg: A kész MiniWord alapváltozat szöveggel és karakterszámlálóval Ne csak futtasd: próbáld ki hosszabb szöveggel is, majd méretezd át az ablakot, és figyeld meg, hogyan viselkedik a két vezérlő.Megoldás és ellenőrzés megnyitása
using System;
using System.Windows.Forms;
namespace MiniWord
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
lblKarakterszam.Text = $"Karakterek: {rtbDokumentum.Text.Length}";
}
}
}using sorokat a Visual Studio készíti el. Ezek teszik elérhetővé a Windows Forms osztályait. A InitializeComponent() hívás építi fel az ablakot a Designerben beállított vezérlőkből.
Önálló gyakorlófeladatok
Először készíts saját megoldást. A lenyitható rész csak ellenőrzéshez van.
1. Törlés gomb
Tegyél az ablakra egy btnTorles nevű, Törlés feliratú gombot, amely kitörli a dokumentum teljes szövegét. A számláló magától nullázódjon.Egy lehetséges megoldás
private void btnTorles_Click(object sender, EventArgs e)
{
rtbDokumentum.Clear();
}
2. Karakterszám a címsorban
Az ablak címsora is mutassa a karakterek számát, például így: MiniWord – 12 karakter. A Egy lehetséges megoldás
private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
lblKarakterszam.Text = $"Karakterek: {rtbDokumentum.Text.Length}";
this.Text = $"MiniWord – {rtbDokumentum.Text.Length} karakter";
}this az ablakot (Form1) jelenti, tehát a this.Text az ablak címsora.
3. Színjelzés
Ha a dokumentum 100 karakternél hosszabb, a számláló felirata legyen piros, különben fekete. Használj Ha a if–else szerkezetet.Egy lehetséges megoldás
private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
int darab = rtbDokumentum.Text.Length;
lblKarakterszam.Text = $"Karakterek: {darab}";
if (darab > 100)
{
lblKarakterszam.ForeColor = Color.Red;
}
else
{
lblKarakterszam.ForeColor = Color.Black;
}
}Color alá piros hullámvonal kerül, add a fájl elejéhez a using System.Drawing; sort.
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. A feladatokhoz egy rtbDokumentum RichTextBox és a leírt feliratok kellenek. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Élő karakterszámláló
Gépelés közben a A lblKarakterszam felirat mutassa: Karakterek: 12.Megoldás megnyitása
TextChanged esemény minden módosításkor lefut. A Text.Length a karakterek száma.private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
lblKarakterszam.Text = $"Karakterek: {rtbDokumentum.Text.Length}";
}
2. Sorok száma
Egy A lblSorok felirat mutassa a szöveg sorainak (bekezdéseinek) számát, gépelés közben is.Megoldás megnyitása
Lines tulajdonság a sorok tömbje, a Length a darabszámuk. Egy sor akkor új, ha Entert nyomtál: a képernyőn tördelt sorokat nem számolja külön.private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
lblSorok.Text = $"Sorok: {rtbDokumentum.Lines.Length}";
}
Közepes szint
3. Szavak száma
A A lblSzavak felirat mutassa a szavak számát. Szónak számít minden, amit szóköz választ el, az üres részek nem.Megoldás megnyitása
Split a szöveget a megadott karakter mentén darabolja. A StringSplitOptions.RemoveEmptyEntries kihagyja az üres darabokat (például a dupla szóközök között). A sorokat egyenként dolgozzuk fel, így az Enterrel elválasztott szavak is külön számítanak.private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
int szavak = 0;
foreach (string sor in rtbDokumentum.Lines)
{
szavak = szavak + sor.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
lblSzavak.Text = $"Szavak: {szavak}";
}
4. Figyelmeztető limit
A karakterszámláló legyen zöld 200 karakterig, 200 felett piros, és mutassa ki a túllépést is: Karakterek: 215 (15 felett). A szín a hossz és a limit összehasonlításától függ. A túllépés a hossz és a limit különbsége.Megoldás megnyitása
private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
int hossz = rtbDokumentum.Text.Length;
if (hossz <= 200)
{
lblKarakterszam.Text = $"Karakterek: {hossz}";
lblKarakterszam.ForeColor = Color.SeaGreen;
}
else
{
lblKarakterszam.Text = $"Karakterek: {hossz} ({hossz - 200} felett)";
lblKarakterszam.ForeColor = Color.Firebrick;
}
}
Kihívás szint
5. Szóköz nélküli karakterszám
A A lblSzokozNelkul felirat mutassa a karakterek számát a szóközök nélkül.Megoldás megnyitása
Replace(" ", "") minden szóközt törölne a szövegből, így a hossza a szóköz nélküli karakterszám. A sortörések (Enter) ezt a számot is növelik: ha ezeket sem akarod számolni, soronként kell végigmenni (lásd a szavak számolását).private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
int szokozNelkul = rtbDokumentum.Text.Replace(" ", "").Length;
lblSzokozNelkul.Text = $"Szóköz nélkül: {szokozNelkul}";
}
6. Statisztikai panel
Építs egy A számításokat külön metódusba tesszük, hogy az eseménykezelő rövid maradjon, és a statisztikát bárhonnan frissíthessük (például fájl megnyitása után).Statisztika() metódust, amely egyszerre frissíti a karakterek, szavak és sorok számát egy lblStat feliratban: Karakterek: 25 | Szavak: 4 | Sorok: 2. A TextChanged csak ezt hívja.Megoldás megnyitása
private void Statisztika()
{
int karakterek = rtbDokumentum.Text.Length;
int sorok = rtbDokumentum.Lines.Length;
int szavak = 0;
foreach (string sor in rtbDokumentum.Lines)
{
szavak = szavak + sor.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
lblStat.Text = $"Karakterek: {karakterek} | Szavak: {szavak} | Sorok: {sorok}";
}
private void rtbDokumentum_TextChanged(object sender, EventArgs e)
{
Statisztika();
}
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. A RichTextBox formázott szöveget kezel: a szöveg egyes részei különböző formátumúak lehetnek, és RTF fájlt is meg tud nyitni, el tud menteni. A TextBox az egész szöveget egy formátumban jeleníti meg. Az esemény valami, ami történik az ablakon, például szövegváltozás vagy kattintás. Az eseménykezelő az a metódus, amely az esemény bekövetkezésekor lefut. Minden alkalommal, amikor a szöveg megváltozik: gépeléskor, törléskor, beillesztéskor és a A kódban a (Name) tulajdonsággal hivatkozunk a vezérlőre. Az A A Properties ablakban, a villám (Events) ikonra kattintva. Az esemény melletti mezőre duplán kattintva a Visual Studio létrehozza az eseménykezelőt.1. Miben különbözik a RichTextBox a TextBoxtól?
2. Mi az esemény, és mi az eseménykezelő?
3. Mikor fut le a TextChanged eseménykezelő?
Clear() hívásakor is.4. Miért adunk beszédes nevet a vezérlőknek?
rtbDokumentum és az lblKarakterszam névből azonnal látszik, milyen vezérlőről van szó, és mire használjuk.5. Miben különbözik a Text és az Rtf?
Text csak a látható szöveg, az Rtf a szöveget és a formázási jelöléseket együtt tartalmazza. A karakterek megszámolásához a Text.Length kell.6. Hol találod meg a vezérlők eseményeit a Visual Studióban?
Mit tudsz már?
- Létrehoztál egy Windows Forms projektet MiniWord néven.
- Elhelyeztél és elneveztél egy RichTextBoxot és egy Labelt.
- Érted az eseményvezérelt működés alapgondolatát.
- A
TextChangedeseménnyel élő karakterszámlálót készítettél. - Tudod, miben különbözik a
Textés azRtf. - Tudod, hogy a sortörés is karakternek számít.
Következő lecke: fájl megnyitása
A MiniWord már számol, de egyelőre csak a saját szövegét ismeri. A következő leckében megtanítjuk RTF és TXT fájlokat megnyitni az OpenFileDialog segítségével.






