Grafikus C# – Windows Forms tanfolyam › 6.9 lecke

Windows Forms · 6.9 lecke · hozzáférhetőség

Hozzáférhetőség: kontraszt, feliratok és használhatóság

A program akkor jó, ha mindenki tudja használni: a gyengén látó, a színtévesztő, a csak billentyűzettel dolgozó, a képernyőolvasót használó felhasználó, és az is, aki napfényben, egy kézzel, siet. Ezt hívjuk hozzáférhetőségnek (accessibility, röviden a11y). Tanárként különösen fontos: egy osztályban mindig vannak diákok különleges igényekkel. Ebben a leckében megtanulod a színkontraszt számítását, a nem csak színnel való jelzést, a vezérlők feliratozását és az AccessibleName használatát, a magas kontrasztú mód kezelését, és elkészíted egy egyszerű ellenőrző programot, amely egy űrlap hiányosságait feltárja.

  • kb. 100 perc
  • közepes szint
  • hozzáférhetőség
Diáklány C# programot készít laptopon

A lecke végére

  • kiszámolod két szín kontrasztarányát, és tudod a megfelelőségi küszöböket (4,5 : 1 és 3 : 1);
  • az információt nem csak színnel jelzed (szöveg, jel, alak);
  • minden beviteli mezőnek címkét adsz, és az AccessibleName, AccessibleDescription értékekkel segíted a képernyőolvasót;
  • a SystemColors és a SystemInformation.HighContrast segítségével kezeled a magas kontrasztú módot;
  • biztosítod a billentyűzetes használatot és az érthető üzeneteket;
  • eszközökkel és egyszerű teszttel ellenőrzöd a hozzáférhetőséget.

Mielőtt elkezded

Ehhez a leckéhez a 6.6 lecke (fókusz, címkék, ErrorProvider), a 6.8 lecke (betűméret, tartalomhoz igazodás), az 5.8 lecke (rekurzív bejárás) és az 1.11 lecke (ToolTip) szükséges. Új projektben próbáld ki a példákat.

6.8 DPI és betűméret →

Miért fontos, és mit jelent?

A hozzáférhetőség nem „extra”, hanem a használhatóság része. Sokan érintettek: a látássérültek (gyengénlátók, vakok), a színtévesztők (a férfiak mintegy 8%-a valamilyen mértékben), a mozgássérültek (akik nem tudnak egeret használni), a hallássérültek (akik nem hallják a hangjelzéseket), és bárki, aki ideiglenes helyzetben van (törött kéz, erős napfény, fáradtság). A nemzetközi irányelv, a WCAG (Web Content Accessibility Guidelines) négy alapelvet fogalmaz meg, amelyek asztali programokra is vonatkoztathatók:

AlapelvJelentésePélda Windows Formsban
ÉrzékelhetőAz információ többféleképp is megjelenik.Hibaüzenet szöveggel és jellel, nem csak piros színnel.
MűködtethetőMinden funkció billentyűzettel is elérhető.Logikus Tab sorrend, mnemonikus betűk, nincs fókuszcsapda.
ÉrthetőEgyértelmű feliratok és üzenetek.„A név kötelező.” a „Hiba 17” helyett.
RobusztusEgyüttműködik a segítő eszközökkel.Valódi vezérlők használata, AccessibleName.

A Windows Forms vezérlők alapból hozzáférhetők

A beépített vezérlők (Button, TextBox, CheckBox, ComboBox) a Windows UI Automation és MSAA technológiáin keresztül kapcsolódnak a képernyőolvasókhoz (Narrator, NVDA, JAWS): ezek tudják, mi a vezérlő neve, típusa és állapota. A hozzáférhetőségi hibák többsége abból jön, hogy a fejlesztő kikerüli ezeket: saját rajzolású „gombot” használ, kép alapú kattintható területet, vagy a vezérlőnek nem ad nevet.

Kontraszt: számoljuk ki!

A szöveg és a háttér közötti kontrasztarány 1 : 1 (azonos szín) és 21 : 1 (fekete a fehéren) között van. A WCAG ajánlása: normál szövegnél legalább 4,5 : 1, nagy szövegnél (legalább 18 pont, vagy 14 pontos félkövér) és a kezelőelemek vizuális jelzéseinél legalább 3 : 1. A számítás a színek relatív fényességén alapul:

