Grafikus C# – Windows Forms tanfolyam › 2.11 lecke Windows Forms · 2.11 lecke Egy igazi szövegszerkesztő mindig megmutatja, hol áll a kurzor, és a gombjai követik a kijelölt szöveg formázását: ha félkövér szóra állsz, a félkövér gomb „benyomva” látszik. Ebben a leckében a MiniWordöt ilyen élő állapotjelzéssel egészítjük ki a SelectionChanged esemény segítségével.Kijelölés és a SelectionChanged esemény

A lecke végére
- érted, mikor fut le a
SelectionChangedesemény; - kiírod a kurzor sorát, oszlopát és a kijelölés hosszát;
- a formázógombok színe követi a kijelölt szöveg stílusát;
- a betűtípus és méret listák is a kijelölést mutatják;
- érted a visszacsatolás hibáját, és kivéded egy jelzőváltozóval (flag);
- felismered a leggyakoribb hibákat.
Mielőtt elkezded
Ehhez a leckéhez kell a MiniWord a 2.10 lecke után, a ComboBox (2.5) és a mező fogalma (1.12 lecke).
Mikor fut le a SelectionChanged?
A RichTextBox SelectionChanged eseménye akkor fut le, amikor a kijelölés vagy a kurzor helye megváltozik: kattintáskor, a nyílbillentyűk használatakor, szöveg kijelölésekor és gépeléskor is (hiszen a kurzor ilyenkor továbblép). Ugyanúgy hozható létre, mint a többi esemény: Properties ablak, villám ikon (Events), dupla kattintás a SelectionChanged sorra.
Jósolj!
Egy szóra duplán kattintasz (kijelöli), majd megnyomod a jobbra nyilat. Hányszor fut le a SelectionChanged és a TextChanged?
Jóslat ellenőrzése
A SelectionChanged kétszer fut le (a duplakattintás kijelöléskor, majd a nyílbillentyűnél, mert a kijelölés megszűnik és a kurzor mozdul). A TextChanged egyszer sem, mert a szöveg nem változott.
Sor, oszlop és kijelölés kijelzése
Tegyél a MiniWord ablakának aljára egy lblAllapot feliratot, és írd meg a SelectionChanged eseménykezelőt:
private void rtbDokumentum_SelectionChanged(object sender, EventArgs e)
{
int kurzor = rtbDokumentum.SelectionStart;
int sor = rtbDokumentum.GetLineFromCharIndex(kurzor);
int oszlop = kurzor - rtbDokumentum.GetFirstCharIndexFromLine(sor);
lblAllapot.Text = $"Sor: {sor + 1}, Oszlop: {oszlop + 1}, Kijelölve: {rtbDokumentum.SelectionLength} karakter";
}A sor a képernyőn látható sor
A GetLineFromCharIndex a sorokat úgy számolja, ahogy a szövegdobozban megjelennek. Ha egy hosszú bekezdés az ablak szélén több sorba tör, a törés után új sornak számít. Ez a Wordhöz hasonló viselkedés, és a sorszám az ablak átméretezésekor megváltozhat.
Jósolj!
A szöveg: Alma Enter körte. A kurzor a „körte” szó „r” betűje előtt áll. Mit ír ki a felirat sorra és oszlopra?
Jóslat ellenőrzése
Sor: 2, Oszlop: 3. A „körte” a második sorban van, és az „r” előtt két karakter áll (k, ö), tehát a kurzor a harmadik oszlopban van. (A számlálás a belső 0-ról indul, ezért a kiírásnál az + 1 kell.)
Mit tegyél ide: a MiniWord alsó sora a „Sor: 2, Oszlop: 3, Kijelölve: 0 karakter” felirattal, felette a szöveg és a kurzor.Javasolt fájlnév: winforms-2-11-allapotsor.webp · Alt szöveg: A MiniWord állapotsora a kurzor sorával és oszlopával
A formázógombok követik a kijelölést
A SelectionFont tulajdonságból kiolvashatjuk, hogy a kijelölt szöveg félkövér, dőlt vagy aláhúzott-e (2.4 lecke). A Font objektumnak vannak olvasható tulajdonságai: Bold, Italic, Underline, amelyek igaz/hamis értéket adnak. A gomb hátterét ennek megfelelően színezzük:
private void GombokFrissitese()
{
Font f = rtbDokumentum.SelectionFont;
if (f == null)
{
return;
}
btnFelkover.BackColor = f.Bold ? Color.LightSkyBlue : SystemColors.Control;
btnDolt.BackColor = f.Italic ? Color.LightSkyBlue : SystemColors.Control;
btnAlahuzott.BackColor = f.Underline ? Color.LightSkyBlue : SystemColors.Control;
}if–else helyett: ha a stílus igaz, világoskék a gomb, különben az alapszín.A SelectionChanged eseménykezelőben hívd meg a GombokFrissitese() metódust. A betűtípus- és méretlistákat is érdemes frissíteni, ehhez azonban vigyázni kell, ahogy a következő szakasz mutatja.
Jósolj!
Félkövér szóra kattintasz. Milyen színű lesz a félkövér (F) gomb? És a dőlt (D) gomb, ha a szó nem dőlt?
Jóslat ellenőrzése
Az F gomb világoskék lesz, a D gomb pedig az alapszínű, mert a Bold igaz, az Italic pedig hamis.
Mit tegyél ide: a MiniWord felső sora, amelyben egy félkövér szóra kattintva az F gomb világoskék, a D és az A gomb pedig alapszínű.Javasolt fájlnév: winforms-2-11-gombok-kovetes.webp · Alt szöveg: A félkövér gomb kiemelve egy félkövér szó kijelölésekor
A visszacsatolás hibája
Szeretnénk, hogy a betűtípus- és méretlista is mutassa a kijelölés értékét. A kézenfekvő megoldás: a SelectionChanged eseményben beállítjuk a listák szövegét. De itt egy veszélyes hurok lappang:
A lista átállítása kiváltja a SelectedIndexChanged eseményt (2.5 lecke), amely a kijelölt szövegre alkalmazza a listában látható betűtípust. Ha a kijelölés vegyes formázású vagy a lista értéke nem pontosan egyezik, a program véletlenül átformázhatja a szöveget, amelyre csak rákattintottál.
A megoldás egy jelzőváltozó (angolul flag): egy bool típusú mező, amely megmondja, hogy éppen a program frissíti-e a listát, és nem a felhasználó választ belőle.
private bool frissites = false;
private void rtbDokumentum_SelectionChanged(object sender, EventArgs e)
{
Font f = rtbDokumentum.SelectionFont;
if (f != null)
{
frissites = true;
cmbBetutipus.Text = f.FontFamily.Name;
cmbMeret.Text = f.Size.ToString();
frissites = false;
}
GombokFrissitese();
}
private void cmbBetutipus_SelectedIndexChanged(object sender, EventArgs e)
{
if (frissites)
{
return;
}
// ... a 2.5 leckében megírt kód ...
}
private void cmbMeret_SelectedIndexChanged(object sender, EventArgs e)
{
if (frissites)
{
return;
}
// ... a 2.5 leckében megírt kód ...
}Arial).Gyakori minta
Ha egy vezérlő értékét a program állítja be, és a vezérlő eseménye ettől lefut, a jelzőváltozós védelem általános megoldás. Később más programoknál is találkozol vele.
Jósolj!
A frissites jelző nélkül egy Arial és egy Verdana szóból álló szövegben az Arial szóra kattintasz. Mi történhet a kijelölt szóval?
Jóslat ellenőrzése
A SelectionChanged átállítja a listát, amelynek SelectedIndexChanged eseménye lefut, és a kijelölésre alkalmazza a lista értékét. Ez a leírt esetben ugyanaz a betűtípus, tehát nem látszik változás, de vegyes méret vagy stílus esetén az átállítás módosíthatja a szöveg formázását. A jelzőváltozó megakadályozza.
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. Átformázódik a szöveg
Egy szóra kattintasz, és a szöveg formázása váratlanul megváltozik. A lista átállítása kiváltja a Ok és javítás
SelectedIndexChanged eseményt, amely formáz. Használd a frissites jelzőváltozót, és a lista eseménykezelőinek elején lépj ki, ha igaz.
2. NullReferenceException
cmbBetutipus.Text = rtbDokumentum.SelectionFont.FontFamily.Name;Hiba és javítás
Futás közbeni hiba, ha vegyes a kijelölés, mert a SelectionFont ilyenkor null. Mentsd el egy változóba, és ellenőrizd: if (f != null).
3. Az oszlop eggyel kevesebb
A szöveg elején álló kurzornál a felirat „Oszlop: 0” értéket mutat. A program 0-tól számol, az emberek 1-től. A kiíráskor adj hozzá egyet: Ok és javítás
oszlop + 1, és ugyanígy a sorhoz is.
4. A felirat csak kattintásra frissül
A nyílbillentyűvel mozgatod a kurzort, de a sor és az oszlop nem változik. A kódot valószínűleg a Ok és javítás
Click eseményhez kötötted, nem a SelectionChanged eseményhez. Billentyűvel mozgatásnál csak a SelectionChanged fut le.
5. A gombok színe nem változik vissza
if (f.Bold)
{
btnFelkover.BackColor = Color.LightSkyBlue;
}Hiba és javítás
Rossz működés: a gomb kékre vált, de nem állítod vissza az alapszínre, amikor nem félkövér a szöveg. Adj hozzá else ágat, vagy használd a rövid feltétel ? igaz : hamis formát.
Mini projekt: állapotsor a MiniWordben
Építsd be a MiniWordbe az élő állapotjelzést:
- Az ablak aljára tedd az
lblAllapotfeliratot a sor, oszlop és kijelölés kiírásához. - Add hozzá a
GombokFrissitese()metódust, hogy az F, D, A gombok kövessék a stílust. - A betűtípus és méret lista mutassa a kijelölés értékét a
frissitesjelzővel védve. - Próbáld ki: kattints félkövér, dőlt, nagy és kis betűs szövegekre. Kattints vegyes kijelölésre is.
Mit tegyél ide: a MiniWord egy félkövér, Verdana betűtípusú szóra kattintva: az F gomb világoskék, a betűtípus listában a Verdana látszik, az alsó sorban pedig a sor és az oszlop száma.Javasolt fájlnév: winforms-2-11-miniword-allapot.webp · Alt szöveg: A MiniWord a kurzor helyén álló szöveg formázását mutatja
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. Igazítás kijelzése
Az állapotsor végén jelenjen meg a kurzor bekezdésének igazítása is, például: Igazítás: Center. Az igazítás (Left, Center, Right) felsorolás értéke. A sorkizárt bekezdéseket ez a tulajdonság nem ismeri fel.Egy lehetséges megoldás
lblAllapot.Text = lblAllapot.Text + $", Igazítás: {rtbDokumentum.SelectionAlignment}";
2. Betűszín jelzése
Tegyél az állapotsorba egy A pnlSzin kis panelt vagy feliratot, amelynek a háttere a kijelölt szöveg színe.Egy lehetséges megoldás
pnlSzin.BackColor = rtbDokumentum.SelectionColor;SelectionColor a kijelölt szöveg betűszíne. A pnlSzin lehet egy kis Panel vezérlő. Vegyes színű kijelölésnél az érték nem határozható meg.
3. Kijelölt szó
Ha van kijelölt szöveg, az állapotsor mutassa meg az első 20 karakterét: Kijelölt: „alma körte”.Egy lehetséges megoldás
string kijelolt = rtbDokumentum.SelectedText;
if (kijelolt.Length > 20)
{
kijelolt = kijelolt.Substring(0, 20) + "...";
}
if (kijelolt.Length > 0)
{
lblAllapot.Text = lblAllapot.Text + $" | Kijelölt: {kijelolt}";
}
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. A feladatokhoz a MiniWord rtbDokumentum RichTextBoxa és egy lblAllapot felirat kell. A SelectionChanged eseménykezelőbe kerül minden kód. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Hányadik sor?
Az állapotsor mutassa: Sor: 3 / 10, vagyis a kurzor sorát és az összes sor számát. A Megoldás megnyitása
GetLineFromCharIndex a kurzor sorát adja (0-tól számolva), ezért adunk hozzá egyet. A sorok számához elég a Lines hossza, de a tördelt sorokat a GetLineFromCharIndex a végpozícióra is megadja.private void rtbDokumentum_SelectionChanged(object sender, EventArgs e)
{
int sor = rtbDokumentum.GetLineFromCharIndex(rtbDokumentum.SelectionStart) + 1;
int osszes = rtbDokumentum.GetLineFromCharIndex(rtbDokumentum.TextLength) + 1;
lblAllapot.Text = $"Sor: {sor} / {osszes}";
}
2. Kijelölt karakterek
Ha van kijelölt szöveg, az állapotsor mutassa a hosszát: 12 karakter kijelölve. Ha nincs, legyen üres. A Megoldás megnyitása
SelectionLength a kijelölt karakterek száma. Nulla esetén nincs kijelölés, ilyenkor üres szöveget írunk ki.private void rtbDokumentum_SelectionChanged(object sender, EventArgs e)
{
if (rtbDokumentum.SelectionLength > 0)
{
lblAllapot.Text = $"{rtbDokumentum.SelectionLength} karakter kijelölve";
}
else
{
lblAllapot.Text = "";
}
}
Közepes szint
3. A félkövér gomb követi a kijelölést
A A btnFelkover gomb háttere legyen világoskék, ha a kijelölt szöveg félkövér, egyébként az alapszín.Megoldás megnyitása
SelectionFont.Bold igaz, ha félkövér a szöveg. Vegyes kijelölésnél a SelectionFont null, ilyenkor nem módosítunk semmit.private void rtbDokumentum_SelectionChanged(object sender, EventArgs e)
{
Font f = rtbDokumentum.SelectionFont;
if (f == null)
{
return;
}
btnFelkover.BackColor = f.Bold ? Color.LightSkyBlue : SystemColors.Control;
}
4. Védelem a visszacsatolás ellen
A Egy cmbMeret lista mutassa a kijelölt szöveg méretét. Hogyan írod meg úgy, hogy a lista átállítása ne formázza át a szöveget?Megoldás megnyitása
bool jelzőváltozó megjegyzi, hogy a program frissít-e. Ha igen, a lista SelectedIndexChanged eseménye azonnal kilép.private bool frissites = false;
private void rtbDokumentum_SelectionChanged(object sender, EventArgs e)
{
Font f = rtbDokumentum.SelectionFont;
if (f != null)
{
frissites = true;
cmbMeret.Text = f.Size.ToString();
frissites = false;
}
}
private void cmbMeret_SelectedIndexChanged(object sender, EventArgs e)
{
if (frissites)
{
return;
}
// a méretváltoztatás kódja
}
Kihívás szint
5. Betűtípus és méret az állapotsorban
Az állapotsor mutassa a kijelölt szöveg betűtípusát és méretét: Arial, 12 pt. Vegyes kijelölésnél: Vegyes formázás. A Megoldás megnyitása
FontFamily.Name a betűcsalád neve, a Size a méret. A null érték vegyes kijelölést jelent.private void rtbDokumentum_SelectionChanged(object sender, EventArgs e)
{
Font f = rtbDokumentum.SelectionFont;
if (f == null)
{
lblAllapot.Text = "Vegyes formázás";
}
else
{
lblAllapot.Text = $"{f.FontFamily.Name}, {f.Size} pt";
}
}
6. Hol tartasz a dokumentumban?
Az állapotsor mutassa százalékban, hogy a kurzor a dokumentum hányadik százalékánál áll: 42 %. Üres dokumentumnál ne legyen osztás nullával. A szorzást az osztás előtt végezzük (Megoldás megnyitása
100 * hely / hossz), mert az egész számok osztása a tizedest levágja. A Math.Max(1, ...) megakadályozza, hogy a nevező nulla legyen.private void rtbDokumentum_SelectionChanged(object sender, EventArgs e)
{
int hossz = Math.Max(1, rtbDokumentum.TextLength);
int szazalek = 100 * rtbDokumentum.SelectionStart / hossz;
lblAllapot.Text = szazalek + " %";
}
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. Amikor a kurzor vagy a kijelölés helye megváltozik, a szöveg változása nélkül is. A TextChanged a szöveg, a SelectionChanged a kurzor és a kijelölés változásakor fut le. A Ha a program átállítja egy vezérlő értékét, és ettől annak eseménye lefut, az pedig újabb módosítást végez. Így a program véletlenül átformázhatja a szöveget. Megmondja, hogy éppen a program frissíti-e a vezérlőt, és nem a felhasználó választott. Az eseménykezelő elején kilépünk, ha igaz. Vegyes formázású kijelölésnél nincs egyetlen betűtípus, ezért az érték 1. Mikor fut le a SelectionChanged?
2. Mi a különbség a TextChanged és a SelectionChanged között?
3. Hogyan számolod ki a sort és az oszlopot?
GetLineFromCharIndex adja a sort, az oszlop pedig a SelectionStart és a sor első karakterének (GetFirstCharIndexFromLine) különbsége. A kiíráskor mindkettőhöz +1 kell.4. Mi a visszacsatolási hiba?
5. Mire való a jelzőváltozó (flag)?
6. Miért kell a SelectionFont null értékét ellenőrizni?
null, és a használata hibát okozna.
Mit tudsz már?
- Érted a SelectionChanged esemény működését.
- Kiírod a kurzor sorát, oszlopát és a kijelölés hosszát.
- A formázógombokat és listákat a kijelöléshez igazítod.
- Jelzőváltozóval kivédöd a visszacsatolást.
Következő lecke: Undo, Redo, Copy, Cut és Paste
Az állapotjelzés kész. A következő leckében a szerkesztés alapműveleteit építjük be.




