更新紀錄(僅初版,2026年08月20日 發布)
- 初次發布
引用本文(DOI(已登錄存檔): 10.5281/zenodo.22176509)
以下 DOI 指向先前登錄的存檔,內容可能與目前正文不同。引用目前正文時,請使用本頁網址。
Go Komura(2026)。〈Windows 應用程式無障礙入門 ── 以 UI Automation 因應合理調整的義務化〉。小村軟體有限公司。 https://comcomponent.com/zh-TW/blog/windows-app-accessibility-ui-automation-guide/
- DOI(已登錄存檔)
- 10.5281/zenodo.22176509
- DOI(上次登錄版本)
- 10.5281/zenodo.22176510
「有視覺障礙的同事,沒辦法用螢幕閱讀器操作核心的訂單輸入應用程式。網頁瀏覽器和電子郵件明明用得很順,只有我們自家的業務應用程式讀不出來。」── 來自客戶資訊部門的這類諮詢愈來愈多。
解決這個問題的起點,是去看應用程式向輔助技術傳達了什麼,而不是畫面看起來如何。Windows 內建了 UI Automation(UIA),供螢幕閱讀器讀取應用程式的資訊。只要理解這套機制,並掌握名稱、鍵盤、顏色這三項基礎,業務應用程式的易用性就會大幅改善。1
在法制度上,公司內部的 Windows 應用程式同樣不是局外人。2021 年修正的日本消除對身心障礙者歧視法已於 2024 年 4 月 1 日施行,事業者提供合理調整也成為義務。另一方面,開頭那種僱用領域屬於身心障礙者就業促進法的範圍,自 2016 年 4 月起就是雇主的義務。這項差別會在第 2 章整理。23
Windows 桌面應用程式的無障礙資訊不像 Web 那麼多,也沒有事後一口氣解決的辦法。不過,需要做的改善有很多,無論使用者有沒有障礙,都能提高所有人的生產力。
本文是寫給日本的業務應用程式開發者與資訊部門負責人的說明。先掌握法制度與標準、UIA 的機制,再進入 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. 先講結論
一開始要掌握的是以下三點。
- 把個別的合理調整與事前的環境整備分開來想。 合理調整是針對提出的要求反覆進行建設性對話,在不造成過重負擔的範圍內回應的過程。事業者自 2024 年 4 月起、僱用領域的雇主自 2016 年 4 月起負有義務。事前修改應用程式屬於「環境整備」(努力義務),和一開始就把所有畫面修到完美是兩回事。23
- 技術因應的基礎,是把資訊公開到 UIA,以及名稱、鍵盤、顏色這三項基本功。 UIA 樹上的 Name、ControlType,以及 Invoke、Value、SelectionItem 等模式,就是朗讀與操作的材料。最優先的是命名。WinForms 用 AccessibleName 以及 Label 與 Tab 順序的關聯,WPF 用 AutomationProperties.Name/LabeledBy;此外還要整理鍵盤操作、以對比度 4.5:1 為大致參考值的配色,以及不只靠顏色的呈現方式。1456
- 驗證與修改要從實際的業務出發。 把 Accessibility Insights 的 FastPass 與螢幕閱讀器的實地確認組合起來,依照使用者實際在用的畫面、新畫面、共用控制項的順序逐步整備。這些改善對建立在同一套 UIA 基礎上的 FlaUI 等 UI 自動測試同樣有幫助。7
技術標準可以用 WCAG 為主軸來整理。JIS X 8341-3:2016 是與 WCAG 2.0 內容相同的一致性標準,而 WCAG2ICT 則提供套用到非 Web 軟體的指引。細節在 2.2 節確認。89
若想依目的閱讀,請從下表指出的章節開始。
| 問題與目的 | 要確認的事 | 閱讀章節 |
|---|---|---|
| 想知道「義務化」到底改變了什麼 | 合理調整、環境整備、僱用領域的差別 | 第 2 章 |
| 按鈕或輸入欄無法被正確朗讀 | UIA 的資訊,以及各框架的命名方式 | 第 3〜5 章 |
| 想不用滑鼠就完成整套業務 | Tab 順序、存取鍵、焦點 | 第 6 章 |
| 變更顏色或縮放比例後就難以使用 | 對比、系統顏色、高 DPI | 第 7 章 |
| 想診斷既有應用程式並決定修改範圍 | 自動檢查、實地確認、優先順序與對話紀錄 | 第 8〜9 章 |
用一句話總結,所謂無障礙因應,就是「在 UIA 樹上公開正確的名稱與操作,並守住鍵盤與顏色的基本功」。
圖中實線表示始終成立的關係,虛線表示附帶條件的關係(成立條件寫在詳細頁面中各關係的說明中)。關係的完整清單(共 16 條,附依據與可信度)以及主要概念的定義,彙整在知識地圖詳細頁面(日文)。資料:JSON-LD / Turtle
2. 法制度與標準的整理 ── 「義務化」改變了什麼
2.1. 消除對身心障礙者歧視法 ── 2024 年 4 月起事業者也負有「提供合理調整」的義務
本節分成三點確認:什麼變成了義務、事前的修改如何定位、僱用領域要看哪一部法律。
事業者的合理調整,從努力義務變成了義務
消除對身心障礙者歧視法,是一部要求行政機關等與事業者禁止對身心障礙者「不當差別待遇」,並提供「合理調整」的法律。在 2021 年(令和 3 年)的修正中,原本只是努力義務的事業者提供合理調整改為義務,並於 2024 年(令和 6 年)4 月 1 日施行。2
內閣府的宣導單張說明,這是指當身心障礙者表達出需要排除障礙的意願時,在不造成過重負擔的範圍內加以回應。由於內容會因障礙特性與場合、狀況而不同,因此當事人與事業者反覆對話、共同研擬因應方案的「建設性對話」很重要。文中也明白寫出,單方面拒絕對話可能構成違反提供義務。2
事前修改應用程式,要當成「環境整備」來看
並不是「事先全部處理好」被課成了義務。 以不特定多數身心障礙者為對象,事先推動手冊檢討、教育訓練、設施無障礙化等措施,稱為「環境整備」,定位在努力義務。2
事先把業務應用程式做到可以用螢幕閱讀器操作,可以視為屬於環境整備這一側的作為。整備做得愈完整,提供個別合理調整時的負擔就愈輕。
員工使用的場合,要看身心障礙者就業促進法
僱用與就業的場合,適用的不是消除對身心障礙者歧視法,而是身心障礙者就業促進法。 這項區別在內閣府的宣導單張中也有記載。2
身心障礙者就業促進法在 2016 年(平成 28 年)4 月施行的修正中,已課予雇主禁止僱用領域的身心障礙歧視,並在不造成過重負擔的範圍內提供合理調整的義務。也就是說,開頭那則「員工無法使用業務應用程式」的諮詢,在 2024 年之前就已經落在義務的範圍內。3
flowchart TB
accTitle: 合理調整與環境整備的定位
accDescr: 一般事業者與身心障礙者之間的關係適用消除對身心障礙者歧視法,對個別要求以建設性對話回應的合理調整提供自 2024 年 4 月起成為義務;僱用領域依身心障礙者就業促進法自 2016 年 4 月起是雇主的義務;事前修改應用程式則屬於努力義務的環境整備
scene{"是哪一種場合?"} -->|事業者與身心障礙者| kaisho["消除對身心障礙者歧視法"]
scene -->|僱用與就業的場合| koyou["身心障礙者就業促進法"]
kaisho --> moushide["以建設性對話回應個別要求"]
moushide --> hairyo["提供合理調整(2024 年 4 月起為義務)"]
koyou --> koyougimu["提供合理調整(2016 年 4 月起為義務)"]
kaisho -.-> kankyo["事前修改應用程式=環境整備(努力義務)"]
kankyo -.-> moushide
圖 2: 依場合不同,依據的法律也不同;合理調整是義務,事前修改則屬於環境整備的努力義務。
另外,個別案例在法律上如何處理會因狀況而異。本文不深入法律解釋,而是從「被要求因應時,技術人員能做什麼」的角度往下談。一手資料請參照內閣府與厚生勞動省的文件。23
2.2. JIS X 8341-3 與 WCAG ── 「Web 的標準」也延伸到了軟體
具體去讀技術標準時,以 WCAG 為主軸整理會比較清楚。JIS X 8341-3:2016、WCAG、WCAG2ICT 的關係如下。869
| 標準與文件 | 定位 | 本文的讀法 |
|---|---|---|
| JIS X 8341-3:2016 | ISO/IEC 40500:2012 的一致性標準,標準本文與 WCAG 2.0 內容相同 | 掌握無障礙的技術標準 |
| WCAG | 提出成功準則的文件,從 2.0 擴充到 2.1/2.2,也有 WAIC 的日文翻譯 | 具體確認應該做到的內容 |
| WCAG2ICT | 說明如何把 WCAG 2.0/2.1/2.2 套用到非 Web 文件與軟體的 W3C Group Note | 把同一套想法套用到桌面應用程式 |
「WCAG 不是網頁內容的標準嗎?」這個疑問,由 WCAG2ICT 來搭橋。它的正式名稱是 Guidance on Applying WCAG 2 to Non-Web Information and Communications Technologies。9
文字的替代、對比、鍵盤操作、不只靠顏色傳達資訊等想法,都能以同一套框架套用到 Windows 桌面應用程式。第 3 章之後,會把這些落實到 WinForms/WPF 的實作上。
flowchart TB
accTitle: JIS X 8341-3 與 WCAG 的關係
accDescr: JIS X 8341-3:2016 是與 WCAG 2.0 內容相同的一致性標準,而 WCAG2ICT 說明如何把 WCAG 的成功準則套用到非 Web 軟體,因此 Windows 桌面應用程式也能以同一套框架檢視
wcag["WCAG 2.0(W3C)"] ---|內容相同的一致性標準| jis["JIS X 8341-3:2016"]
wcag --> ict["WCAG2ICT"]
ict --> soft["套用到非 Web 軟體"]
soft --> app["Windows 桌面應用程式"]
圖 3: JIS X 8341-3:2016 是 WCAG 2.0 的一致性標準,WCAG2ICT 則把同一套準則延伸到桌面應用程式。
3. 輔助技術讀取應用程式的機制 ── UI Automation 的三件組
3.1. UIA 樹、屬性、控制項模式
Windows 內建的 UI Automation(UIA),是居中連接應用程式端與輔助技術端的無障礙基礎架構。應用程式端以「提供者」的身分公開 UI 資訊,螢幕閱讀器等輔助技術端則以「用戶端」的身分取得資訊。以標準輸入以外的手段操作 UI,也是靠這套機制達成。1
首先請用畫面的結構、元素的性質、可做的操作這三件組來理解。1
| 要素 | 作用 | 代表例 |
|---|---|---|
| UIA 樹 | 以桌面為根節點,依視窗→控制項一路串起來的樹狀結構。輔助技術沿著這棵樹掌握 UI | 視窗、窗格、按鈕、編輯方塊 |
| 屬性 | 表示各元素性質的值 | 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 上主要的螢幕閱讀器有內建的旁白、免費開放原始碼的 NVDA10,以及在日本國內廣泛使用的商用軟體 PC-Talker。
它們朗讀的方式各有不同,但讀取桌面應用程式 UI 的主要途徑都是 UIA。應用程式端要做的事,不是只針對特定的螢幕閱讀器,而是集中在把正確的資訊公開到 UIA這一點上。
flowchart TB
accTitle: 主要螢幕閱讀器的共同途徑
accDescr: 只要應用程式把正確的資訊公開到 UIA,旁白、NVDA、PC-Talker 都能沿同一條途徑讀取 UI,因此應用程式端要做的不是針對特定螢幕閱讀器,而是集中在公開資訊到 UIA
app["應用程式"] -->|公開資訊| uia["UI Automation(UIA)"]
uia --> nar["旁白"]
uia --> nvda["NVDA"]
uia --> pct["PC-Talker"]
app -.-> goal["因應集中在公開到 UIA"]
圖 5: 主要的螢幕閱讀器都以 UIA 為途徑,因此應用程式的因應集中在公開資訊到 UIA。
3.3. 「Name 空白的按鈕」會被讀成什麼
假設工具列上有一個只顯示磁片圖示的儲存按鈕。就算用看的就知道它的用途,只要 Name 還是空的,螢幕閱讀器就只會唸出「按鈕」。如果旁邊的「開啟」「列印」也是一樣的狀態,聽到的就只是「按鈕、按鈕、按鈕」,完全分不出來。
沒有 Name 的按鈕,以及只會被讀成「Image」的圖片,在 Microsoft 的修正指南中也被列為會讓使用者工作停擺的代表性問題。5
WinForms/WPF 的標準控制項一開始就支援 UIA,多數會從文字或標籤自動決定 Name。會出問題的典型狀況有以下三種。
| 典型的原因 | 要確認的地方 |
|---|---|
| 只有圖示,沒有可當名稱的材料 | 是否明確指定了朗讀用的名稱 |
| 沒有與標籤建立關聯 | 是否把輸入欄與顯示用標籤關聯起來 |
| 自訂繪製,沒有公開資訊 | UIA 樹上是否出現有意義的資訊 |
接下來的兩章,會把這套釐清原因的方式,分別接到 WinForms 與 WPF 的修法上。
flowchart TB
accTitle: 朗讀失效的三種典型
accDescr: 只有圖示而沒有可當名稱的材料、沒有與標籤建立關聯、自訂繪製而 UIA 樹上沒有資訊,這三種情況會讓朗讀失效,變成只會被唸成按鈕的狀態
c1["只有圖示,沒有材料"] --> broken["Name 變成空的"]
c2["沒有標籤關聯"] --> broken
c3["自訂繪製,沒有資訊"] --> broken
broken --> result["只會被唸成按鈕"]
圖 6: 朗讀失效大多可歸結為名稱材料不足、關聯不足、自訂繪製這三種情況。
4. 在 WinForms 的實作 ── AccessibleName 與 Tab 順序
4.1. Text 會自動變成 Name 的控制項,以及不會的控制項
先確認它是不是會把 Text 當名稱的種類
在 WinForms 中,即使同樣是會顯示文字的控制項,也分成 Text 會被用作 UIA Name 的,和不會的。4
| 控制項範例 | Name 的處理方式 |
|---|---|
| Button、CheckBox | Text 屬性的值會被用作 Name |
| ComboBox、ListBox、ListView、PictureBox、ProgressBar、TabControl、TextBox、TreeView | Text 不會變成 Name,必須用其他方式給名稱 |
用顯示用標籤,放不下時再設定 AccessibleName
最好維護的作法,是把說明用的 Label 放在目標控制項前一個 Tab 順序。只要讓目標控制項的 TabIndex 緊接在 Label 的 TabIndex 之後,Label 的文字就會被用作 UIA 的 Name。這樣畫面顯示與朗讀內容會一致,文案也不必兩邊各維護一份。411
放不下 Label 時,就明確指定 AccessibleName。補充說明可用 AccessibleDescription,需要讓角色符合實際情況時,還可以設定 AccessibleRole。12
flowchart TB
accTitle: WinForms 控制項決定名稱的方式
accDescr: Button 之類的控制項會直接把 Text 當成 UIA 的 Name,TextBox 這類不沿用 Text 的控制項則使用放在前一個 Tab 順序的 Label 文字,放不下 Label 時就明確設定 AccessibleName
ctrl["控制項"] --> qtext{"是 Text 會變成 Name 的種類?"}
qtext -->|是| usetext["Text 直接變成 Name"]
qtext -->|否| qlabel{"前一個 Tab 順序有 Label?"}
qlabel -->|是| uselabel["使用 Label 的文字當 Name"]
qlabel -->|否| explicit["明確設定 AccessibleName"]
圖 7: WinForms 的 Name 依 Text、前一個 Tab 順序的 Label、AccessibleName 的順序挑選決定方式。
// 只有圖示的工具列按鈕: 明確指定朗讀用的名稱
saveToolStripButton.AccessibleName = "儲存";
// 只有圖片的按鈕: 名稱+補充說明
btnSearchCustomer.AccessibleName = "搜尋客戶";
btnSearchCustomer.AccessibleDescription = "以客戶代號或姓名搜尋客戶主檔";
// 無法把 Label 放在前一個 Tab 順序的輸入欄,就直接設定
txtOrderNo.AccessibleName = "訂單編號";
// 轉用來顯示圖表的 PictureBox: 角色也要符合實際情況
pictureBoxChart.AccessibleRole = AccessibleRole.Chart;
pictureBoxChart.AccessibleName = "各月訂單件數圖表";
明明刪掉了名稱,卻回不到預設的朗讀時
在 Visual Studio 的屬性窗格中設定過 AccessibleName 之後再刪掉,設計工具檔裡有時會只留下設為空字串的那一行。當這行設定妨礙預設的名稱解析時,請從設計工具檔中刪除該行。4
flowchart TB
accTitle: AccessibleName 殘留空字串的問題
accDescr: 在屬性窗格設定過 AccessibleName 再刪掉時,設計工具檔會殘留設為空字串的設定並妨礙預設的名稱解析,要從設計工具檔刪除該行來修正
set["設定 AccessibleName"] --> erase["在屬性窗格刪掉"]
erase --> remain["殘留空字串的設定"]
remain --> block["妨礙預設的名稱解析"]
block -.-> fix["刪除設計工具檔的該行"]
圖 8: 即使在屬性窗格刪掉,空字串仍會殘留,要刪除設計工具檔的該行才能修正。
4.2. 訂單輸入畫面常見的改善點
以下把本公司在業務應用程式中實際常修改的地方整理成檢查清單。
| 常見狀態 | 問題 | 修改方式 |
|---|---|---|
| 只有圖示的 ToolStripButton | 只會被唸成「按鈕」 | 設定 AccessibleName |
| TextBox 附近雖然有 Label,Tab 順序卻很亂 | 輸入欄的名稱是空的,或變成毫不相關的名稱 | 把輸入欄放在 Label 的 TabIndex 正後方 |
| 把 PictureBox 當按鈕,靠 Click 使用 | 角色沒有以按鈕的形式傳達,也無法用鍵盤按下 | 改用 Button,或設定 AccessibleRole/AccessibleName 並加上鍵盤支援 |
| DataGridView 的欄標頭是空的或只有符號 | 朗讀儲存格時無法得知欄位的意義 | 在 HeaderText 設定有意義的欄名 |
| 只用 Panel 做內容分組,標題還是圖片 | 無法分辨這是哪一組輸入欄 | 改用 GroupBox,或把標題改成 Label |
這些都只是幾行的修改,但對螢幕閱讀器的使用者來說,卻是「不能用的畫面」與「能用的畫面」之間的分水嶺。
5. 在 WPF 的實作 ── AutomationProperties 與 AutomationPeer
5.1. AutomationProperties.Name / LabeledBy / HelpText
按鈕的名稱,用字串的 Content 或明確設定來給
像 WPF 的 Button 這種 Content 是字串的控制項,其內容會被用作 UIA 的 Name。另一方面,只放 Image 或 Path 的按鈕沒有可當名稱的材料。此時要用 AutomationProperties.Name 明確指定;若附近有顯示文字,則用 AutomationProperties.LabeledBy 建立關聯。5
在 TextBox 要把「名稱」和「輸入值」分開
TextBlock 的 Text 會被沿用為 Name,但 TextBox 的 Text 是公開在 UIA 的 Value 屬性那一側,不會變成 Name。即使裡面已經有輸入值,光靠那個也傳達不出「這是要輸入什麼的欄位」。13
輸入欄的第一選擇,是用 LabeledBy 把顯示用標籤的 TextBlock 關聯起來。這樣畫面顯示與朗讀內容一致,也不必兩邊維護同一份文案。13
<!-- 輸入欄: 用 LabeledBy 關聯顯示用標籤 -->
<TextBlock x:Name="OrderNoLabel" Text="訂單編號" />
<TextBox
AutomationProperties.LabeledBy="{Binding ElementName=OrderNoLabel}"
AutomationProperties.AutomationId="OrderNoTextBox" />
<!-- 只有圖示的按鈕: 明確指定名稱,必要時再加上補充說明 -->
<Button
AutomationProperties.Name="確定訂單"
AutomationProperties.HelpText="確定目前輸入中的訂單,並分配庫存">
<Path Data="{StaticResource CheckIconGeometry}" Width="16" Height="16" />
</Button>
flowchart TB
accTitle: WPF 控制項決定名稱的方式
accDescr: Content 是字串的控制項會直接用其內容當 Name,否則第一選擇是用 LabeledBy 關聯附近的顯示用標籤,都沒有時就明確指定 AutomationProperties.Name,而 TextBox 的 Text 公開在 Value 而不是 Name
ctrl["控制項"] --> qc{"Content 是字串?"}
qc -->|是| auto["內容變成 Name"]
qc -->|否| ql{"附近有顯示用標籤?"}
ql -->|是| lb["用 LabeledBy 建立關聯"]
ql -->|否| nm["明確設定 Name"]
tbx["TextBox 的 Text"] -.-> val["公開在 Value 而非 Name"]
圖 9: WPF 的 Name 依 Content 字串、LabeledBy、明確設定的順序決定,而 TextBox 的 Text 不會變成 Name。
HelpText 與 AutomationId 的角色和名稱不同
放不進 Name 的補充資訊,就用 AutomationProperties.HelpText 公開。5 AutomationId 則是連 UI 自動測試定位元素時也會用到的識別碼。在畫面設計階段就先訂好命名規則,後續測試會很有幫助。
歸納起來,Name 是用途、HelpText 是補充、AutomationId 是識別碼。在自動測試中的用法,在「Windows 桌面應用程式的 UI 自動測試」中有詳細說明。
5.2. 自訂控制項要用 AutomationPeer
自訂繪製的控制項就這樣放著,是無法把有意義的資訊公開到 UIA 樹上的。在 WPF 中,要覆寫 UIElement 衍生類別的 OnCreateAutomationPeer,回傳 AutomationPeer 的衍生類別,藉此公開名稱、種類與模式。14
若是繼承既有控制項,對應的 Peer 也要一併繼承。例如繼承 ButtonBase 時就用 ButtonBaseAutomationPeer,便能沿用已經實作好的行為。14
flowchart TB
accTitle: AutomationPeer 公開資訊的機制
accDescr: 自訂控制項覆寫 OnCreateAutomationPeer 回傳 AutomationPeer 衍生類別,藉此公開名稱、種類與模式;若繼承既有控制項,則繼承對應的 Peer 以沿用已實作好的行為
custom["自訂控制項"] --> ov["OnCreateAutomationPeer"]
ov --> peer["回傳 Peer 衍生類別"]
peer --> pub["公開名稱、種類、模式"]
inherit["繼承既有控制項"] -.-> basepeer["繼承對應的 Peer"]
basepeer -.-> reuse["沿用已實作好的行為"]
圖 10: 自訂控制項以 OnCreateAutomationPeer 回傳 Peer,把資訊公開到 UIA。
// 以彩色燈號自訂繪製線路狀態的控制項範例
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 ? "線路狀態: 連線中" : "線路狀態: 已離線";
private static void OnIsOnlineChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// 在值改變的瞬間發出 UIA 的屬性變更事件。少了這一步,
// 螢幕閱讀器會一直抱著舊名稱,察覺不到狀態的變化
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
protected override string GetNameCore()
=> StatusLamp.NameFor(((StatusLamp)Owner).IsOnline);
}
不只回傳目前的名稱,也要通知狀態的變化
上面的範例把兩件事組合在一起:依目前狀態回傳名稱的處理,以及 IsOnline 改變時發出 Name 屬性變更事件的處理。
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 等模式介面。14
只要在共用控制項程式庫這一側連 Peer 都做好,使用它的所有畫面就自動完成因應。 這正是第 9 章要說明的橫向展開的基礎。
6. 能不能只用鍵盤到達所有功能
WCAG 的成功準則 2.1.1(鍵盤)要求所有功能都必須能從鍵盤介面操作。6 螢幕閱讀器的使用者原則上不用滑鼠,因此鍵盤到不了的功能,等同於不存在的功能。
6.1. 檢查移動、執行與目前位置
要確認的不只是 Tab 順序,還包括能不能執行主要操作,以及看不看得出目前的焦點在哪裡。
| 觀點 | 要確認的事 | WinForms / WPF 的主要手段 |
|---|---|---|
| Tab 順序 | Tab 鍵的移動順序是否與視覺排列(左上→右下)一致 | 整理 TabIndex、設定 TabStop |
| 存取鍵 | 能否用 Alt+英文字母直接移到主要項目 | WinForms 在 Text 加 &,WPF 在標頭加 _ |
| 快速鍵 | 常用操作(儲存、搜尋、確定)是否各有獨立的按鍵 | 指派 Ctrl+S 等按鍵,並標示在功能表上 |
| 焦點顯示 | 能否用眼睛看出目前焦點在哪裡 | 不要拿掉焦點外框,自訂繪製時要自己畫 |
| 只能用滑鼠的功能 | 有沒有只能靠雙擊、右鍵、拖曳、停留才能使用的功能 | 同樣的功能也要在功能表與按鍵上一併提供 |
| 對話方塊 | Enter=預設按鈕、Esc=取消是否有作用 | AcceptButton/CancelButton、IsDefault/IsCancel |
在 WinForms 的無障礙指引中,也把「把標籤放在輸入欄前一個 Tab 順序」與「為使用者會想移動過去的控制項和功能表加上存取鍵」列為基本作法。11
6.2. 整理鍵盤操作,也會提升所有使用者的輸入效率
這不只是「為身心障礙者因應而多付的成本」。在訂單輸入這類固定作業中,手不離開基準鍵位就能完成輸入與否,直接決定了操作員的處理件數。
Tab 順序混亂、非用滑鼠不可的操作,都是每天一點一點削掉所有使用者生產力的缺陷。無障礙因應與鍵盤效率化,只是同一件工作的兩種叫法。依使用環境排定的優先順序,也請參照「Windows 應用程式 UX 設計」。
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(對比(最低限度))要求文字與文字圖片至少要有 4.5:1,大型文字至少要有 3:1 的對比度。6
把淡灰色文字放在白底上的設計,跌破這個標準並不罕見。請把因年齡而視力、色覺改變的人,以及在工廠這類照明條件不佳的場所使用的人也納入設想,養成在檢視設計時用對比檢查工具實測的習慣。
7.2. 不要只用顏色傳達資訊
成功準則 1.4.1(顏色的使用)要求顏色不可以成為傳達資訊的唯一視覺手段。6 業務應用程式的典型例子如下。
| 只靠顏色傳達的狀態 | 可並用的手段 |
|---|---|
| 只用紅色文字標示錯誤的資料列 | 錯誤圖示與訊息欄 |
| 只用標籤顏色標示必填項目 | 加上「*」或「必填」的標記 |
| 只用燈號顏色標示狀態 | 顏色搭配形狀,或「運轉中」「停止」等文字 |
考慮到色覺的多樣性,這同樣不是「特別的因應」,而是顯示設計的基本功。
flowchart TB
accTitle: 改成不只靠顏色的資訊傳達
accDescr: 只用紅色文字標示錯誤的呈現改成並列錯誤圖示與訊息欄,只用標籤顏色標示必填項目的呈現改成加上必填的標記,只用燈號顏色標示狀態的呈現改成並用形狀或文字
err["錯誤只用紅色文字"] --> erra["並列圖示與文字"]
req["必填只用標籤顏色"] --> reqa["加上必填的標記"]
lamp["狀態只用燈號顏色"] --> lampa["顏色並用形狀或文字"]
圖 13: 只靠顏色傳達的典型例子,都可以換成並用圖示、標記、形狀或文字。
7.3. 跟隨對比佈景主題(高對比)
Windows 的對比佈景主題(過去的高對比)是把前景與背景強烈分離的配色。內建佈景主題設計成對比度大致在 7:1 以上,使用者可以自行選擇與編輯。15
應用程式端則要不把顏色寫死,尊重系統顏色。各框架的作法如下。
| 框架 | 基本配色 | 有自訂配色時的確認事項 |
|---|---|---|
| WinForms | 讓 ForeColor/BackColor 維持預設,使用使用者的配色設定 | 以 SystemInformation.HighContrast 判斷後切換成以 SystemColors 為基礎的配色,並用 UserPreferenceChanged 跟隨設定變更 |
| WPF/WinUI | 參照 SystemColors 系列的資源,跟隨佈景主題切換 | 確認用自訂筆刷塗滿的地方是不是造成畫面跑掉的原因 |
WinForms 的具體設定請參照 Microsoft 的指引,佈景主題的配色請參照對比佈景主題的文件。1115
flowchart TB
accTitle: 跟隨對比佈景主題
accDescr: 把顏色寫死的地方在切換到對比佈景主題時會跑掉,因此要改成以 SystemColors 為基礎的配色並用設定變更事件跟隨,只要參照系統顏色就能自動跟隨使用者的配色
theme["切換到對比佈景主題"] --> qh{"顏色的指定方式?"}
qh -->|寫死| broken["配色跑掉"]
qh -->|參照系統顏色| ok["自動跟隨使用者的配色"]
broken -.-> fix["改用 SystemColors"]
fix -.-> ev["用設定變更事件跟隨"]
圖 14: 只有把顏色寫死的地方會在對比佈景主題下跑掉,參照系統顏色就能自動跟隨。
高 DPI 下不跑版,同樣列入這項檢查
弱視的使用者常會把作業系統的縮放比例(DPI 縮放)調高來使用,因此高 DPI 支援也是無障礙因應的一部分。在 125%〜200% 就會版面跑掉的應用程式,在那樣的使用環境下就是不能用。
具體的處理方式請參照「WinForms 的高 DPI 支援」與「WPF 的高 DPI 支援」。
8. 驗證的實務 ── Accessibility Insights 與螢幕閱讀器的實地確認
8.1. Accessibility Insights for Windows
Microsoft 提供的 Accessibility Insights for Windows,可以依目的選擇三種用法。7
| 用法 | 能確認什麼 | 使用場合 |
|---|---|---|
| Live Inspect | 滑鼠停留或鍵盤焦點所在元素的 UIA 資訊(Name、ControlType、模式等) | 用最短路徑查出「這個按鈕的 Name 是什麼」 |
| FastPass | 在五分鐘內找出高影響問題的輕量檢查,查的是 Name 缺漏這類可機械判定的問題 | 為每個新畫面盤點問題 |
| Troubleshooting | 協助診斷與修正特定問題,從找到的問題連到各框架的修正指南 | 查出找到的問題該怎麼修 |
Windows SDK 內含的 Inspect.exe 與 AccEvent 也能確認 UIA 樹與屬性,但它們被定位為舊版工具,目前建議改用 Accessibility Insights。7
flowchart TB
accTitle: Accessibility Insights 的三種用法
accDescr: Accessibility Insights for Windows 以 Live Inspect 確認 UIA 屬性、以 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. 用螢幕閱讀器做實地確認
通過自動檢查,和真的能完成業務,是兩回事。 工具能找出來的只有可機械判定的問題,因此最後一定要用螢幕閱讀器把業務操作走完一輪。
首先,用 Ctrl+Windows 鍵+Enter 啟動旁白,或安裝免費的 NVDA。10 接著訂出「輸入並確定一筆訂單」這類代表性任務,不看畫面,或乾脆關掉螢幕,試試看能不能只靠朗讀完成。
名稱雖然有了,但朗讀順序七零八落,或焦點跑到強制回應對話方塊之外——這類問題不做實地確認是找不出來的。
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 | 能用螢幕閱讀器完成代表性任務 | 旁白/NVDA |
把 UIA 的整備也用在自動測試上
FlaUI 這類 UI 自動測試,和螢幕閱讀器建立在同一套 UIA 之上。為了無障礙而整理好的 Name 與模式,會直接成為測試程式碼的零件;為了測試而設計的 AutomationId,也讓在 Live Inspect 裡偵錯變得輕鬆。
反過來說,不會出現在 UIA 樹上的 UI,測試與輔助技術都看不見。無障礙與可測試性,是同一筆投資的一體兩面。 詳情請參照「Windows 桌面應用程式的 UI 自動測試」。
flowchart TB
accTitle: 無障礙與 UI 自動測試的相乘效果
accDescr: 螢幕閱讀器與 FlaUI 等 UI 自動測試建立在同一套 UIA 之上,因此整理好的 Name 與模式兩邊都能使用,而不會出現在 UIA 樹上的 UI 兩邊都看不見
uia["整備 UIA 樹"] --> sr["螢幕閱讀器讀得到"]
uia --> test["UI 自動測試用得到"]
sr -.-> both["同一筆投資的一體兩面"]
test -.-> both
hidden["不出現在 UIA 的 UI"] -.-> invisible["兩邊都看不見"]
圖 17: 因為建立在同一套 UIA 基礎上,整備 UIA 樹對輔助技術與 UI 自動測試都有效。
9. 排定優先順序的方法 ── 不要一次修完所有畫面
要把數百個畫面的核心系統一次全部改掉,不論在成本還是品質上都不切實際。本公司建議依下面三個階段推進。
9.1. 從那位使用者實際在業務中使用的畫面開始修
合理調整是針對當事人的要求個別回應的過程。2 請先請本人用螢幕閱讀器實際操作業務,一起找出卡住的地方。
多數情況下,日常業務會用到的畫面會收斂到數個到十幾個。其中的致命問題,例如沒有名稱的按鈕、無法用鍵盤按下的確定按鈕,用幾天的修改就能解決。
9.2. 新開發的部分預設就做到位
把第 8 章的檢查清單加進完成的定義(Definition of Done)。方針是新畫面一開始就做成已完成因應的狀態。和事後補修不同,在設計階段就納入的成本增加非常有限。
9.3. 用共用控制項的修改做橫向展開
在公司內共用的搜尋對話方塊、格線、日期輸入等元件上,實作 AccessibleName 的預設值或 AutomationPeer。只要修好共用元件,使用它的所有畫面就會一次生效。比起一個一個修改個別畫面,這是成本效益更高的做法。
flowchart TB
accTitle: 修改優先順序的三段式做法
accDescr: 先從使用者在業務中使用的畫面修起,新開發的部分以檢查清單做成標準因應,再用共用控制項的修改橫向展開到所有畫面
s1["1. 從使用者在用的畫面修起"] --> s2["2. 新開發的部分預設做到位"] --> s3["3. 用共用控制項橫向展開"]
s3 -.-> all["對使用它的所有畫面一次生效"]
圖 18: 不是一次改完所有畫面,而是用在用的畫面、新開發的部分、共用元件這三段式推進。
9.4. 不只記錄修改內容,也要記錄對話的經過
和技術因應同樣重要的,是對話的紀錄。合理調整是透過對話個別調整的過程,而不是把所有要求都完全滿足。
面對負擔過重的修改,改用其他畫面執行該項業務、提供 CSV 匯出、以維運方式補足等替代手段,只要與本人一起研議並取得共識,同樣是建設性對話的正當結果。2
把被要求了什麼、做了哪些因應、以什麼作為替代手段記錄下來,就是組織展現誠信的證明。
flowchart TB
accTitle: 建設性對話與紀錄的流程
accDescr: 面對身心障礙者的要求以建設性對話回應,能做的修改就執行,負擔過重的修改則與本人研議替代手段並取得共識,並記錄被要求了什麼、做了哪些因應、以什麼作為替代手段
req["要求"] --> talk["建設性對話"]
talk --> q{"負擔是否過重?"}
q -->|否| kaishu["以修改因應"]
q -->|是| alt["研議替代手段並取得共識"]
kaishu --> rec["記錄經過"]
alt --> rec
圖 19: 建設性對話要與本人就修改或替代手段取得共識,並把經過留在紀錄裡。
10. 總結
把法制度、技術、推進方式分開來看,著手點就會浮現。
在法制度上,事業者的合理調整自 2024 年 4 月起、僱用領域雇主的合理調整自 2016 年起是義務。事前修改應用程式屬於「環境整備」(努力義務),做得愈多,個別因應就愈輕鬆。對話的經過也請留下紀錄。
在技術上,以 WCAG(JIS X 8341-3:2016)為主軸,透過 WCAG2ICT 檢視桌面應用程式。基礎是 UIA 樹、屬性(Name/ControlType/AutomationId)與控制項模式。最優先的命名,WinForms 用 AccessibleName 以及 Label 與 Tab 順序,WPF 用 AutomationProperties.Name/LabeledBy,自訂控制項則用 AutomationPeer 來處理。
在這之上,為了只用鍵盤就能到達所有功能,要整理 Tab 順序、存取鍵與焦點顯示。顏色以對比度 4.5:1 為大致的參考值,不只靠顏色,在對比佈景主題下則尊重系統顏色。這些改善同樣關係到全體操作員的生產力。
推進方式依序是使用者在用的畫面、新開發部分的標準因應、共用控制項的橫向展開。請把 Accessibility Insights 的 FastPass、Live Inspect,和旁白/NVDA 的實地確認組合起來,做成新畫面的檢查清單放進開發流程。
建議的第一步,是挑一個自家的主力畫面,先執行 Accessibility Insights for Windows 的 FastPass,再只用 Tab 鍵把業務走完一輪。三十分鐘內,自家應用程式目前的位置就會具體得令人意外。
相關文章
- Windows 桌面應用程式的 UI 自動測試 ── UI Automation 的原理與用 FlaUI 打造不易損壞的測試
- Windows 應用程式 UX 設計 - 依使用環境排定的優先順序
- WinForms 的高 DPI 支援 ── 4K 螢幕上模糊、跑版的原因與務實對策
- WPF 的高 DPI 支援 ── 「應該對 DPI 很強才對」卻仍模糊、暈開的原因與對策
- 小村軟體為什麼用日本數位廳設計系統做官網 ── 便宜與品質可以兼顧
- 日文字型與文字的陷阱 ── 業務應用程式如何處理 JIS2004、異體字選擇器與外字
相關諮詢領域
小村軟體有限公司承接 WinForms/WPF 業務應用程式的無障礙改善(螢幕閱讀器支援、鍵盤操作的整備、對比佈景主題支援)、在共用控制項實作 AutomationPeer,以及使用 Accessibility Insights 進行現況診斷與排定優先順序的諮詢。從「想確認員工能不能用螢幕閱讀器使用我們的應用程式」這個階段開始也沒問題。
參考連結
-
Microsoft Learn, UI Automation Specification. 說明 UI Automation 向螢幕閱讀器等輔助技術提供 UI 資訊,並讓標準輸入以外的手段得以操作,以及 UIA 元素、樹、屬性、控制項模式、控制項類型與事件的組成。 ↩ ↩2 ↩3 ↩4
-
內閣府, 宣導單張「自令和 6 年 4 月 1 日起提供合理調整成為義務」. 說明令和 3 年修正的消除對身心障礙者歧視法於令和 6 年 4 月 1 日施行、事業者提供合理調整成為義務;提供合理調整是針對身心障礙者表明的意願,在不造成過重負擔的範圍內回應;建設性對話的重要性以及單方面拒絕可能構成違反義務;以不特定多數身心障礙者為對象的事前改善措施「環境整備」屬於努力義務;以及僱用與就業依身心障礙者就業促進法的規定。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9
-
厚生勞動省, 僱用領域中對身心障礙者的禁止歧視與提供合理調整的義務. 說明平成 28 年 4 月施行的身心障礙者就業促進法修正,課予雇主禁止僱用領域的身心障礙歧視,以及在不造成過重負擔的範圍內提供合理調整的義務,並整理合理調整指針等相關資料。 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, WinForms: Setting the accessible name on a control. 說明部分控制項會把 Text 沿用為 UIA Name,而 ComboBox、ListBox、ListView、PictureBox、ProgressBar、TabControl、TextBox、TreeView 等則不會;把目標控制項放在 Label 的 TabIndex 正後方即可讓 Label 的文字被用作 Name;以及明確設定 AccessibleName,與空字串殘留在設計工具檔的問題。 ↩ ↩2 ↩3 ↩4
-
W3C/網頁無障礙基礎委員會(WAIC)翻譯, Web Content Accessibility Guidelines (WCAG) 2.1 日文翻譯. 說明成功準則 1.4.3(對比(最低限度))的文字 4.5:1、大型文字 3:1,成功準則 1.4.1(顏色的使用)不讓顏色成為唯一的視覺手段,以及成功準則 2.1.1(鍵盤)要求所有功能都能以鍵盤操作。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Accessibility testing. 說明 Accessibility Insights for Windows 的 Live Inspect(以滑鼠停留/焦點確認 UIA 屬性)、FastPass(五分鐘內找出高影響問題)、Troubleshooting 三種情境,以及建議從 Inspect、AccEvent 等舊版工具移轉過來。 ↩ ↩2 ↩3
-
網頁無障礙基礎委員會(WAIC), 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). 說明如何把 WCAG 2.0/2.1/2.2 的原則、指導方針與成功準則套用到非 Web 文件與軟體的 W3C Group Note。 ↩ ↩2 ↩3
-
NVDA 日本語團隊, NVDA 日本語版. 關於免費開放原始碼的 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. 說明 WinForms 控制項的 AccessibleName、AccessibleDescription、AccessibleRole、AccessibleDefaultActionDescription 各屬性與設定方式。 ↩
-
Microsoft Learn, WPF: Setting the accessible name on an edit field. 說明 TextBlock 的 Text 會沿用為 UIA Name,但 TextBox 的 Text 是以 UIA Value 公開,以及 TextBox 應以 AutomationProperties.LabeledBy 關聯標籤用的 TextBlock,或設定 AutomationProperties.Name。 ↩ ↩2
-
Microsoft Learn, UI Automation of a WPF Custom Control. 說明自訂控制項覆寫 OnCreateAutomationPeer 回傳 AutomationPeer 衍生類別、繼承對應基底控制項的 Peer 類別、以 GetPattern 提供模式提供者,以及從 XAML 端以 AutomationProperties 附加屬性覆寫。 ↩ ↩2 ↩3
-
Microsoft Learn, Contrast themes. 說明對比佈景主題使用對比度大致 7:1 以上的受限調色盤、內建佈景主題的選擇與顏色編輯,以及 SystemColor 系列資源以前景/背景成對定義並自動跟隨佈景主題切換。 ↩ ↩2
相關文章
共用相同標籤的最新文章。能以相近的主題延伸理解。
Windows 應用程式的深色模式與對比佈景主題支援 ── DWM 的深色標題列、WinForms/WPF 跟隨系統佈景主題、高對比時的繪製
說明如何讓 WinForms/WPF 應用程式跟隨 Windows 11 的深色模式與對比佈景主題。整理 DWM 的深色標題列、.NET 9/10 的 SetColorMode 與 ThemeMode、佈景主題切換的偵測,以及高對比時以系統色彩繪製的做法。
Windows 桌面應用程式的 UI 自動測試 ── UI Automation 的原理與用 FlaUI 打造不易損壞的測試
本文從 Windows UI Automation 的原理(樹狀結構、AutomationId、控制項模式)整理 WinForms/WPF 應用程式的 UI 自動測試。內容涵蓋以 FlaUI 實作的最小範例、WinAppDriver 的現況、透過 AutomationId ...
委外・委託開發 Windows 應用程式前該整理的事項
在委外・委託開發 Windows 應用程式之前,整理既有軟體改版、設備整合、COM/ActiveX、發布與更新、維護等應留意的重點。
Windows 列印驅動程式停止提供 ── 業務應用程式的報表與標籤列印如何因應
Microsoft 正分階段推動 v3/v4 列印驅動程式的停止提供,從 2026 年 7 月起會優先選用 IPP 類別驅動程式。本文整理 Windows protected print mode 之下會消失哪些東西,並以判斷表梳理業務應用程式的報表、標籤列印中相依處的盤點...
「沒有回應」的真面目 ── Windows 如何判定應用程式卡住,以及不卡住的設計
Windows 的「沒有回應」,是視窗 5 秒沒有取出訊息時由作業系統判定、並換成幽靈視窗的機制。本文從判定的內部運作,講到卡住的經典原因、把重工作移出 UI 執行緒的設計,以及無回應的調查程序。
相關主題
與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。
Windows 技術主題
彙整 KomuraSoft LLC 關於 Windows 開發、故障調查與既有資產活用文章的主題中心。
UI 執行緒 & 計時器
整理 WPF / WinForms UI 執行緒、非同步流程、Dispatcher 使用、計時器判斷的主題頁面。
常見問題
整理諮詢這個主題時常見的問題。
- 業務應用程式的無障礙因應,是法律規定的義務嗎?
- 2021 年修正的日本消除對身心障礙者歧視法已於 2024 年 4 月 1 日施行,事業者對身心障礙者提供合理調整也成為義務。合理調整是指身心障礙者提出要求時,在不造成過重負擔的範圍內排除個別障礙的作法;事先把應用程式改得更好用,則歸類為「環境整備」這項努力義務。另外,員工與公司這類僱用領域不適用消除對身心障礙者歧視法,而屬於身心障礙者就業促進法的範圍,該法在 2016 年 4 月施行的修正中已課予雇主提供合理調整的義務。也就是說,「員工無法使用業務應用程式」這種情境,在更早之前就已經落在義務的範圍內。要做什麼、做到什麼程度會因個案而異,因此請先確認內閣府與厚生勞動省的一手資料,再透過與當事人的對話來決定。
- 螢幕閱讀器是怎麼朗讀 Windows 桌面應用程式的?
- 旁白與 NVDA 這類螢幕閱讀器,是透過 UI Automation(UIA)這套無障礙基礎架構讀取應用程式的 UI。應用程式端以 UIA 樹這種結構公開畫面上的元素,每個元素具有 Name(用途)、ControlType(種類)等屬性,以及 Invoke(按下)、Value(值)等控制項模式。螢幕閱讀器會把這些資訊朗讀成「確定訂單 按鈕」,並透過模式進行操作。WinForms 與 WPF 的標準控制項一開始就具備這套機制,因此開發者的主要工作是不要讓 Name 空白、讓功能能用鍵盤操作,以及為自訂控制項實作這些資訊。
- 既有的 WinForms 應用程式,第一步該從哪裡下手?
- 最快的作法,是先對目標畫面執行 Accessibility Insights for Windows 的 FastPass,盤點出 Name 空白的控制項與 Tab 順序的問題。修正則從三件事開始:為只有圖示的按鈕設定 AccessibleName、把 Label 放在輸入欄前一個 Tab 順序以建立關聯、整理 TabIndex 讓它與視覺上的排列一致。接著啟動旁白或 NVDA,不看畫面實際走完一輪業務操作,確認會卡在哪裡。不需要一次修好所有畫面;從真的有人在用的畫面著手,新畫面則用檢查清單做成標準流程,才是務實的作法。
- 要因應高對比(對比佈景主題),該做些什麼?
- 基本原則是不要把顏色寫死,並尊重系統顏色。WinForms 可以讓 ForeColor/BackColor 維持預設或改用 SystemColors,以 SystemInformation.HighContrast 判斷狀態,再用 UserPreferenceChanged 事件跟隨切換。WPF 與 WinUI 只要參照 SystemColors 系列的資源,也會自動跟隨佈景主題切換。同時,請停止「只靠顏色」傳達資訊的作法,例如只用紅色表示錯誤,應一併搭配圖示或文字。即使在一般佈景主題下,把 WCAG 的文字對比度 4.5:1 以上當作大致的參考值,對照明條件不佳的現場或年長使用者也會更好閱讀。
- 無障礙因應對 UI 自動測試也有幫助嗎?
- 有幫助。因為 FlaUI 這類 UI 自動測試工具,和螢幕閱讀器建立在同一套 UI Automation 之上。為了無障礙而整理好的 Name、ControlType、控制項模式,測試程式碼可以直接拿來使用;為測試而設計的 AutomationId,則讓元素定位更穩定。反過來說,不會出現在 UIA 樹上的自訂繪製 UI,螢幕閱讀器與測試都看不見。無障礙與自動測試是對同一個基礎的投資,因此只要整備其中一邊,另一邊的成本也會跟著下降。