Hozzaferhetoseg.csC#
public static class Hozzaferhetoseg
{
// egy színösszetevő (0–255) átszámítása lineáris fényességre
private static double Linearis(int ertek)
{
double s = ertek / 255.0;

return s <= 0.03928 ? s / 12.92 : Math.Pow((s + 0.055) / 1.055, 2.4);
}

// a szín relatív fényessége (0 = fekete, 1 = fehér)
public static double Fenyero(Color szin)
{
return 0.2126 * Linearis(szin.R) + 0.7152 * Linearis(szin.G) + 0.0722 * Linearis(szin.B);
}

// a két szín kontrasztaránya (1 és 21 között)
public static double Kontraszt(Color a, Color b)
{
double l1 = Fenyero(a);
double l2 = Fenyero(b);

double vilagos = Math.Max(l1, l2);
double sotet = Math.Min(l1, l2);

return (vilagos + 0.05) / (sotet + 0.05);
}
}

// használat:
double arany = Hozzaferhetoseg.Kontraszt(Color.Black, Color.White); // 21
double szurke = Hozzaferhetoseg.Kontraszt(Color.FromArgb(118, 118, 118), Color.White); // kb. 4,54
SzövegszínHáttérKontraszt (kb.)Normál szöveg (4,5)Nagy szöveg (3)
fekete #000000fehér21 : 1megfelelmegfelel
sötétszürke #767676fehér4,54 : 1éppen megfelelmegfelel
szürke #777777fehér4,48 : 1nem felel meg (hajszállal)megfelel
világosszürke #AAAAAAfehér2,32 : 1nem felel megnem felel meg
fehérlila #6840A5kb. 7,4 : 1megfelelmegfelel
Miért kell a számítás?A szemünk nem lineárisan érzékeli a fényességet, ezért a „látszik” megítélése megtévesztő: a nagy képernyőn, nyugodt körülmények között jónak tűnő halvány szürke szöveg a napfényes teremben vagy gyengébb látással olvashatatlan.
A számok viszonylagosakA 4,5 : 1 egy küszöb, nem a tökéletes érték. Törekedj magasabbra, főleg kis betűméretnél. Az értékek a betűvastagságtól és mérettől is függenek.
Halvány szövegA letiltott (Enabled = false) vezérlők szövege szándékosan halvány, ezekre a küszöb nem vonatkozik. A súgószövegek, a helykitöltők és a tipp-szövegek viszont igen: ne legyenek túl halványak.
Online eszközökA kontraszt ellenőrzésére számos ingyenes online számológép van (keress: „contrast checker”), és a böngészők fejlesztői eszközei is megmutatják. A saját számításod ugyanazt adja, és programba építhető.

Jósolj!

Egy űrlap súgószövege #999999 (világosszürke) fehér háttéren, 9 pontos betűvel. Megfelel-e a 4,5 : 1 küszöbnek, és mi a kontrasztarány nagyságrendje?

Jóslat ellenőrzése

A #999999 fehéren kb. 2,8 : 1: nem felel meg sem a normál szöveg (4,5), sem a nagy szöveg (3) küszöbének. Az ilyen szürke szöveg népszerű, mert „elegáns”, de sokaknak olvashatatlan. Sötétítsd legalább #767676 értékig.

Ne csak színnel jelezz!

A piros–zöld színtévesztő felhasználó a piros hibaszínt és a zöld „rendben” színt nem különbözteti meg. A színt soha ne használd egyedüli információhordozóként: adj mellé szöveget, jelet (ikon, szimbólum) vagy alakot:

RosszJó
A kötelező mezők pirosak.A kötelező mezők címkéjén * jel és „(kötelező)” szöveg.
A hibás mező háttere piros.Hibaikon (ErrorProvider) és hibaüzenet-szöveg a mező mellett.
Állapot: zöld pont = kész, piros pont = hiba.Szöveg („Kész”, „Hiba”) vagy különböző jelek (✔, ✖) a színek mellett.
A grafikonon csak a színek különböztetik meg a sorokat.Eltérő jelölők (kör, négyzet) vagy mintázat, és felirat a vonalon.
Form1.csC#
private void Allapot(bool rendben, string uzenet)
{
// szín + jel + szöveg együtt: a szín csak erősítés
lblAllapot.Text = (rendben ? "✔ " : "✖ ") + uzenet;
lblAllapot.ForeColor = rendben ? Color.FromArgb(0, 110, 50) : Color.FromArgb(170, 20, 20); // sötét árnyalatok: jó kontraszt fehéren
}

