מבוא לנגישות יישומי Windows — הכנה לאוטומציית UI ולדרישות התאמות סבירות
· Go Komura · נגישות, UI Automation, Windows, WinForms, WPF, התאמה סבירה, קוראי מסך, חוק אפליית מוגבלות, יישומים עסקיים
“עובד באמצע הקריירה עם לקות ראייה לא יכול להשתמש ביישום הזנת ההזמנות המרכזי עם קורא מסך. הוא משתמש בדפדפן ובדואר בלי בעיה, אבל רק הקריאה של היישום העסקי שלנו לא עובדת כמו שצריך. אפשר לעשות משהו?” — ייעוצים מהסוג הזה ממחלקות IT של לקוחות הולכים וגדלים.
רקע אחד הוא המסגרת החוקית. תיקון 2021 לחוק ביטול האפליה נגד אנשים עם מוגבלות נכנס לתוקף ב-1 באפריל 2024, ו”מתן התאמה סבירה” לאנשים עם מוגבלות הפך לחובה גם לעסקים.1 יתרה מזו, יחס עובד–חברה כמו בפתיחה (תחום התעסוקה) הוא תחום חוק קידום תעסוקת אנשים עם מוגבלות, שחייב מעסיקים לספק התאמה סבירה מאז אפריל 2016.2 הרעיון ש”נגישות היא נושא של אתרים ואין לה קשר ליישומי Windows פנימיים” כבר לא מחזיק, לא בחוק ולא בפועל.
מצד שני, מרצפת הפיתוח, “אין לנו מושג מה לעשות” הוא מקום כנה. לנגישות של יישומי שולחן עבודה של Windows יש פחות מידע מאשר לאינטרנט, ואין פתרון קסם בדיעבד. גם אין צורך להיות פסימיים. אם מבינים את המנגנון שבו קורא מסך קורא יישום (UI Automation) וקולטים את היסודות של שם, מקלדת וצבע, השימושיות של יישום עסקי משתפרת מהותית. והרבה מזה הוא שיפור שמעלה את הפרודוקטיביות של כל משתמש, עם מוגבלות או בלי.
מיועד למפתחי יישומים עסקיים יפניים ולאנשי IT, המאמר הזה מחבר במעבר אחד ממיון מינימלי של המסגרת החוקית והתקנים, דרך מנגנון UI Automation, מימוש ב-WinForms/WPF, הפעלת מקלדת, צבע וניגודיות וכלי אימות, ועד דרך מציאותית לקביעת סדרי עדיפות.
flowchart TB
accTitle: זרימת המאמר הזה
accDescr: מבנה המאמר, המחבר בסדר ממיון המסגרת החוקית והתקנים דרך מנגנון UI Automation, מימוש ב-WinForms וב-WPF, הפעלת מקלדת, צבע וניגודיות, כלי אימות ואופן קביעת סדרי עדיפות
law["מיון המסגרת החוקית והתקנים"] --> uia["מנגנון UI Automation"]
uia --> impl["מימוש ב-WinForms/WPF"]
impl --> kb["הפעלת מקלדת"]
kb --> color["צבע וניגודיות"]
color --> verify["כלי אימות"]
verify --> prio["אופן קביעת סדרי עדיפות"]
איור 1: המאמר מחבר את המסגרת החוקית דרך מנגנון, מימוש, אימות וסדרי עדיפות בזרימה אחת.
1. השורה התחתונה קודם
- מתן התאמה סבירה הוא חובה גם לעסקים מאז 1 באפריל 2024. כשאדם עם מוגבלות מביע כוונה להסרת מחסום, נדרשת תגובה בטווח שאינו נטל מופרז. תחום התעסוקה הוא תחת חוק קידום תעסוקת אנשים עם מוגבלות, וזו חובת מעסיק מאז אפריל 2016.12
- התאמה סבירה היא תהליך של “תגובה לבקשה אישית דרך דיאלוג בונה”; הפיכת היישום לקל יותר לשימוש מראש היא “שיפור סביבתי” (חובת מאמץ). תמיכה מוקדמת מושלמת אינה החובה; מה שחשוב הוא לא לסרב לדיאלוג באופן חד-צדדי.1
- הקריטריונים הטכניים לנגישות מרוכזים ב-WCAG (JIS X 8341-3:2016). JIS X 8341-3:2016 הוא תקן מקביל באותו תוכן ל-WCAG 2.0, ו-WCAG2ICT של W3C נותן הנחיה ליישום על תוכנה שאינה-רשת. אפשר לבדוק יישום שולחן עבודה באותה חשיבה.34
- קורא מסך קורא יישום דרך UI Automation (UIA). המאפיינים שכל רכיב בעץ UIA מחזיק — Name, ControlType וכדומה — ודפוסי בקרה כמו Invoke, Value ו-SelectionItem הם החומר להכרזה ולהפעלה.5
- כפתור ש-Name שלו ריק מוכרז רק כ”כפתור”. התיקון בעדיפות הגבוהה ביותר הוא מתן שמות. WinForms משתמש ב-AccessibleName ובשיוך Label לסדר Tab; WPF משתמש ב-AutomationProperties.Name/LabeledBy.67
- היכולת להגיע לכל פונקציה מהמקלדת בלבד היא קריטריון הצלחה של WCAG (2.1.1) ובאותו זמן מהירות הקלט של מפעיל מיומן עצמה. הצבת סדר Tab, מקשי גישה וסימן מיקוד מתחברת ישירות ליעילות של כל משתמש.8
- לוקחים יחס ניגודיות טקסט 4.5:1 או יותר כמדריך, ולא מעבירים מידע בצבע בלבד. בערכת נושא ניגודיות (ניגודיות גבוהה), מכבדים צבעי מערכת ולא צבעים מקודדים בקשיחות.89
- משלבים אימות עם FastPass ב-Accessibility Insights for Windows ועם בדיקה מעשית עם קורא מסך. כי הם יושבים על אותה תשתית UIA, העבודה הזאת גם משתלמת הדדית עם נכסי בדיקות UI אוטומטיות כמו FlaUI.10
- אין צורך לתקן כל מסך בבת אחת. הסדר המציאותי הוא (1) מהמסכים שהמשתמש ההוא משתמש בהם, (2) פיתוח חדש תואם-תקן, (3) גלגול הצידה בתיקון פקדים משותפים.
במשפט אחד: תמיכת נגישות היא “חשיפת השם והפעולות הנכונים בעץ UIA, והחזקת היסודות של מקלדת וצבע”.
2. מיון המסגרת החוקית והתקנים — מה ש”הפך לחובה” השתנה
2.1. חוק ביטול האפליה נגד אנשים עם מוגבלות — מאפריל 2024, גם עסקים חייבים לספק התאמה סבירה
חוק ביטול האפליה נגד אנשים עם מוגבלות הוא חוק שאוסר “יחס מפלה בלתי-צודק” לאנשים עם מוגבלות מצד גופים מינהליים ועסקים, ודורש “מתן התאמה סבירה”. בתיקון 2021 (ריווה 3), מתן התאמה סבירה על ידי עסקים, שהיה חובת מאמץ, הפך לחובה, והחוק המתוקן נכנס לתוקף ב-1 באפריל 2024 (ריווה 6).1
לפי עלון משרד הקבינט, מתן התאמה סבירה הוא תגובה, בטווח שאינו נטל מופרז, כשאדם עם מוגבלות מביע כוונה שתגובה כלשהי נדרשת להסרת מחסום בחברה. וכי התוכן שונה לפי מאפיין מוגבלות, סצנה ומצב, מודגש “דיאלוג בונה” שבו האדם עם המוגבלות והעסק עורמים דיאלוג ושוקלים תגובה יחד. סירוב חד-צדדי לדיאלוג בונה מצוין כעלול להוות הפרה של חובת מתן התאמה סבירה.1
שתי הבחנות מעשיות חשובות כאן.
- “שיש הכול במקום מראש” אינו מה שהפך לחובה. אמצעי שיפור מוקדמים שמכוונים למספר לא מוגדר של אנשים עם מוגבלות — הצד הרך כמו סקירת מדריך והכשרה, הצד הקשה כמו הפיכת מתקן נגיש — נקראים “שיפור סביבתי”, וזו חובת מאמץ.1 הצבת יישום עסקי במצב שמיש עם קורא מסך מראש אפשר לחשוב עליה כמאמץ של שיפור סביבתי. ככל ששיפור הסביבה התקדם יותר, הנטל של מתן התאמה סבירה אישית קל יותר.
- תחום התעסוקה אינו תחת חוק ביטול האפליה אלא תחת חוק קידום תעסוקת אנשים עם מוגבלות. אותו עלון גם קובע שתעסוקה ועבודה עוקבות אחר הוראות חוק קידום התעסוקה.1 ותחת החוק ההוא, בתיקון שנכנס לתוקף באפריל 2016 (הייסיי 28), איסור אפליה בשל מוגבלות בתעסוקה ומתן התאמה סבירה בטווח שאינו נטל מופרז חויבו על מעסיקים.2 הייעוץ בפתיחה של “עובד לא יכול להשתמש ביישום העסקי” היה, למעשה, בתחום החובה הרבה לפני 2024.
flowchart TB
accTitle: המיקום של התאמה סבירה ושיפור סביבתי
accDescr: היחס בין עסק כללי לאדם עם מוגבלות הוא תחת חוק ביטול האפליה, ומתן התאמה סבירה בתגובה לבקשה אישית דרך דיאלוג בונה הוא חובה מאפריל 2024; תחום התעסוקה הוא חובת מעסיק מאפריל 2016 תחת חוק קידום התעסוקה; הפיכת היישום לקל יותר לשימוש מראש היא שיפור סביבתי, חובת מאמץ
scene{"איזו סצנה?"}
scene -->|"עסק + מוגבלות"| kaisho["חוק האפליה"]
scene -->|"תעסוקה / עבודה"| koyou["חוק התעסוקה"]
kaisho --> moushide["בקשה דרך דיאלוג"]
moushide --> hairyo["מתן התאמה"]
hairyo -.-> hairyoN["חובה מאז 2024"]
koyou --> koyougimu["מתן התאמה"]
koyougimu -.-> koyouN["חובה מאז 2016"]
kaisho -.-> kankyo["יישום קל יותר מראש"]
kankyo -.-> kankyoN["שיפור סביבתי"]
kankyoN -.-> kankyoN2["חובת מאמץ"]
kankyo -.-> moushide
איור 2: החוק השולט מתפצל לפי סצנה; התאמה סבירה היא חובה, ותיקונים מוקדמים הם שיפור סביבתי, חובת מאמץ.
איך מקרה אישי מטופל בחוק תלוי במצב. המאמר הזה לא נכנס לפרשנות משפטית; הוא ממשיך מנקודת המבט של מה מהנדס יכול לעשות כשמבקשים תגובה. למקורות ראשוניים, ראו חומרי משרד הקבינט ומשרד הבריאות, העבודה והרווחה.12
2.2. JIS X 8341-3 ו-WCAG — “קריטריוני הרשת” מתרחבים גם לתוכנה
בצד הקריטריונים הטכניים, הם מרוכזים ב-JIS X 8341-3:2016. התקן הזה הוא תקן מקביל של ISO/IEC 40500:2012, וגוף התקן הוא אותו תוכן כמו WCAG 2.0 של W3C.3 אם רוצים לדעת באופן מוחשי ממה מורכבת “תמיכת נגישות”, קריאת קריטריוני הצלחה של WCAG (כעת מורחבים ב-WCAG 2.1/2.2) היא הנתיב הקצר, ותרגום יפני של WAIC גם מפורסם.8
השאלה “האם WCAG הוא קריטריון לתוכן רשת?” הוגנת, אבל W3C ארגן, ב-Group Note שנקרא WCAG2ICT (Guidance on Applying WCAG 2 to Non-Web Information and Communications Technologies), איך ליישם קריטריוני הצלחה של WCAG 2.0/2.1/2.2 על מסמכים ותוכנה שאינם-רשת.4 במילים אחרות, חשיבה כמו “חלופות טקסט”, “ניגודיות”, “הפעלת מקלדת” ו”צבע אינו האמצעי היחיד” אפשר ליישם על יישום שולחן עבודה של Windows באותה מסגרת כמו הרשת. פרקים 3 ואילך של המאמר מורידים את החשיבה הזאת למימוש WinForms/WPF מוחשי.
flowchart TB
accTitle: היחס בין JIS X 8341-3 ל-WCAG
accDescr: JIS X 8341-3:2016 הוא תקן מקביל באותו תוכן ל-WCAG 2.0, ו-WCAG2ICT מראה איך ליישם קריטריוני הצלחה של WCAG על תוכנה שאינה-רשת, כך שאפשר לבדוק יישום שולחן עבודה של Windows באותה מסגרת
wcag["WCAG 2.0(W3C)"] ---|"תקן מקביל באותו תוכן"| jis["JIS X 8341-3:2016"]
wcag --> ict["WCAG2ICT"]
ict --> soft["יישום על תוכנה שאינה-רשת"]
soft --> app["יישום שולחן עבודה של Windows"]
איור 3: JIS X 8341-3:2016 הוא תקן מקביל של WCAG 2.0, ו-WCAG2ICT מרחיב את אותם קריטריונים ליישומי שולחן עבודה.
3. איך טכנולוגיה מסייעת קוראת יישום — שלישיית UI Automation
3.1. עץ UIA, מאפיינים ודפוסי בקרה
ל-Windows יש תשתית נגישות שנקראת UI Automation (UIA) מובנית. UIA הוא מנגנון שמאפשר לטכנולוגיה מסייעת כמו קורא מסך להשיג מידע UI ולהפעיל את הממשק באמצעים שאינם קלט סטנדרטי, והוא מתווך בין צד היישום (הספק) לצד הטכנולוגיה המסייעת (הלקוח).5
את עולם UIA אפשר להבין כשלישייה הבאה.5
| רכיב | תפקיד | דוגמאות מייצגות |
|---|---|---|
| עץ UIA | עץ שמתחיל משולחן העבודה כשורש וממשיך חלון ← פקד. טכנולוגיה מסייעת הולכת בעץ הזה כדי לתפוס את הממשק | חלון, חלונית, כפתור, תיבת עריכה |
| מאפיינים | ערכים שמייצגים את אופי כל רכיב | Name (מטרה), ControlType (סוג), AutomationId (מזהה), IsEnabled, IsKeyboardFocusable |
| דפוסי בקרה | אוצר מילים של “פעולות שאפשר לעשות” לפי סוג | Invoke (לחיצה), Value (קריאה/כתיבת ערך), SelectionItem (בחירה), Toggle (הפעלה/כיבוי), ExpandCollapse (הרחבה/כיווץ) |
כשקורא מסך ממקד כפתור, ההכרזה “כפתור אישור הזמנה” היא, בגסות, השילוב של Name + סוג בקרה. כשהמשתמש מבצע פעולת “ביצוע”, הטכנולוגיה המסייעת לוחצת על הכפתור דרך דפוס Invoke. במילים אחרות, אם Name והדפוסים נחשפים נכון אפשר לקרוא ולהפעיל; אם הם לא נחשפים, זה כמו לא קיים גם אם זה נראה על המסך.
flowchart TB
accTitle: שלישיית UI Automation
accDescr: היישום, כספק, חושף מאפיינים ודפוסי בקרה של כל רכיב בעץ UIA; קורא המסך, כלקוח, מכריז Name ו-ControlType ופועל דרך דפוסים כמו Invoke
app["יישום(ספק)"] --> tree["עץ UIA"]
tree --> prop["מאפיינים(Name, ControlType וכדומה)"]
tree --> pat["דפוסים(Invoke, Value וכדומה)"]
sr["קורא מסך(לקוח)"] -->|"מכריז"| prop
sr -->|"מפעיל"| pat
איור 4: קורא המסך משתמש במאפיינים ובדפוסים שהיישום חשף בעץ UIA להכרזה ולהפעלה.
3.2. קורא מסך הוא לקוח UIA
קוראי המסך העיקריים בשימוש ב-Windows כוללים את Narrator, המובנה ב-Windows; את NVDA,11 החינמי וקוד פתוח; ואת PC-Talker, מוצר מסחרי בשימוש נרחב ביפן. סגנון ההכרזה שונה ביניהם, אבל הנתיב העיקרי לקריאת ממשק יישום שולחן עבודה הוא UIA בכל מקרה. לכן התגובה בצד היישום אינה “תמיכה לקורא מסך מסוים” אלא מתרכזת בחשיפת המידע הנכון ל-UIA.
flowchart TB
accTitle: הנתיב המשותף של קוראי המסך העיקריים
accDescr: אם היישום חושף את המידע הנכון ל-UIA, Narrator, NVDA ו-PC-Talker כולם יכולים לקרוא את הממשק באותו נתיב, ולכן התגובה בצד היישום אינה מכוונת לקורא מסך מסוים אלא מתרכזת בחשיפה ל-UIA
app["יישום"] -->|"חושף מידע"| uia["UI Automation(UIA)"]
uia --> nar["Narrator"]
uia --> nvda["NVDA"]
uia --> pct["PC-Talker"]
app -.-> goal["התגובה מתרכזת בחשיפה ל-UIA"]
איור 5: קוראי המסך העיקריים כולם לוקחים את UIA כנתיב, ולכן תגובת היישום מתרכזת בחשיפה ל-UIA.
3.3. כ”כפתור ש-Name שלו ריק” מוכרז כ?
דוגמה אחת מוחשית. נניח שלסרגל כלים יש כפתור שמירה שמציג רק אייקון דיסקט. למשתמש רואה האייקון מעביר את המשמעות, אבל אם Name נשאר ריק, קורא מסך מכריז על הכפתור הזה רק כ”כפתור”. אם “פתח” ו”הדפס” השכנים זהים, המשתמש שומע רק “כפתור, כפתור, כפתור” ואין לו אמצעי לדעת מי זה מי. מדריך תיקון הנגישות של Microsoft גם מונה כפתור בלי Name, ותמונה שמוכרזת רק כ-“Image”, כבעיות מייצגות שעוצרות את עבודת המשתמש.7
למרבה המזל, לפקדי WinForms ו-WPF סטנדרטיים יש תמיכת UIA מההתחלה, וברבים מהמקרים Name נקבע אוטומטית מטקסט או תווית. מה שנשבר בדרך כלל הוא אחד מ-(1) אייקון בלבד, בלי חומר לשם, (2) אין שיוך לתווית, או (3) ציור מותאם שלא שם מידע על עץ UIA. שני הפרקים הבאים מסתכלים איך לתקן לפי מסגרת.
flowchart TB
accTitle: שלוש דרכים טיפוסיות שבהן הכרזה נשברת
accDescr: הכרזה נשברת כשאין חומר לשם כי זה אייקון בלבד, כשאין שיוך לתווית, או כשציור מותאם לא שם מידע על עץ UIA, וזה נגמר מוכרז רק ככפתור
c1["אייקון בלבד, בלי חומר"] --> broken["Name הופך לריק"]
c2["אין שיוך לתווית"] --> broken
c3["ציור מותאם לא מוציא מידע"] --> broken
broken --> result["מוכרז רק ככפתור"]
איור 6: שבירת הכרזה בדרך כלל מתכנסת לאחד משלושה דפוסים: חומר שם לא מספיק, שיוך לא מספיק, או ציור מותאם.
4. מימוש ב-WinForms — AccessibleName וסדר Tab
4.1. פקדים ש-Text שלהם הופך ל-Name אוטומטית, ופקדים שלא
ב-WinForms, פקד שמציג טקסט, כמו Button או CheckBox, משתמש בערך מאפיין Text כ-UIA Name. לעומת זאת, ComboBox, ListBox, ListView, PictureBox, ProgressBar, TabControl, TextBox, TreeView וכדומה לא הופכים את Text ל-Name. אלה צריכים שם באמצעי אחר.6
הדרך הכי ניתנת לתחזוקה היא להניח Label תיאורי בסדר ה-Tab הקודם מיד של פקד היעד. אם מגדירים את TabIndex של פקד היעד לבוא מיד אחרי TabIndex של ה-Label, הטקסט של אותו Label משמש אוטומטית כ-UIA Name. התווית הנראית על המסך וההכרזה תואמות, ואין צורך לנהל את הניסוח פעמיים.612
אם אי אפשר להניח Label, מגדירים AccessibleName במפורש. אפשר גם להגדיר AccessibleDescription אם נדרש הסבר משלים, ו-AccessibleRole אם התפקיד שונה מהמראה.13
flowchart TB
accTitle: איך נקבע שם של פקד WinForms
accDescr: ל-Button וכדומה, Text הופך ל-UIA Name כמו שהוא; לפקדים כמו TextBox ש-Text שלהם לא ממוחזר, משתמשים בטקסט של Label שהונח בסדר ה-Tab הקודם מיד; אם אי אפשר להניח Label, מגדירים AccessibleName במפורש
ctrl["פקד"] --> qtext{"סוג ש-Text שלו הופך ל-Name?"}
qtext -->|"כן"| usetext["Text הופך ל-Name כמו שהוא"]
qtext -->|"לא"| qlabel{"Label בסדר ה-Tab הקודם מיד?"}
qlabel -->|"כן"| uselabel["טקסט ה-Label משמש כ-Name"]
qlabel -->|"לא"| explicit["מגדירים AccessibleName במפורש"]
איור 7: ל-Name ב-WinForms, בוחרים איך לקבוע אותו בסדר Text, Label בסדר ה-Tab הקודם מיד, AccessibleName.
// An icon-only toolbar button: state the name for announcement explicitly
saveToolStripButton.AccessibleName = "Save";
// An image-only button: name + a supplementary explanation
btnSearchCustomer.AccessibleName = "Search customer";
btnSearchCustomer.AccessibleDescription = "Search the customer master by customer code or name";
// Set it directly on an input field where you cannot place a Label in the immediately preceding tab order
txtOrderNo.AccessibleName = "Order number";
// A PictureBox reused as a chart display: match the role to the reality as well
pictureBoxChart.AccessibleRole = AccessibleRole.Chart;
pictureBoxChart.AccessibleName = "Monthly order-count chart";
כזהירות, אם מגדירים AccessibleName פעם אחת בחלונית המאפיינים של Visual Studio ואז מנקים אותו, הגדרת מחרוזת ריקה יכולה להישאר בקובץ המעצב ולהפריע לפתרון השם כברירת מחדל. מוחקים את השורה המתאימה מקובץ המעצב.6
flowchart TB
accTitle: בעיית AccessibleName מחרוזת ריקה שנשארת
accDescr: אם מגדירים AccessibleName פעם אחת בחלונית המאפיינים ואז מנקים אותו, הגדרת מחרוזת ריקה נשארת בקובץ המעצב ומפריעה לפתרון השם כברירת מחדל, ולכן מתקנים במחיקת השורה המתאימה מקובץ המעצב
set["הגדרת AccessibleName"] --> erase["ניקוי בחלונית המאפיינים"]
erase --> remain["הגדרת מחרוזת ריקה נשארת"]
remain --> block["מפריעה לפתרון השם כברירת מחדל"]
block -.-> fix["מחיקת השורה מקובץ המעצב"]
איור 8: ניקוי בחלונית המאפיינים עדיין משאיר מחרוזת ריקה, ולכן מתקנים במחיקת השורה המתאימה מקובץ המעצב.
4.2. שיפורים נפוצים במסך הזנת הזמנות
המקומות שבאמת מתקנים הרבה ביישומים עסקיים מסוכמים כרשימת בדיקה.
| מצב נפוץ | בעיה | איך מתקנים |
|---|---|---|
| ToolStripButton אייקון בלבד | מוכרז רק כ”כפתור” | מגדירים AccessibleName |
| יש Label ליד TextBox אבל סדר ה-Tab מפוזר | שם שדה הקלט ריק, או הופך לשם לא קשור | מניחים את שדה הקלט מיד אחרי TabIndex של ה-Label |
| PictureBox בשימוש ככפתור דרך Click | התפקיד לא מועבר ככפתור, ואי אפשר ללחוץ מהמקלדת | מחליפים ב-Button, או מגדירים AccessibleRole/AccessibleName פלוס תמיכת מקלדת |
| כותרת עמודת DataGridView ריקה או סמלים בלבד | משמעות העמודה לא ברורה כשתא מוכרז | מגדירים שם עמודה משמעותי ב-HeaderText |
| רק Panel משמש לקיבוץ תוכן, והכותרת היא תמונה | אי אפשר לדעת איזו קבוצת קלט זו | משתמשים ב-GroupBox, או הופכים את הכותרת ל-Label |
כל אחד הוא תיקון של כמה שורות, אבל למשתמש קורא מסך זה הפיצול בין “מסך שאי אפשר להשתמש בו” ל”מסך שאפשר להשתמש בו”.
5. מימוש ב-WPF — AutomationProperties ו-AutomationPeer
5.1. AutomationProperties.Name / LabeledBy / HelpText
ב-WPF, פקד ש-Content שלו הוא מחרוזת, כמו Button, משתמש בתוכן הזה כ-UIA Name. כפתור אייקון בלבד (Image או Path) אין לו חומר ל-Name, לכן מציינים אותו עם AutomationProperties.Name, או אם יש טקסט תצוגה קרוב משייכים אותו עם AutomationProperties.LabeledBy.7
ל-TextBox יש זהירות חשובה. Text של TextBlock ממוחזר כ-Name, אבל Text של TextBox נחשף בצד מאפיין UIA Value ולא הופך ל-Name. לשדה קלט, שיוך TextBlock תווית התצוגה עם LabeledBy הוא המועמד הראשון. הכרזה ותצוגה על המסך תואמות, וגם נמנעים מניהול הניסוח פעמיים.14
<!-- An input field: associate the display label with LabeledBy -->
<TextBlock x:Name="OrderNoLabel" Text="Order number" />
<TextBox
AutomationProperties.LabeledBy="{Binding ElementName=OrderNoLabel}"
AutomationProperties.AutomationId="OrderNoTextBox" />
<!-- An icon-only button: state the name, and a supplement if needed -->
<Button
AutomationProperties.Name="Confirm order"
AutomationProperties.HelpText="Confirm the order being entered and allocate inventory">
<Path Data="{StaticResource CheckIconGeometry}" Width="16" Height="16" />
</Button>
flowchart TB
accTitle: איך נקבע שם של פקד WPF
accDescr: פקד ש-Content שלו מחרוזת משתמש בתוכן כ-Name; אחרת שיוך תווית תצוגה קרובה עם LabeledBy הוא המועמד הראשון; אם גם זה חסר, מציינים AutomationProperties.Name; Text של TextBox נחשף בצד Value, לא כ-Name
ctrl["פקד"] --> qc{"האם Content מחרוזת?"}
qc -->|"כן"| auto["התוכן הופך ל-Name"]
qc -->|"לא"| ql{"תווית תצוגה קרובה?"}
ql -->|"כן"| lb["שיוך עם LabeledBy"]
ql -->|"לא"| nm["הגדרת Name במפורש"]
tbx["Text של TextBox"] -.-> val["נחשף כ-Value, לא Name"]
איור 9: ל-Name ב-WPF, מחליטים בסדר מחרוזת Content, LabeledBy, הגדרה מפורשת; Text של TextBox לא הופך ל-Name.
מידע משלים שלא נכנס ב-Name אפשר לחשוף עם AutomationProperties.HelpText.7 גם, AutomationId הוא מזהה לזיהוי רכיבים בבדיקות UI אוטומטיות, ולכן החלטת מוסכמת שמות בזמן עיצוב המסך משתלמת אחר כך (מכוסה לעומק ב”בדיקות UI אוטומטיות ליישומי שולחן עבודה של Windows”).
5.2. פקד מותאם צריך AutomationPeer
פקד מותאם שמציירים בעצמכם לא יכול, כמו שהוא, לחשוף מידע משמעותי בעץ UIA. ב-WPF דורסים OnCreateAutomationPeer במחלקה נגזרת מ-UIElement ומחזירים מחלקה נגזרת מ-AutomationPeer כדי לחשוף שם, סוג ודפוסים. אם יורשים פקד קיים, ירושת ה-Peer המתאים (ButtonBaseAutomationPeer ל-ButtonBase) מאפשרת לקחת התנהגות שכבר מומשה.15
flowchart TB
accTitle: איך מידע נחשף דרך AutomationPeer
accDescr: פקד מותאם חושף שם, סוג ודפוסים בדריסת OnCreateAutomationPeer והחזרת מחלקה נגזרת מ-AutomationPeer; אם יורשים פקד קיים, יורשים את ה-Peer המתאים ולוקחים התנהגות שכבר מומשה
custom["פקד מותאם"] --> ov["OnCreateAutomationPeer"]
ov --> peer["החזרת מחלקה נגזרת מ-Peer"]
peer --> pub["חשיפת שם, סוג ודפוסים"]
inherit["ירושת פקד קיים"] -.-> basepeer["ירושת ה-Peer המתאים"]
basepeer -.-> reuse["לקיחת התנהגות שכבר מומשה"]
איור 10: פקד מותאם מחזיר Peer מ-OnCreateAutomationPeer וחושף מידע ל-UIA.
// An example of a control that custom-draws line status as a coloured lamp
public class StatusLamp : Control
{
public static readonly DependencyProperty IsOnlineProperty =
DependencyProperty.Register(nameof(IsOnline), typeof(bool), typeof(StatusLamp),
new FrameworkPropertyMetadata(false,
FrameworkPropertyMetadataOptions.AffectsRender, OnIsOnlineChanged));
public bool IsOnline
{
get => (bool)GetValue(IsOnlineProperty);
set => SetValue(IsOnlineProperty, value);
}
internal static string NameFor(bool isOnline)
=> isOnline ? "Line status: online" : "Line status: offline";
private static void OnIsOnlineChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Raise a UIA property-changed event the moment the value changes. Without this,
// a screen reader keeps the old name and cannot notice the change of state
if (UIElementAutomationPeer.FromElement((UIElement)d) is AutomationPeer peer)
{
peer.RaisePropertyChangedEvent(
AutomationElementIdentifiers.NameProperty,
NameFor((bool)e.OldValue), NameFor((bool)e.NewValue));
}
}
protected override AutomationPeer OnCreateAutomationPeer()
=> new StatusLampAutomationPeer(this);
}
public class StatusLampAutomationPeer : FrameworkElementAutomationPeer
{
public StatusLampAutomationPeer(StatusLamp owner) : base(owner) { }
protected override AutomationControlType GetAutomationControlTypeCore()
=> AutomationControlType.Text; // Text-equivalent if it is a status display with no operation
protected override string GetNameCore()
=> StatusLamp.NameFor(((StatusLamp)Owner).IsOnline);
}
החזרת שם אינה מספיקה; לספר לו באירוע ברגע שהוא משתנה גם היא עבודת ה-Peer. לטכנולוגיה מסייעת אין תזמון משלה לשליפה מחדש של ערך, ולכן מימוש שלא מרים אירוע שינוי נמצא במצב של “נכון רק כששואלים שוב”, ומשתמש קורא מסך לא מקבל הודעה על שינוי המצב.
sequenceDiagram
accTitle: זרימת סיפור לקורא מסך על שינוי מצב
accDescr: ברגע שערך הפקד משתנה, ה-AutomationPeer מרים אירוע שינוי מאפיין Name; טכנולוגיה מסייעת לא שולפת מחדש מעצמה, ולכן בלי האירוע היא נשארת על השם הישן ולא יכולה להבחין בשינוי
participant c as פקד
participant p as AutomationPeer
participant s as קורא מסך
c->>p: ערך IsOnline משתנה
p->>s: הרמת אירוע שינוי מאפיין Name
s->>s: הכרזת המצב החדש
Note over s: בלי האירוע נשארים על השם הישן
איור 11: שינוי ערך מגיע לקורא מסך רק כשה-AutomationPeer מספר לו באירוע שינוי.
אם לפקד המותאם יש פעולה (אפשר ללחוץ, אפשר לשנות ערך, אפשר לבחור), דורסים GetPattern ומספקים ממשק דפוס כמו IInvokeProvider או IRangeValueProvider.15 הנקודה היא שאם בונים את ה-Peer גם בצד ספריית הפקדים המשותפת, כל מסך שמשתמש בו הופך נתמך אוטומטית. זו התשתית של “גלגול הצידה” בפרק 9.
6. אפשר להגיע לכל פונקציה מהמקלדת בלבד?
קריטריון הצלחה WCAG 2.1.1 (Keyboard) דורש שכל הפונקציונליות של התוכן תהיה ניתנת להפעלה דרך ממשק מקלדת.8 משתמש קורא מסך כעיקרון לא משתמש בעכבר, ולכן פונקציה שאי אפשר להגיע אליה מהמקלדת היא כמו פונקציה שלא קיימת. נקודות המבט לבדיקה הן כדלקמן.
| נקודת מבט | מה לאשר | האמצעים העיקריים ב-WinForms / WPF |
|---|---|---|
| סדר Tab | האם סדר תנועת מקש Tab תואם לסדר החזותי (שמאל-עליון ← ימין-תחתון)? | סידור TabIndex, הגדרת TabStop |
| מקש גישה | אפשר לעבור ישירות לפריט ראשי עם Alt+אות? | ב-WinForms, & ב-Text; ב-WPF, _ בכותרת |
| קיצור | יש מקש עצמאי לפעולות תכופות (שמירה, חיפוש, אישור)? | הקצאת Ctrl+S וכדומה, הצגה בתפריט |
| סימן מיקוד | אפשר לעקוב בעיניים איפה המיקוד עכשיו? | לא מסירים את מלבן המיקוד; מציירים אותו בעצמכם כשמציירים מותאם |
| פונקציות עכבר בלבד | יש פונקציה שמישה רק בלחיצה כפולה, לחיצה ימנית, גרירה או ריחוף? | מציעים את אותה פונקציה גם מתפריט או ממקש |
| דיאלוג | Enter = כפתור ברירת מחדל ו-Esc = ביטול עובדים? | AcceptButton/CancelButton, IsDefault/IsCancel |
ה-walkthrough של נגישות WinForms גם מונה, כיסודות, הנחת תווית בסדר ה-Tab הקודם מיד של שדה קלט, והנחת מקשי גישה על הפקדים והתפריטים שהמשתמש רוצה לעבור אליהם.12
מה שרוצים להדגיש הוא שזה אינו “עלות נוספת לתמיכת מוגבלות”. בעבודה שגרתית כמו הזנת הזמנות, האם אפשר להשלים קלט בלי להרים ידיים ממיקום הבית הוא מה שמחליט את התפוקה של המפעיל כמו שהיא. סדר Tab מבולגן או פעולה שדורשת עכבר הוא פגם שמגלח קצת מפרודוקטיביות כל משתמש כל יום. תמיכת נגישות ויעילות מקלדת הם רק שני שמות לאותה עבודה (לסדרי עדיפות לפי סביבת שימוש, ראו גם “עיצוב UX ליישומי Windows”).
flowchart TB
accTitle: האפקט הכפול של סידור המקלדת
accDescr: הצבת סדר Tab, מקשי גישה וסימן מיקוד מייצרת שני אפקטים בבת אחת — משתמש טכנולוגיה מסייעת יכול להגיע לפונקציה, ומהירות הקלט של כל מפעיל — ופונקציה שמישה רק בעכבר היא כמו פונקציה שלא קיימת
seibi["סידור מקלדת"] --> a11y["משתמשי טכנולוגיה מסייעת"]
seibi --> speed["מהירות כל מפעיל"]
mouse["פונקציית עכבר בלבד"] -.-> none["כמו לא קיימת"]
איור 12: סידור הפעלת מקלדת מממש תמיכת טכנולוגיה מסייעת ויעילות לכל משתמש באותו זמן; פונקציית עכבר בלבד היא כמו לא קיימת.
7. צבע וניגודיות — 4.5:1 ו”צבע אינו האמצעי היחיד”
7.1. המדריך ליחס ניגודיות הוא 4.5:1
קריטריון הצלחה WCAG 1.4.3 (Contrast (Minimum)) דורש יחס ניגודיות של לפחות 4.5:1 לטקסט ולתמונות של טקסט, ולפחות 3:1 לטקסט גדול.8 עיצוב מודרני שמניח טקסט אפור בהיר על רקע לבן אינו נדיר בנפילה מתחת לקריטריון הזה. משתמשי יישום עסקי כוללים אנשים שראייתם וראיית הצבע שלהם השתנו עם הגיל, ואנשים שמשתמשים בו בסביבה חשוכה כמו מפעל. מתרגלים מדידה עם בודק ניגודיות בסקירת עיצוב.
7.2. לא מעבירים מידע בצבע בלבד
קריטריון הצלחה 1.4.1 (Use of Color) הוא שצבע לא חייב להיות האמצעי החזותי היחיד להעברת מידע.8 דוגמאות טיפוסיות ביישום עסקי הן כדלקמן.
- הצגת שורת שגיאה בטקסט אדום בלבד ← מספקים גם אייקון שגיאה ועמודת הודעה
- הצגת שדה חובה בצבע התווית בלבד ← מוסיפים “*” או את הניסוח “חובה”
- הצגת מצב בצבע המנורה בלבד ← הופכים לצבע + צורה, או ניסוח (“רץ”, “עצור”)
בהינתן הגיוון של ראיית צבע, גם זה אינו “תגובה מיוחדת” אלא יסוד של עיצוב תצוגה.
flowchart TB
accTitle: החלפת מידע שמועבר בצבע בלבד
accDescr: תצוגה שמראה שגיאה בטקסט אדום בלבד מוחלפת באייקון שגיאה פלוס עמודת הודעה; תצוגה שמראה שדה חובה בצבע התווית בלבד מוחלפת בהוספת הניסוח חובה; תצוגה שמראה מצב בצבע המנורה בלבד מוחלפת בשילוב צורה או ניסוח
err["שגיאה בטקסט אדום בלבד"] --> erra["מספקים גם אייקון וניסוח"]
req["חובה בצבע התווית בלבד"] --> reqa["מוסיפים את הניסוח חובה"]
lamp["מצב בצבע המנורה בלבד"] --> lampa["משלבים צבע עם צורה או ניסוח"]
איור 13: דוגמאות טיפוסיות להעברה בצבע בלבד מוחלפות בשילוב אייקון, ניסוח וצורה או טקסט.
7.3. מעקב אחרי ערכת נושא ניגודיות (ניגודיות גבוהה)
ל-Windows יש ערכות נושא ניגודיות (לשעבר ניגודיות גבוהה) שמחליפות לסכמת צבעים עם הפרדה חזקה של קדמה ורקע; המשתמש יכול לבחור ולערוך ערכות נושא מובנות שתוכננו כך שיחס הניגודיות הוא בדרך כלל 7:1 או יותר.9 העיקרון בצד היישום פשוט: לא לקודד צבעים בקשיחות; לכבד צבעי מערכת.
- WinForms: אם משאירים ForeColor/BackColor בברירת המחדל, משמשות הגדרות הצבע של המשתמש. במקום שהחלתם צבע משלכם, שופטים עם SystemInformation.HighContrast, מחליפים לסכמה מבוססת-SystemColors, ועוקבים אחרי שינוי הגדרות עם אירוע UserPreferenceChanged.12
- WPF/WinUI: אם מפנים למשאבי מחלקת SystemColors, עוקבים אחרי החלפת ערכת נושא. מקומות שמילאתם במברשת משלכם הופכים לסיבת השבירה.9
flowchart TB
accTitle: מעקב אחרי ערכת נושא ניגודיות
accDescr: מקומות שצבע מקודד בהם בקשיחות נשברים בהחלפה לערכת נושא ניגודיות, לכן מחליפים לסכמה מבוססת-SystemColors ועוקבים עם אירוע שינוי הגדרות; אם מפנים לצבעי מערכת אפשר לעקוב אחרי צבעי המשתמש אוטומטית
theme["החלפה לערכת נושא ניגודיות"] --> qh{"איך הצבע צוין?"}
qh -->|"מקודד בקשיחות"| broken["סכמת הצבעים נשברת"]
qh -->|"הפניה לצבע מערכת"| ok["עוקב אוטומטית אחרי צבעי המשתמש"]
broken -.-> fix["החלפה ל-SystemColors"]
fix -.-> ev["מעקב עם אירוע שינוי הגדרות"]
איור 14: רק מקומות שצבע מקודד בהם בקשיחות נשברים תחת ערכת נושא ניגודיות; הפניה לצבע מערכת עוקבת אוטומטית.
גם, משתמש עם ראייה ירודה לעיתים קרובות משתמש בהגדלת מערכת הפעלה גבוהה (קנה מידה DPI), ולכן תמיכת DPI גבוהה היא גם חלק מתמיכת נגישות. יישום שהפריסה שלו נשברת ב-125%–200% אינו שמיש בנקודה הזאת. ראו “תמיכת DPI גבוהה ב-WinForms” ו”תמיכת DPI גבוהה ב-WPF” לפרטים.
8. אימות בפועל — Accessibility Insights ובדיקה מעשית עם קורא מסך
8.1. Accessibility Insights for Windows
Microsoft מספקת את Accessibility Insights for Windows ככלי אימות נגישות ליישומי Windows, עם שלושה שימושים עיקריים.10
- Live Inspect: פשוט מרחפים עם העכבר מעל רכיב או ממקדים אותו במקלדת, ואפשר לאשר את מאפייני UIA שלו (Name, ControlType, דפוסים וכדומה). האמצעי הקצר ביותר לראות “מה ה-Name של הכפתור הזה”.
- FastPass: בדיקה קלה שמזהה בעיות נגישות בעלות השפעה גבוהה בפחות מחמש דקות. בעיות שאפשר לשפוט מכנית, כמו Name חסר, אפשר למנות לכל מסך חדש.
- Troubleshooting: מסייע באבחון ובתיקון של בעיה מסוימת. מבעיה שזוהתה אפשר ללכת ישירות למדריכי התיקון לפי מסגרת שהמאמר גם מצטט.
Inspect.exe ו-AccEvent, הכלולים ב-Windows SDK, יכולים גם לאשר את עץ UIA ואת המאפיינים, אבל הם ממוקמים ככלים ישנים, ומעבר ל-Accessibility Insights מומלץ כעת.10
flowchart TB
accTitle: שלושה שימושים של Accessibility Insights
accDescr: Accessibility Insights for Windows מספק אישור מאפייני UIA עם Live Inspect, בדיקה קלה של בעיות בעלות השפעה גבוהה עם FastPass, וסיוע באבחון ובתיקון בעיה עם Troubleshooting; מעבר מכלים ישנים כמו Inspect.exe מומלץ
ai["Accessibility Insights"] --> live["Live Inspect"]
ai --> fast["FastPass"]
ai --> ts["Troubleshooting"]
live --> livef["אישור מאפייני UIA"]
fast --> fastf["זיהוי בעיות בעלות השפעה גבוהה"]
ts --> tsf["סיוע באבחון ובתיקון"]
legacy["Inspect.exe וכדומה"] -.->|"מעבר מומלץ"| ai
איור 15: ל-Accessibility Insights יש את שלושת השימושים אישור, זיהוי ואבחון, והוא יעד המעבר מכלים ישנים.
8.2. בדיקה מעשית עם קורא מסך
מה שבדיקה אוטומטית של כלי יכולה לזהות הוא רק בעיות שאפשר לשפוט מכנית. בסוף, תמיד הולכים בפעולה עסקית אמיתית עם קורא מסך. אפשר להפעיל את Narrator המובנה ב-Windows מיד עם Ctrl+מקש Windows+Enter, ואת NVDA אפשר להכניס בחינם.11 התחבולה של הבדיקה היא לנסות, בלי להסתכל על המסך (או עם התצוגה כבויה), תוך הסתמכות רק על ההכרזה, האם אפשר להשלים משימה אמיתית כמו “להזין הזמנה אחת ולאשר אותה”. בעיות כמו שם שקיים אבל סדר ההכרזה לא קוהרנטי, או מיקוד שבורח מחוץ למודל, נמצאות רק בידיים.
flowchart TB
accTitle: שילוב אימות כלי ובדיקה מעשית
accDescr: מה שבדיקה אוטומטית כמו FastPass יכולה לזהות הוא רק בעיות שאפשר לשפוט מכנית; השאר נמצא בידיים בהליכה בפעולה עסקית אמיתית עם קורא מסך ובמציאת בעיות סדר הכרזה ומיקוד
tool["בדיקה אוטומטית של כלי"] --> kikai["בעיות שאפשר לשפוט מכנית"]
tool -.-> nokori["בעיות שהיא לא מזהה נשארות"]
nokori --> sr["בדיקה מעשית עם קורא מסך"]
sr --> task["הליכה בפעולה עסקית"]
task --> mieru["בעיות סדר הכרזה ומיקוד"]
איור 16: מונים בעיות מכניות בבדיקה אוטומטית, ומוצאים את השאר בבדיקה מעשית עם קורא מסך.
8.3. בנייתו לזרימת הפיתוח, וההשתלמות ההדדית עם בדיקות UI אוטומטיות
כדי שהאימות לא יהפוך לתלוי-אדם, ממליצים לבנות את רשימת הבדיקה הבאה לפריטי סקירה של מסך חדש.
| # | פריט בדיקה | אמצעי |
|---|---|---|
| 1 | FastPass בלי שגיאות | Accessibility Insights |
| 2 | לכל שדה קלט וכפתור יש Name | Live Inspect |
| 3 | אפשר להגיע לכל פונקציה במקש Tab בלבד | ידני |
| 4 | Enter/Esc והקיצורים העיקריים עובדים | ידני |
| 5 | יחס ניגודיות טקסט 4.5:1 או יותר | בודק ניגודיות |
| 6 | לא נשבר תחת ערכת נושא ניגודיות | מחליפים ערכת נושא ובודקים חזותית |
| 7 | לא נשבר ב-200% קנה מידה | משנים הגדרת תצוגה ובודקים חזותית |
| 8 | אפשר להשלים משימה מייצגת עם קורא מסך | Narrator/NVDA |
ועוד אחד. בדיקות UI אוטומטיות עם FlaUI וכדומה בנויות על אותו UIA שקוראי מסך משתמשים בו. ה-Name והדפוסים ששמים לנגישות הופכים לחלקי קוד בדיקה, ו-AutomationId שתוכנן לבדיקות מקל על ניפוי באגים ב-Live Inspect. לעומת זאת, ממשק שלא מופיע בעץ UIA בלתי-נראה גם לבדיקות וגם לטכנולוגיה מסייעת. נגישות וניתנות לבדיקה הן שני צדדים של אותה השקעה (“בדיקות UI אוטומטיות ליישומי שולחן עבודה של Windows”).
flowchart TB
accTitle: ההשתלמות ההדדית של נגישות ובדיקות UI אוטומטיות
accDescr: קורא מסך ובדיקות UI אוטומטיות כמו FlaUI בנויים על אותו UIA, ולכן אפשר להשתמש ב-Name ובדפוסים ששמים משניהם, וממשק שלא מופיע בעץ UIA בלתי-נראה מכל אחד
uia["סידור עץ UIA"] --> sr["קורא מסך יכול לקרוא אותו"]
uia --> test["אפשר להשתמש בבדיקות UI אוטומטיות"]
sr -.-> both["שני צדדים של אותה השקעה"]
test -.-> both
hidden["ממשק שלא מופיע ב-UIA"] -.-> invisible["בלתי-נראה מכל אחד"]
איור 17: כי הם יושבים על אותה תשתית UIA, סידור עץ UIA משתלם גם לטכנולוגיה מסייעת וגם לבדיקות UI אוטומטיות.
9. איך לקבוע סדרי עדיפות — לא לתקן כל מסך בבת אחת
תיקון מערכת ליבה של מאות מסכים בבת אחת אינו מציאותי לא בעלות ולא באיכות. הגישה שאנחנו ממליצים עליה היא שלוש השכבות הבאות.
- מתקנים מהמסכים שהמשתמש ההוא משתמש בהם בעבודה. התאמה סבירה היא תהליך של תגובה אישית לבקשה מהאדם הנוגע בדבר.1 קודם נותנים לאדם להפעיל את העבודה בפועל עם קורא מסך, ומזהים יחד איפה הוא נתקע. ברבים מהמקרים המסכים שבשימוש יומיומי מצטמצמים לכמה עד תריסר, והבעיות הקטלניות ביניהן (כפתור בלי שם, כפתור אישור שאי אפשר ללחוץ מהמקלדת) אפשר לפתור בתיקון של ימים.
- הופכים פיתוח חדש לתואם-תקן. מוסיפים את רשימת הבדיקה של פרק 8 להגדרת הסיום, ובונים מסכים חדשים נתמכים מההתחלה. בניגוד לתיקון בדיעבד, תוספת העלות של בנייתו בזמן עיצוב קלה.
- מגלגלים הצידה בתיקון פקדים משותפים. אם מממשים AccessibleName כברירת מחדל או AutomationPeer על חלקים פנימיים משותפים כמו דיאלוג חיפוש, רשת או קלט תאריך, זה נכנס לתוקף באצווה בכל מסך שמשתמש בהם. זה מהלך הרבה יותר חסכוני מלגעת במסכים בודדים אחד אחד.
flowchart TB
accTitle: שלוש שכבות עדיפות התיקון
accDescr: מתקנים מהמסכים שהמשתמש משתמש בהם בעבודה, הופכים פיתוח חדש לתואם-תקן עם רשימת בדיקה, ומגלגלים לכל מסך בתיקון פקדים משותפים
s1["1. תיקון מהמסכים שהמשתמש משתמש בהם"] --> s2["2. עבודה חדשה תואמת-תקן"] --> s3["3. גלגול הצידה עם פקדים משותפים"]
s3 -.-> all["נכנס לתוקף באצווה בכל מסך שמשתמש בהם"]
איור 18: מתקדמים לא בתיקון כל מסך בבת אחת אלא בשלוש השכבות מסכים בשימוש, עבודה חדשה וחלקים משותפים.
ורישום הדיאלוג חשוב כמו התגובה הטכנית. התאמה סבירה היא תהליך של “דיאלוג והתאמה אישית”, לא של מילוי מלא של כל בקשה. שקילת אמצעי חלופי עם האדם (לעשות את העבודה הזאת במסך אחר, להכין ייצוא CSV, לכסות בתפעול) והסכמה, לתיקון שהנטל שלו כבד מדי, גם היא תוצאה לגיטימית של דיאלוג בונה.1 רישום מה התבקש, למה הגיבו, ומה הפך לאמצעי חלופי הופך להוכחת תום הלב של הארגון.
flowchart TB
accTitle: זרימת דיאלוג בונה ורישום
accDescr: מגיבים לבקשה מאדם עם מוגבלות דרך דיאלוג בונה; מבצעים תיקון שאפשר להגיב לו; לתיקון שהנטל שלו כבד מדי, שוקלים אמצעי חלופי עם האדם ומסכימים; רושמים מה התבקש, למה הגיבו ומה הפך לאמצעי חלופי
req["בקשה"] --> talk["דיאלוג בונה"]
talk --> q{"האם הנטל כבד מדי?"}
q -->|"לא"| kaishu["מגיבים בתיקון"]
q -->|"כן"| alt["שוקלים אמצעי חלופי ומסכימים"]
kaishu --> rec["רושמים את ההיסטוריה"]
alt --> rec
איור 19: בדיאלוג בונה מסכימים עם האדם על תיקון או אמצעי חלופי, ומשאירים את ההיסטוריה הזאת ברישום.
10. סיכום
- עם תיקון חוק ביטול האפליה שנכנס לתוקף באפריל 2024, מתן התאמה סבירה הפך לחובה גם לעסקים. תחום התעסוקה הוא חובת מעסיק מאז 2016 תחת חוק קידום תעסוקת אנשים עם מוגבלות. הפיכת היישום לקל יותר לשימוש מראש היא “שיפור סביבתי” (חובת מאמץ), וככל שהתקדם יותר התגובות האישיות נעשות קלות יותר.
- הקריטריונים הטכניים מרוכזים ב-WCAG (JIS X 8341-3:2016), ואותה חשיבה אפשר ליישם על יישום שולחן עבודה דרך WCAG2ICT.
- קורא מסך קורא יישום דרך UI Automation. שלישיית עץ UIA, מאפיינים (Name/ControlType/AutomationId) ודפוסי בקרה היא התשתית.
- העדיפות הגבוהה ביותר היא Name. WinForms משתמש ב-AccessibleName ובשיוך Label לסדר Tab; WPF משתמש ב-AutomationProperties.Name/LabeledBy; פקד מותאם משתמש ב-AutomationPeer.
- היכולת להגיע לכל פונקציה מהמקלדת בלבד היא קריטריון הצלחה של WCAG ובאותו זמן הפרודוקטיביות של כל מפעיל. מסדרים סדר Tab, מקשי גישה וסימן מיקוד.
- שלושת היסודות של צבע הם יחס ניגודיות 4.5:1, צבע אינו האמצעי היחיד, וכיבוד צבעי מערכת בערכת נושא ניגודיות.
- משלבים אימות עם FastPass+Live Inspect ב-Accessibility Insights ועם בדיקה מעשית עם Narrator/NVDA, ובונים אותו לזרימת הפיתוח כרשימת בדיקה למסך חדש.
- לא מתקנים כל מסך בבת אחת; מתקדמים בסדר המסכים שהמשתמש משתמש בהם ← תמיכה תקנית לעבודה חדשה ← גלגול הצידה של פקדים משותפים. התאמה סבירה היא תהליך של דיאלוג, ורישום ההיסטוריה מגן על הארגון.
כצעד ראשון ממליצים לבחור אחד מהמסכים העיקריים שלכם, להריץ FastPass ב-Accessibility Insights for Windows, ואז ללכת בעבודה במקש Tab בלבד. בשלושים דקות, המיקום הנוכחי של היישום שלכם הופך מוחשי באופן מפתיע.
מאמרים קשורים
- בדיקות UI אוטומטיות ליישומי שולחן עבודה של Windows — איך UI Automation עובד ובניית בדיקות עמידות עם FlaUI
- עיצוב UX ליישומי Windows - סדרי עדיפות לפי סביבת שימוש
- תמיכת DPI גבוהה ב-WinForms — למה הממשק מטשטש או נשבר במסכי 4K, ותיקונים מעשיים
- תמיכת DPI גבוהה ב-WPF — למה זה עדיין מטשטש ודולף למרות ש”אמור להיות מודע ל-DPI”, ואיך לתקן
- למה KomuraSoft בונה אתרים על מערכת העיצוב של הסוכנות הדיגיטלית — עלות נמוכה ואיכות גבוהה יכולות לדור יחד
- מלכודות גופנים ותווים יפניים — טיפול ב-JIS2004, IVS וגאיג’י ביישומים עסקיים
תחומי ייעוץ קשורים
KomuraSoft LLC מטפלת בתיקוני נגישות של יישומים עסקיים WinForms/WPF (תמיכת קורא מסך, סידור הפעלת מקלדת, תמיכת ערכת נושא ניגודיות), במימוש AutomationPeer על פקדים משותפים, ובייעוצים על אבחון מצב נוכחי וקביעת סדרי עדיפות עם Accessibility Insights. בסדר להתחיל משלב של “אנחנו רוצים לאשר אם עובד יכול להשתמש ביישום שלנו עם קורא מסך”.
קישורים
-
Cabinet Office, Leaflet “From 1 April 2024, the provision of reasonable accommodation became an obligation”. על כניסת תיקון ריווה 3 לחוק ביטול האפליה לתוקף ב-1 באפריל ריווה 6 והפיכת מתן התאמה סבירה על ידי עסקים לחובה; על כך שמתן התאמה סבירה הוא תגובה, בטווח שאינו נטל מופרז, לביטוי כוונה מאדם עם מוגבלות; על חשיבות דיאלוג בונה ועל כך שסירוב חד-צדדי עלול להוות הפרת החובה; על כך ש”שיפור סביבתי”, אמצעי שיפור מוקדמים שמכוונים למספר לא מוגדר של אנשים עם מוגבלות, הוא חובת מאמץ; ועל כך שתעסוקה ועבודה עוקבות אחר הוראות חוק קידום התעסוקה. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Ministry of Health, Labour and Welfare, The prohibition of discrimination against persons with disabilities in employment and the obligation to provide reasonable accommodation. על כך שחוק קידום התעסוקה המתוקן שנכנס לתוקף באפריל הייסיי 28 חייב מעסיקים לאסור אפליה בשל מוגבלות בתעסוקה ולספק התאמה סבירה בטווח שאינו נטל מופרז; ועל חומרים קשורים כמו הנחיות התאמה סבירה. ↩ ↩2 ↩3 ↩4
-
Web Accessibility Infrastructure Committee (WAIC), Understanding JIS X 8341-3:2016. על כך ש-JIS X 8341-3:2016 הוא תקן מקביל של ISO/IEC 40500:2012, וגוף התקן הוא אותו תוכן כמו WCAG 2.0; ועל היקף תוכן הרשת שהתקן מניח. ↩ ↩2
-
W3C, Guidance on Applying WCAG 2 to Non-Web Information and Communications Technologies (WCAG2ICT). על ה-W3C Group Note שמראה איך ליישם את העקרונות, ההנחיות וקריטריוני ההצלחה של WCAG 2.0/2.1/2.2 על מסמכים ותוכנה שאינם-רשת. ↩ ↩2
-
Microsoft Learn, UI Automation Specification. על כך ש-UI Automation מספק מידע UI לטכנולוגיה מסייעת כמו קורא מסך ומאפשר הפעלה באמצעים שאינם קלט סטנדרטי; ועל הרכב רכיבי UIA, העץ, מאפיינים, דפוסי בקרה, סוגי בקרה ואירועים. ↩ ↩2 ↩3
-
Microsoft Learn, WinForms: Setting the accessible name on a control. על כך ש-Text ממוחזר כ-UIA Name בחלק מהפקדים, בעוד ComboBox, ListBox, ListView, PictureBox, ProgressBar, TabControl, TextBox, TreeView וכדומה לא ממחזרים אותו; על הנחת פקד היעד מיד אחרי TabIndex של Label כך שטקסט ה-Label משמש כ-Name; ועל הגדרת AccessibleName במפורש ובעיית מחרוזת ריקה שנשארת בקובץ המעצב. ↩ ↩2 ↩3 ↩4
-
W3C / Web Accessibility Infrastructure Committee (WAIC) translation, Web Content Accessibility Guidelines (WCAG) 2.1 Japanese translation. על קריטריון הצלחה 1.4.3 (Contrast (Minimum)) של 4.5:1 לטקסט ו-3:1 לטקסט גדול; על קריטריון הצלחה 1.4.1 (Use of Color) של לא להפוך צבע לאמצעי החזותי היחיד; ועל קריטריון הצלחה 2.1.1 (Keyboard) של הפעלת מקלדת של כל הפונקציונליות. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, Contrast themes. על כך שערכות נושא ניגודיות משתמשות בלוח מוגבל של יחס ניגודיות בדרך כלל 7:1 או יותר; על בחירת ערכת נושא מובנית ועריכת צבעים; ועל כך שמשאבי מחלקת SystemColor מוגדרים כזוגות קדמה/רקע ועוקבים אחרי החלפת ערכת נושא אוטומטית. ↩ ↩2 ↩3
-
Microsoft Learn, Accessibility testing. על שלושת התרחישים של Accessibility Insights for Windows — Live Inspect (אישור מאפייני UIA בריחוף/מיקוד), FastPass (זיהוי בעיות בעלות השפעה גבוהה בפחות מחמש דקות), ו-Troubleshooting — ועל ההמלצה לעבור מכלים ישנים כמו Inspect ו-AccEvent. ↩ ↩2 ↩3
-
NVDA Japanese Team, NVDA Japanese edition. על קורא המסך החינמי וקוד פתוח של Windows NVDA ועל אספקת המהדורה היפנית שלו. ↩ ↩2
-
Microsoft Learn, Walkthrough: Creating an Accessible Windows-based Application. על הנחת Label תיאורי בסדר ה-Tab הקודם מיד של שדה קלט; על מקש גישה דרך & ב-Text; על שיפוט ניגודיות גבוהה עם SystemInformation.HighContrast ושימוש ב-SystemColors; על מעקב אחרי אירוע UserPreferenceChanged; ועל שילוב רמז חזותי עם מידע שמועבר בצבע. ↩ ↩2 ↩3
-
Microsoft Learn, Providing Accessibility Information for Controls. על מאפייני AccessibleName, AccessibleDescription, AccessibleRole ו-AccessibleDefaultActionDescription של פקד WinForms ואיך להגדיר אותם. ↩
-
Microsoft Learn, WPF: Setting the accessible name on an edit field. על כך ש-Text של TextBlock ממוחזר כ-UIA Name, בעוד Text של TextBox נחשף כ-UIA Value; ועל שיוך TextBlock תווית ל-TextBox דרך AutomationProperties.LabeledBy, או הגדרת AutomationProperties.Name. ↩
-
Microsoft Learn, UI Automation of a WPF Custom Control. על כך שפקד מותאם דורס OnCreateAutomationPeer ומחזיר מחלקה נגזרת מ-AutomationPeer; על ירושת מחלקת ה-Peer שמתאימה לפקד הבסיס; על אספקת ספק דפוס דרך GetPattern; ועל דריסה מצד XAML עם מאפייני AutomationProperties. ↩ ↩2
מאמרים קשורים
מאמרים עדכניים עם אותן תגיות, להעמקה בנושאים קרובים.
מה "לא מגיב" באמת — איך Windows מחליט שיישום נתקע, ואיך לתכנן יישומים שלא
"לא מגיב" של Windows הוא מנגנון שבו מערכת ההפעלה קובעת שחלון לא שלף הודעה במשך 5 שניות ומחליפה אותו בחלון רפאים. המאמר מכסה את פנים השיפו...
איך לוח ההעתקה וגרירה ושחרור עובדים — טיפול נכון בהעברת נתוני OLE ביישומים עסקיים
מדביקים טבלת Excel והעיצוב מתפרק; סוגרים את יישום המקור ואי אפשר יותר להדביק — שניהם באים מכך שהלוח שם את אותו תוכן בכמה פורמטים בבת אחת....
יישומים שנשברים בחזרה משינה — איך אירועי צריכת החשמל של Windows עובדים ואיך לבנות יישומים עסקיים ששורדים אותם
פתחתם את המחשב הנייד והחיבורים של היישום העסקי היו מתים — הסיבה היא תכנון שלא חשב על שינה. המאמר מכסה את זרימת ההודעות WM_POWERBROADCAST,...
מלכודות גופנים ותווים יפניים — טיפול ב-JIS2004, IVS וגאיג'י ביישומים עסקיים
"התו 葛 נראה שונה על המסך ועל הטופס המודפס." "תו בשם אדם לא מוצג." בעיות תווים במערכות עסקיות נעשות ניתנות לטיפול ברגע שמפרידים את שכבת קו...
עיצוב UX ליישומי Windows - סדרי עדיפות לפי סביבת שימוש
המאמר מסדר מה צריך להעדיף בעיצוב UX ליישומי Windows, בטבלת החלטה לפי ToC/ToB, אמצעי קלט, סביבת שימוש ועלות טעות.
נושאים קשורים
העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.
נושאים טכניים ב-Windows
שער לנושאי פיתוח Windows, חקירת תקלות וניצול נכסים קיימים.
תהליכון ה-UI וטיימרים
תהליכון ה-UI של WPF / WinForms, זרימות אסינכרוניות, Dispatcher ותכנון טיימרים.
שירותים הקשורים לנושא הזה
המאמר קשור ישירות לשירותים הבאים.
פיתוח יישומי Windows
יישומים עסקיים, חיבור התקנים וכלי תקשורת, מהגדרת הדרישות ועד הפיתוח.
שאלות נפוצות
שאלות נפוצות בפניות בנושא המאמר.
- האם תמיכת נגישות ליישום עסקי נדרשת בחוק?
- תיקון 2021 לחוק ביטול האפליה נגד אנשים עם מוגבלות נכנס לתוקף ב-1 באפריל 2024, ומתן התאמה סבירה לאנשים עם מוגבלות הפך לחובה גם לעסקים. התאמה סבירה היא תגובה שמסירה, כשאדם עם מוגבלות מבקש, מחסום אישי בטווח שאינו נטל מופרז; הפיכת היישום לקל יותר לשימוש מראש ממוקמת כחובת מאמץ שנקראת "שיפור סביבתי". תעסוקה, כמו היחס בין עובד לחברה, אינה תחת החוק ההוא אלא תחת חוק קידום תעסוקת אנשים עם מוגבלות, שחייב מעסיקים לספק התאמה סבירה מאז התיקון שנכנס לתוקף באפריל 2016. במילים אחרות, מצב של "עובד לא יכול להשתמש ביישום העסקי" נמצא בתחום החובה כבר זמן מה. עד כמה ללכת בכל מקרה תלוי במצב האישי, לכן מאשרים מקורות ראשוניים ממשרד הקבינט ו ממשרד הבריאות, העבודה והרווחה ומחליטים דרך דיאלוג עם האדם הנוגע בדבר.
- איך קורא מסך קורא יישום שולחן עבודה של Windows?
- קוראי מסך כמו Narrator ו-NVDA קוראים את ממשק היישום דרך תשתית נגישות שנקראת UI Automation (UIA). צד היישום חושף רכיבי מסך במבנה שנקרא עץ UIA; לכל רכיב יש מאפיינים כמו Name (מטרה) ו-ControlType (סוג), ודפוסי בקרה כמו Invoke (לחיצה) ו-Value (ערך). קורא המסך מכריז על המידע הזה כ"כפתור אישור הזמנה" ופועל דרך הדפוסים. פקדי WinForms ו-WPF סטנדרטיים יש להם את המנגנון הזה מההתחלה, ולכן העבודה העיקרית של המפתח היא לא להשאיר Name ריק, להפוך את הממשק להפעלה ממקלדת, ולממש מידע על פקדים מותאמים.
- ביישום WinForms קיים, מאיפה מתחילים?
- הנתיב הקצר ביותר הוא להריץ FastPass ב-Accessibility Insights for Windows מול המסך היעד ולמנות פקדים ש-Name שלהם ריק ובעיות סדר Tab. התיקונים מתחילים בהגדרת AccessibleName על כפתורי-אייקון-בלבד, בשיוך Label בסדר ה-Tab הקודם מיד של שדה קלט, ובסידור TabIndex כך שיתאים לסדר החזותי. אחר כך מפעילים Narrator או NVDA והולכים בפעולה עסקית אמיתית בלי להסתכל על המסך, ומאשרים איפה נתקעים. אין צורך לתקן כל מסך בבת אחת; התחלה ממסכים שמישהו באמת משתמש בהם, והפיכת מסכים חדשים לתואמי-תקן עם רשימת בדיקה, היא מציאותית.
- מה לעשות לתמיכת ניגודיות גבוהה (ערכת נושא ניגודיות)?
- הבסיס הוא לא לקודד צבעים בקשיחות ולכבד צבעי מערכת. ב-WinForms, משאירים ForeColor/BackColor בברירת המחדל או משתמשים ב-SystemColors, שופטים את המצב עם SystemInformation.HighContrast, ועוקבים אחרי החלפה עם אירוע UserPreferenceChanged. גם ב-WPF וב-WinUI, אם מפנים למשאבי מחלקת SystemColors, עוקבים אחרי החלפת ערכת נושא אוטומטית. באותו זמן, מפסיקים להעביר מידע "בצבע בלבד" — הצגת שגיאה באדום בלבד — ומשלבים עם אייקון או ניסוח. גם בערכת הנושא הרגילה, לקיחת קריטריון WCAG של יחס ניגודיות טקסט 4.5:1 או יותר כמדריך גם הופכת את הממשק לקריא יותר לרצפת מפעל חשוכה ולמשתמשים מבוגרים.
- האם תמיכת נגישות עוזרת גם לבדיקות UI אוטומטיות?
- כן. כלי בדיקות UI אוטומטיות כמו FlaUI בנויים על אותו UI Automation שקוראי מסך משתמשים בו. ה-Name, ControlType ודפוסי הבקרה ששמים לנגישות יכולים לשמש כמו שהם מקוד בדיקה, ו-AutomationId שתוכנן לבדיקות מייצב זיהוי רכיבים. לעומת זאת, ממשק מצויר-מותאם שלא מופיע בעץ UIA בלתי-נראה גם לקורא מסך וגם לבדיקות. נגישות ובדיקות אוטומטיות הן השקעה באותה תשתית, ולכן הצבת כל אחת מהן גם מורידה את עלות השנייה.