private void btnMent_Click(object sender, EventArgs e)
{
if (txtNev.Text.Trim().Length == 0)
{
epHiba.SetError(txtNev, "A név kötelező."); // ikon + szöveg a mező mellett
Allapot(false, "A név kötelező.");
txtNev.Focus();
return;
}

epHiba.SetError(txtNev, "");
Allapot(true, "Mentve.");
}
Szimulálj színtévesztéstEgy képernyőkép szürkeárnyalatossá alakítása megmutatja, mi vész el, ha csak a szín hordoz információt. Ha a szürke képen is érthető a felület, jó úton jársz.
Biztonságos színpárokA kék–narancs, a kék–sárga és a sötét–világos kombinációk a legtöbb színtévesztőnek is jól elkülönülnek. A piros–zöld és a zöld–barna kerülendő egymás mellett jelzésként.
Hang is csak kiegészítésHa a program egy hangjelzéssel figyelmeztet (SystemSounds), mellé kell vizuális jelzés is: a hallássérült vagy a némított hangszórójú felhasználó másképp nem venné észre.
IdőkorlátA csak néhány másodpercig látszó üzenet (átmeneti felugró, automatikusan eltűnő felirat) elmaradhat. Fontos üzenet maradjon látható, amíg a felhasználó el nem fogadja.

Jósolj!

Egy színtévesztő felhasználó a hibás mezőt piros háttérrel látja jelölve, de a jelzés nála szürkének tűnik, ugyanolyannak, mint a többi mező. A mellette lévő ErrorProvider ikon és szöveg is hiányzik. Mit vesz észre?

Jóslat ellenőrzése

Semmit: a hibát nem érzékeli, és az űrlap „megáll”, mert a mentés nem sikerül, de ő nem tudja, miért. A hibát több csatornán kell jelezni: ikon, szöveges magyarázat és a fókusz áthelyezése a hibás mezőre (a képernyőolvasó is ezt olvassa fel).

Feliratok, AccessibleName és billentyűzet

A képernyőolvasó a vezérlőt a nevével mondja be. A név a vezérlő Text tulajdonságából jön (gomb, jelölőnégyzet), vagy a hozzá tartozó címkéből. Ha nincs ilyen (ikonos gomb, kép, a címke nélküli mező), a név hiányzik, és a felhasználó csak annyit hall: „gomb”. Három tulajdonság segít:

TulajdonságMire való?
AccessibleNameA vezérlő neve a segítő eszköz számára („Mentés”, „Keresés”).
AccessibleDescriptionHosszabb leírás („Elmenti a dokumentumot a jelenlegi fájlba”).
AccessibleRoleA vezérlő szerepe (PushButton, Text, Link…): általában a vezérlő típusa magától megadja, csak saját rajzolású vezérlőknél kell.
Form1.csC#
private void Form1_Load(object sender, EventArgs e)
{
// ikonos gomb: nincs szövege, ezért kell név és súgó
btnMent.AccessibleName = "Mentés";
btnMent.AccessibleDescription = "Elmenti a dokumentumot.";
ttSugo.SetToolTip(btnMent, "Mentés (Ctrl+S)"); // a látó felhasználónak

// címke nélküli keresőmező
txtKereso.AccessibleName = "Keresés a jegyzetek között";

// dekoratív kép: a képernyőolvasó kihagyhatja
pbDiszito.AccessibleRole = AccessibleRole.None;

// informatív kép: szöveges alternatíva
pbGrafikon.AccessibleName = "Az eladások havi alakulása: júniusban a legmagasabb.";
}
Mindig legyen címkeMinden beviteli mezőhöz tartozzon látható Label, amely a tabulátorsorrendben közvetlenül a mező előtt áll (6.6 lecke): a képernyőolvasó a címkét a mező nevének tekinti. A mezőbe írt „halvány tipp” (placeholder) nem helyettesíti a címkét: eltűnik gépeléskor.
Ikonos gombokIkon mellé írj feliratot, vagy legalább ToolTip és AccessibleName. A ToolTip a látó felhasználónak, az AccessibleName a képernyőolvasónak szól: mindkettő kell.
Érthető üzenetekA hibaüzenet mondja meg, mi a hiba és mit tegyen a felhasználó: „Az e-mail címnek tartalmaznia kell a @ jelet.” hasznos, a „Érvénytelen bevitel.” nem.
Valódi vezérlőt használjEgy kattintható PictureBox a billentyűzettel nem érhető el, és nincs neve a képernyőolvasónak. Gombra (Button) alakítható a megjelenése (FlatStyle, kép), így az elérhetőség megmarad.

Jósolj!

Egy eszköztáron három ikonos Button van (szöveg nélkül), AccessibleName nélkül, és nincs ToolTip sem. Mit hall a képernyőolvasót használó felhasználó a gombokról?

Jóslat ellenőrzése

Csak annyit, hogy „gomb” (háromszor), anélkül, hogy tudná, melyik mit csinál. A látó felhasználó az ikonról kitalálja, a képernyőolvasós nem. Két mondat kód (AccessibleName minden gombra) megoldja. A tervezőben a Properties → Accessibility csoportban is beállítható.

Magas kontrasztú mód és rendszerszínek

A Windows magas kontrasztú témái (Beállítások → Kisegítő lehetőségek → Kontrasztos témák) a rendszerszíneket (SystemColors) átállítják: sötét háttér, fényes szöveg, élénk kiemelés. A rendszerszíneket használó vezérlők ezt automatikusan követik. Ha a vezérlők színét te állítod fix értékekre (Color.WhiteSmoke, Color.FromArgb(...)), a felhasználó témája nem érvényesül, és a program olvashatatlan lehet.

Form1.csC#
// rendszerszínek használata fix színek helyett
lblCim.ForeColor = SystemColors.ControlText;
pnlSav.BackColor = SystemColors.Control;
txtMezo.BackColor = SystemColors.Window;
txtMezo.ForeColor = SystemColors.WindowText;
pnlKiemelt.BackColor = SystemColors.Highlight;
lblKiemelt.ForeColor = SystemColors.HighlightText;

// saját színek csak, ha nincs magas kontraszt
private void TemaAlkalmaz(Control szulo)
{
foreach (Control c in szulo.Controls)
{
if (c is Label && c.Tag is string cimke && cimke == "kiemelt")
{
if (SystemInformation.HighContrast)
{
c.ForeColor = SystemColors.HighlightText; // a felhasználó témája
c.BackColor = SystemColors.Highlight;
}
else
{
c.ForeColor = Color.White; // a program saját arculata
c.BackColor = Color.FromArgb(104, 64, 165);
}
}

TemaAlkalmaz(c);
}
}
SystemInformation.HighContrastIgaz, ha a felhasználó magas kontrasztú témát használ. Ilyenkor a saját színeket hagyd el, és a rendszerszíneket használd.
RendszerszínekA SystemColors osztály értékei (Control, ControlText, Window, WindowText, Highlight, HighlightText, GrayText) a felhasználó témáját követik: sötét módban is helyesek.
Téma váltása futás közbenA témaváltásra a Microsoft.Win32.SystemEvents.UserPreferenceChanged esemény figyelmeztet (a rendszerbeállítás módosult). Ezt a haladóbb lehetőséget most csak megemlítjük. Ha mégis használod, az 5.7 leckében tanultak szerint a statikus eseményről le is kell iratkoznod, amikor az ablak bezárul.
Saját arculat és kontrasztMárkaszín használható, de a szöveg és háttér kontrasztja legyen megfelelő (a leckebeli Kontraszt metódussal ellenőrizhető).

Jósolj!

A program címkéi mind fix Color.DimGray színűek fehér háttéren. A felhasználó magas kontrasztú (fekete hátterű) témát kapcsol be. Mit lát?

Jóslat ellenőrzése

Attól függ, mely részek követik a rendszerszíneket: az alapértelmezett vezérlők háttere feketére vált, a fix DimGray színű szöveg azonban sötétszürke marad a fekete háttéren, és gyakorlatilag olvashatatlan (a kontrasztja nagyon alacsony). Ezért ne állítsd fixre a szöveg- és háttérszíneket, ahol nem feltétlenül szükséges: az alapértelmezés (SystemColors) a témákkal együtt él.

📷 Képernyőkép helye

Mit tegyél ide: ugyanaz az űrlap normál és magas kontrasztú témában, a hozzáférhető elrendezés mindkettőn olvasható.Javasolt fájlnév: winforms-6-9-kontraszt.webp · Alt szöveg: Űrlap normál és magas kontrasztú témában

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. A hiba csak színnel van jelezve

txtNev.BackColor = Color.Red;   // csak a háttér piros
Hiba és javítás

A színtévesztő és a képernyőolvasós felhasználó nem veszi észre. Adj mellé ErrorProvider ikont és szöveges üzenetet, és tedd a fókuszt a hibás mezőre.

2. Olvashatatlan halvány szöveg

A súgószöveg világosszürke a fehér háttéren.

Ok és javítás

A kontraszt 2–3 : 1 körüli, a 4,5 : 1 küszöb alatt. Sötétítsd legalább #767676 értékre, és ellenőrizd a Kontraszt metódussal.

3. Az ikonos gombnak nincs neve

A képernyőolvasó csak annyit mond: „gomb”.

Ok és javítás

Hiányzik az AccessibleName és a szöveg. Adj nevet és ToolTip-et, vagy írj feliratot az ikon mellé.

4. Magas kontrasztú témában olvashatatlan a program

A felhasználó témája nem látszik, a szöveg eltűnik.

Ok és javítás

A színeket fixre állítottad. Használd a SystemColors értékeit, vagy a SystemInformation.HighContrast vizsgálattal hagyd el a saját színeket.

5. A kattintható kép nem érhető el billentyűzettel

pbTorol.Click += (s, e) => Torol();   // PictureBox: nincs fókusz, nincs név
Hiba és javítás

A PictureBox nem kap fókuszt, és nincs neve. Használj Button vezérlőt képpel (FlatStyle = Flat, Image), amely a billentyűzettel és a képernyőolvasóval is működik.

6. A placeholder helyettesíti a címkét

A szövegmezőbe halványan „Név” szerepel, de címke nincs mellette.

Ok és javítás

A helykitöltő szöveg gépeléskor eltűnik, és a segítő eszközök nem mindig olvassák. Mindig legyen látható Label a mező mellett (vagy fölött), a helykitöltő legfeljebb kiegészítés.

Mini projekt: hozzáférhetőségi ellenőrző

Készíts két részes programot: egy kontrasztszámolót és egy egyszerű űrlap-ellenőrzőt:

  1. Kontrasztszámoló (tabKontraszt lap): két színválasztó gomb (btnSzoveg, btnHatter, ColorDialog), egy lblMinta címke a kiválasztott szín- és háttérszínnel, egy lblArany (Kontraszt: 4,54 : 1) és két lblNormal, lblNagy jelzés a megfelelésre, színnel és jellel (✔ / ✖). A Kontraszt metódus a leckéből.
  2. Űrlap-ellenőrző (tabEllenorzo lap): egy pnlMinta panelen egy mintaűrlap szándékosan hibás elemekkel (egy címke nélküli TextBox; egy szöveg és név nélküli gomb; egy 7 pontos betűjű címke; egy rendben lévő címke–mező pár; egy világosszürke szöveg). Az Ellenőrzés gomb (btnEllenoriz) rekurzívan végigmegy a pnlMinta vezérlőin, és egy lstJelentes listába írja a hiányosságokat.
  3. A szabályok: (a) beviteli mező (TextBox, ComboBox, NumericUpDown) címke nélkül: nincs AccessibleName, és a tabulátorsorrendben előtte nem Label áll; (b) Button szöveg és AccessibleName nélkül; (c) betűméret 9 pont alatt; (d) szövegszín–háttér kontraszt 4,5 : 1 alatt; (e) beviteli mezőn TabStop = false.
  4. A jelentés minden sora tartalmazza a vezérlő nevét és a hiba leírását; ha nincs hiba, egy megerősítő sor (Nincs hiány.) jelenik meg. A végén összesítés: 3 hiány, 2 figyelmeztetés.
  5. A program maga is legyen hozzáférhető: minden vezérlőnek címke vagy AccessibleName, a hibák ikonnal és szöveggel, rendszerszínek, logikus Tab sorrend.
  6. Teszteld: a kontrasztszámoló ismert értékekkel (fekete/fehér = 21), az ellenőrző a mintaűrlapon, a javított mintaűrlapon (nincs hiány), a Narrator vagy a billentyűzetes használat.
Megoldás megnyitása (próbáld ki előbb önállóan!)

A címke–mező kapcsolat vizsgálata a szülő vezérlőinek TabIndex szerinti rendezésén alapul: az adott mező előtti vezérlő (a legnagyobb kisebb TabIndex a szülőn belül) legyen Label, nem üres szöveggel. A kontraszt a vezérlő ForeColor és BackColor értékéből jön (a BackColor az örökölt háttér is lehet).

Form1.cs (using System.Collections.Generic;)C#
private Color szovegSzin = Color.Black;
private Color hatterSzin = Color.White;

private void KontrasztFrissit()
{
lblMinta.ForeColor = szovegSzin;
lblMinta.BackColor = hatterSzin;

double arany = Hozzaferhetoseg.Kontraszt(szovegSzin, hatterSzin);
lblArany.Text = $"Kontraszt: {arany:0.00} : 1";

lblNormal.Text = (arany >= 4.5 ? "✔ " : "✖ ") + "Normál szöveg (4,5 : 1)";
lblNagy.Text = (arany >= 3.0 ? "✔ " : "✖ ") + "Nagy szöveg (3 : 1)";
}

private void btnSzoveg_Click(object sender, EventArgs e)
{
cdSzin.Color = szovegSzin;

if (cdSzin.ShowDialog() == DialogResult.OK)
{
szovegSzin = cdSzin.Color;
KontrasztFrissit();
}
}

private void btnHatter_Click(object sender, EventArgs e)
{
cdSzin.Color = hatterSzin;

if (cdSzin.ShowDialog() == DialogResult.OK)
{
hatterSzin = cdSzin.Color;
KontrasztFrissit();
}
}

private bool BeviteliMezo(Control c)
{
return c is TextBox || c is ComboBox || c is NumericUpDown;
}

private Control ElozoVezerlo(Control c)
{
Control elozo = null;

foreach (Control t in c.Parent.Controls)
{
if (t.TabIndex < c.TabIndex && (elozo == null || t.TabIndex > elozo.TabIndex))
{
elozo = t;
}
}

return elozo;
}

private Color ValosHatter(Control c)
{
Control t = c;

while (t != null && t.BackColor.A == 0)
{
t = t.Parent;
}

return t == null ? SystemColors.Control : t.BackColor;
}

private void Ellenoriz(Control szulo, List<string> hibak, List<string> figyelmeztetesek)
{
foreach (Control c in szulo.Controls)
{
if (BeviteliMezo(c))
{
Control elozo = ElozoVezerlo(c);
bool vanCimke = (elozo is Label && elozo.Text.Trim().Length > 0) || c.AccessibleName != null && c.AccessibleName.Length > 0;

if (!vanCimke)
{
hibak.Add($"{c.Name}: a beviteli mezőnek nincs címkéje vagy AccessibleName értéke.");
}

if (!c.TabStop)
{
hibak.Add($"{c.Name}: a mező kimarad a Tab sorrendből (TabStop = false).");
}
}

if (c is Button && c.Text.Trim().Length == 0 && (c.AccessibleName == null || c.AccessibleName.Length == 0))
{
hibak.Add($"{c.Name}: a gombnak nincs szövege és AccessibleName értéke.");
}

if ((c is Label || c is Button) && c.Font.Size < 9)
{
figyelmeztetesek.Add($"{c.Name}: kis betűméret ({c.Font.Size:0.#} pt).");
}

if (c is Label && c.Text.Trim().Length > 0)
{
double arany = Hozzaferhetoseg.Kontraszt(c.ForeColor, ValosHatter(c));

if (arany < 4.5)
{
figyelmeztetesek.Add($"{c.Name}: alacsony kontraszt ({arany:0.0} : 1).");
}
}

Ellenoriz(c, hibak, figyelmeztetesek);
}
}

private void btnEllenoriz_Click(object sender, EventArgs e)
{
List<string> hibak = new List<string>();
List<string> figyelmeztetesek = new List<string>();

Ellenoriz(pnlMinta, hibak, figyelmeztetesek);

lstJelentes.Items.Clear();

foreach (string h in hibak)
{
lstJelentes.Items.Add("✖ Hiba: " + h);
}

foreach (string f in figyelmeztetesek)
{
lstJelentes.Items.Add("⚠ Figyelmeztetés: " + f);
}

if (hibak.Count == 0 && figyelmeztetesek.Count == 0)
{
lstJelentes.Items.Add("✔ Nincs hiány.");
}

lblOsszegzes.Text = $"{hibak.Count} hiány, {figyelmeztetesek.Count} figyelmeztetés";
}
📷 Képernyőkép helye

Mit tegyél ide: az ellenőrző program: a mintaűrlap hibáinak listája (✖ és ⚠ jelekkel) és az összesítés.Javasolt fájlnév: winforms-6-9-kesz.webp · Alt szöveg: A hozzáférhetőségi ellenőrző program jelentése

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. Állapotjelző szín, jel és szöveg

Készíts állapotjelző metódust (Jelez(Allapot, szöveg)), amely sikeres, figyelmeztetés és hiba állapotot mutat színnel, jellel (✔ ⚠ ✖) és szöveggel is. Milyen színeket választasz, hogy fehér háttéren elég legyen a kontraszt?

Egy lehetséges megoldás

A színek sötét árnyalatok (a kontraszt 4,5 : 1 felett): sötétzöld, sötét borostyán, sötétvörös. Az állapotot a jel és a szöveg is hordozza, a szín csak erősít. Egy három elemű felsorolás vagy három szöveges kód elegendő az állapotokhoz.

Form1.csC#
private void Jelez(string allapot, string szoveg)
{
switch (allapot)
{
case "siker":
lblAllapot.Text = "✔ " + szoveg;
lblAllapot.ForeColor = Color.FromArgb(0, 100, 40);
break;

case "figyelmeztetes":
lblAllapot.Text = "⚠ " + szoveg;
lblAllapot.ForeColor = Color.FromArgb(150, 80, 0);
break;

default:
lblAllapot.Text = "✖ " + szoveg;
lblAllapot.ForeColor = Color.FromArgb(170, 20, 20);
break;
}
}

2. Eszköztár ikonos gombokkal

Egy FlowLayoutPanelen négy ikonos gomb áll (Új, Megnyitás, Mentés, Nyomtatás). Adj mindegyiknek AccessibleName és ToolTip értéket egyetlen ciklussal. Honnan veszed a neveket?

Egy lehetséges megoldás

A gombok Tag tulajdonsága tárolja a nevet (5.8 lecke), így a ciklus a Tagből dolgozik. A ToolTip kiegészítheti a gyorsbillentyűvel.

Form1.csC#
private void Form1_Load(object sender, EventArgs e)
{
foreach (Control c in flpEszkoztar.Controls)
{
Button gomb = c as Button;

if (gomb != null && gomb.Tag != null)
{
gomb.AccessibleName = gomb.Tag.ToString();
ttSugo.SetToolTip(gomb, gomb.Tag.ToString());
}
}
}

3. Magas kontrasztú mód követése

A program minden címkéje és panelje a saját arculati színeket használja. Írj Tema() metódust, amely magas kontrasztú módban a rendszerszíneket állítja be mindenhová (rekurzívan), és a normál módban visszaállítja a saját színeket. Hogyan tárolod az eredeti színeket?

Egy lehetséges megoldás

Az eredeti színeket a vezérlők Tag tulajdonságában sem tárolhatod (a Tag már foglalt lehet), ezért egy Dictionary<Control, Color> a megfelelő megoldás (a gyűjteményekről a 8. fejezet szól). Egyszerűbb megoldás: a saját színeket egy SajatSzinek metódus állítja be, amelyet normál módban újra hívsz.

Form1.csC#
private void Tema(Control szulo)
{
foreach (Control c in szulo.Controls)
{
if (SystemInformation.HighContrast)
{
c.BackColor = SystemColors.Window;
c.ForeColor = SystemColors.WindowText;
}
else
{
SajatSzin(c); // a program arculati színei
}

Tema(c);
}
}

private void SajatSzin(Control c)
{
if (c is Label)
{
c.ForeColor = Color.FromArgb(40, 30, 50);
}
else if (c is Panel)
{
c.BackColor = Color.FromArgb(250, 248, 252);
}
}

Gyakorlótár: 6 további feladat

Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.

Alap szint

1. Kontraszt becslése

Sorold a következő szövegszíneket fehér háttéren a kontraszt szerint csökkenően: #000000, #AAAAAA, #767676, #555555. Melyek felelnek meg a 4,5 : 1 küszöbnek?

Megoldás megnyitása

Csökkenő sorrend: #000000 (21 : 1), #555555 (kb. 7,5 : 1), #767676 (4,54 : 1), #AAAAAA (2,32 : 1). Az első három megfelel, az utolsó nem.

2. Nem csak színnel

Írj három példát arra, hogyan jelezhetsz egy hibát színen kívül is egy űrlapon.

Megoldás megnyitása

(1) Hibaikon és szöveges üzenet a mező mellett (ErrorProvider); (2) a hibás mezőre helyezett fókusz; (3) összefoglaló üzenet az űrlap tetején a hibák felsorolásával (és jellel, például ✖).

Közepes szint

3. A Kontraszt metódus használata

Írj kódot, amely egy TextBox szövegének és hátterének kontrasztját kiszámolja, és ha nem éri el a 4,5 : 1 arányt, a szövegszínt feketére vagy fehérre állítja (amelyik jobb kontrasztot ad).

Megoldás megnyitása

A fekete és a fehér szöveg kontrasztját is kiszámoljuk a háttérhez, és a nagyobbat választjuk. Ez a „tiszta” szövegszín automatikus kiválasztása (gyakran használt trükk).

Form1.csC#
private void SzovegSzinJavit(TextBox mezo)
{
if (Hozzaferhetoseg.Kontraszt(mezo.ForeColor, mezo.BackColor) >= 4.5)
{
return;
}

double fekete = Hozzaferhetoseg.Kontraszt(Color.Black, mezo.BackColor);
double feher = Hozzaferhetoseg.Kontraszt(Color.White, mezo.BackColor);

mezo.ForeColor = fekete >= feher ? Color.Black : Color.White;
}

4. AccessibleName a címke nélküli mezőn

Egy keresőmező mellett nincs címke (csak egy nagyító ikon). Mit állítasz be, hogy a mező a képernyőolvasónak érthető legyen, és mit a látó felhasználónak?

Megoldás megnyitása

A képernyőolvasónak: AccessibleName = "Keresés". A látónak: egy ToolTip, és a mezőben (kiegészítésként) halvány helykitöltő szöveg. Még jobb egy látható „Keresés:” címke.

Form1.csC#
txtKereso.AccessibleName = "Keresés";
txtKereso.AccessibleDescription = "Írd be a keresett szót, majd nyomd meg az Entert.";
ttSugo.SetToolTip(txtKereso, "Keresés (Ctrl+F)");

Kihívás szint

5. Betűméret-ellenőrzés

Bővítsd az ellenőrzőt úgy, hogy figyelmeztessen, ha egy beviteli mező vagy címke betűmérete 9 pont alatt van, és a vezérlő mérete rögzített (AutoSize = false), tehát nagyobb betűméretnél levágódhat (6.8 lecke).

Megoldás megnyitása

A két feltétel együtt jelzi a veszélyt: a kis betű és a fix méret. A Label.AutoSize tulajdonság elérhető, a TextBox esetén a magasságot a betű adja, ezért ott a Multiline értéket is érdemes vizsgálni.

Form1.csC#
// az Ellenoriz metódusban, a címkék vizsgálatánál:
Label cimke = c as Label;

if (cimke != null && !cimke.AutoSize)
{
figyelmeztetesek.Add($"{c.Name}: fix méretű címke, nagyobb betűnél a szöveg levágódhat.");
}

6. Hozzáférhetőségi ellenőrzőlista a saját projekthez

Készíts legalább 8 pontos ellenőrzőlistát (táblázat) a saját programodhoz a lecke témáiból: kontraszt, nem csak szín, címkék, AccessibleName, billentyűzet, betűméret, magas kontraszt, üzenetek. Minden ponthoz: mit ellenőrzöl, hogyan, és mi az elvárt eredmény.

Megoldás megnyitása
#EllenőrzésHogyan?Elvárt
1KontrasztSzöveg–háttér párok a Kontraszt metódussal vagy online eszközzel.Legalább 4,5 : 1 (nagy szöveg 3 : 1).
2Nem csak színnelSzürkeárnyalatos képernyőkép.Az állapotok szürkén is megkülönböztethetők.
3CímkékMinden beviteli mező mellett látható címke.Nincs címke nélküli mező.
4AccessibleNameIkonos gombok, kép nélküli elemek.Mindegyiknek van neve.
5BillentyűzetAz egész program egér nélkül.Minden elérhető, logikus Tab sorrend, nincs csapda.
6BetűméretWindows szövegméret 150%.Nincs levágott vagy átlapolt szöveg.
7Magas kontrasztKontrasztos Windows-téma.A program olvasható marad.
8ÜzenetekA hibaüzenetek átolvasása.Mindegyik megmondja a hibát és a teendőt.
9KépernyőolvasóNarrator indítása (Win+Ctrl+Enter).A vezérlők neve és típusa érthetően felolvasódik.

Gyors önellenőrzés

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

1. Mi a minimális ajánlott kontrasztarány normál szövegre?

4,5 : 1 (nagy szövegre és kezelőelemekre 3 : 1).

2. Miért ne használj csak színt információhordozónak?

A színtévesztő és a látássérült felhasználó nem érzékeli. Mellé kell szöveg, jel vagy alak.

3. Mire való az AccessibleName?

A vezérlő nevét adja a képernyőolvasónak, ha a vezérlőnek nincs szövege vagy címkéje (ikonos gomb, címke nélküli mező).

4. Miért nem helyettesíti a placeholder a címkét?

Gépeléskor eltűnik, és a segítő eszközök nem mindig olvassák. Látható címke kell.

5. Hogyan kezeled a magas kontrasztú módot?

Rendszerszíneket (SystemColors) használsz, vagy a SystemInformation.HighContrast vizsgálattal elhagyod a saját színeket.

6. Miért jobb egy Button, mint a kattintható PictureBox?

A Button kap fókuszt, billentyűzettel működtethető, és van neve a képernyőolvasónak. A PictureBox ezek egyikére sem képes.

7. Milyen kis tesztekkel ellenőrizhető a hozzáférhetőség?

Billentyűzet-teszt egér nélkül, szürkeárnyalatos kép, 150%-os szövegméret, kontrasztos téma, Narrator, és kontraszt-számolás.

Mit tudsz már?

  • Kiszámolod a színkontrasztot, és tudod a küszöbértékeket.
  • Az információt színen kívül más csatornán is jelzed.
  • Címkével, AccessibleName értékkel és érthető üzenetekkel segíted a képernyőolvasót.
  • Kezeled a magas kontrasztú módot a rendszerszínekkel.
  • Egyszerű eszközökkel és teszttel ellenőrzöd a hozzáférhetőséget.

Következő lecke: mini projekt – átméretezhető űrlap

A 6. fejezet záró projektje: egy valódi, átméretezhető, billentyűzettel kezelhető és hozzáférhető űrlap a fejezet minden eszközével.