建立更易理解的動態註釋使用者介面 (轉)

worldblog發表於2007-12-27
建立更易理解的動態註釋使用者介面 (轉)[@more@]Rob Sinclair 和 Brendan McKeon
Corporation
2000年9月

摘要: :作為 Microsoft Active Accessibility 2.0 系列的第一篇文章,本文論述了動態註釋 (DA),一種使開發人員提高介面可用性的新技術。

目錄

  • #1">簡介


簡介

前面的文章介紹了作為 Microsoft Active Accessibility 1.0 的一部分的 IAccessible 介面,並說明了 oleacc.dll 為標準(USER 和 ComCtl)提供了該介面的預設實現。這些文章使開發人員在使用自己繪製的和自定義控制元件時避免破壞預設實現。有關詳細資訊,請參閱 (英文)(另在 MSDN News 的 2000 年 5/6 月刊) 和 (英文)(另在 MSDN News 的 2000 年 7/8 月刊)。

本文是討論 Active Accessibility 2.0 及其新功能系列文章的第一篇。作為這些功能之一的動態註釋 (DA) 與前面文章中討論的技術相比,為自定義輔助功能資訊提供了更好的靈活性並明顯降低了開發成本。



什麼是動態註釋

Active Accessibility oleacc.dll 建立代表標準 Microsoft ? 控制元件實現 IAccessible 的。由於這些代理使用標準 Windows 訊息和控制元件專用 收集每個控制元件的資訊,因此沒有直接的機制自定義這些代理透過 IAccessible 提供的資訊。

動態註釋允許開發人員將提示和其他有用資訊傳遞給 OLEACC 來自定義其提供的資訊。該功能本身將降低支援 Active Accessibility 的成本,使開發人員大大改進使用者介面的輔助功能。



動態註釋的替代方法

還有其他方法可以為介面元素提供自定義 IAccessible 支援,在某些場合它們是正確的解決方案。實際上,在引入註釋之前,這些技術是開發人員的唯一選擇。

第一種替代方法是實現整個 IAccessible 介面。自定義控制元件或不同使用者介面元素通常需要該方法,但是開發和測試成本明顯太高,因此除非真正必要否則應該避免採用。如果目標是更改單個屬性,則成本難以判斷。

第二種方法是使用子類和封裝技術修改指定屬性的資訊。這是動態註釋要替代的技術。要使用子類和封裝過載單個屬性,開發人員必須:

  • 使 IAccessible 物件的 HWND 成為子類。

  • 擷取 WM_GET 獲得正確 lParam/OBJID 值。

  • 將 WM_GETOBJECT 透過 CallWndProc() 傳遞給基類。如果返回 0,則 CreateStdAccessibleObject;否則呼叫 LresultFromObject 來獲得控制元件本身的 IAccessible

  • 建立封裝類,該類實現 IAccessible 並封裝了上一步返回的 IAccessible。除需要過載的之外,該封裝類將所有方法和屬性均傳遞給原始 IAccessible。這包括編寫傳遞 IAccessible 所有 21 種屬性和方法的程式碼,無論實際過載多少。

  • 過載方法和屬性必須只處理所需的子 ID,而將所有其他內容傳遞給原始 IAccessible

  • 如果且僅在原始物件支援的情況下,封裝還必須傳遞 IEnumVARIANTIOleWindow 介面。

  • 必須仔細確保正確處理引用計算,特別是如果支援其它介面的話。

  • 必須仔細正確處理 IDispatch,特別是 ITypeLib::Invoke(),它必須隨指向封裝介面的介面指標一起呼叫,而不是指向原始 IAccessible 介面的指標。

如前所見,這包括相當的工作量,即使只有一個或兩個屬性需要過載。結果程式碼的大部分用於子類和封裝,只有一小部分結果程式碼實際真正提供過載資訊的任務。



為使用者介面新增註釋

Active Accessibility 2.0 中支援三種動態註釋:直接註釋數值對映註釋回撥註釋。每種型別都有它的優點,因此首先要理解哪一種方法適用於指定場合。

註釋介面

在繼續之前,熟悉註釋所涉及的三種主要介面非常重要。由於篇幅所限,我們只對每一種進行高層次的說明。有關詳細資訊,包括每個介面方法的討論,可在 Active Accessibility SDK 中找到。

IAccPropServices 介面。這是由單個類 CLSID_AccPropServices 實現的主要註釋介面,該類位於 oleacc.dll 中。該介面包含註釋訪問元素的方法(請參閱表 1)。

表 1. IAccPropServices 介面方法

SetPropValue() 需要透過一個 VARIANT 變數傳遞 IAccessiblentity 和註釋值。 SetPropServer() 用於回撥註釋。 Clerops() 闡述屬性的註釋值,但是這通常不需要,因為註釋服務在註釋元素銷燬時自動清除並釋放該資訊。 SetHwndProp()

SetHwndPropStr()

SetHwndPropServer()

這些方法提供 HWND 專用註釋。 SetHmenuProp()

SetHmenuPropStr()

SetHmenuPropServer()

這些方法提供 HMENU 專用註釋。

IAccIdentity 介面。IAccessible 物件實現並內部用於進入註釋的密匙。所有希望支援動態註釋的物件必須支援該介面。

IAccPropServer 介面。由在回撥註釋中使用的回撥物件實現。

直接註釋

動態註釋的最簡單形式稱作直接註釋。這種註釋最適用於註釋屬性不依賴於控制元件狀態的訪問元素,因此不需要由數值對映註釋回撥註釋提供的附加支援。

要使用直接註釋為訪問元素進行註釋:

  • 獲得指向要註釋的訪問元素的 IAccessible 介面指標。

  • IAccIdentity 介面的 QI,並呼叫 GetIdentityString() 獲得訪問元素的標識字串。

  • 同時建立 AccPropServices 物件。

  • 呼叫 IAccPropServices::SetPropValue,傳遞標識字串,代表要過載的屬性的 GUID,一個包含新屬性值的 VARIANT 變數。

如果不對訪問元素的標識呼叫 SetPropValue,開發人員可以呼叫 SetHwndPropXSetHmenuPropX 方法並提供訪問元素的 HWND/HMENU、物件 ID 和子 ID。這不需要 IAccIdentity 的 QI,呼叫 GetIdentityString 並在 VARIANT 中包裝字串值。

下列屬性可使用直接註釋進行註釋,數值必須為指定型別:

PROPID_ACC_DEFAULTACTION (VT_BSTR) PROPID_ACC_DESCRIPTION (VT_BSTR) PROPID_ACC_HELP (VT_BSTR) PROPID_ACC_KEYBOARDSHORTCUT (VT_BSTR) PROPID_ACC_NAME (VT_BSTR) PROPID_ACC_ROLE (VT_I4) PROPID_ACC_STATE (VT_I4) PROPID_ACC_VALUE (VT_BSTR)

示例 1:設定對話方塊中圖示的 Description 屬性。

#include ... BOOL CALLBACK DialogProc( HMENU Hmenu, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch( uMsg ) { case WM_INITDIALOG: { IAccPropServices * pAccPropS= NULL; HRESULT hr = CoCreateInstance( CLSID_AccPropServices, NULL, CLSCTX_SERVER, IID_IAccPropServices, (void **) & pAccPropSvc ); if( hr == S_OK && pAccPropSvc ) { HMENU HmenuIcon = GetDlgItem( Hmenu, IDC_ICON1); pAccPropSvc->SetHmenuPropStr( HandleToLong(HmenuIcon), OBJID_CLIENT, 0, PROPID_ACC_DESCRIPTION, L"Picture of a thermometer"); pAccPropSvc->Release(); } ... } ... } ... }


數值對映註釋

除了直接註釋 IAccessible 屬性外,經常需要將控制元件專用數值或轉換為使用者可理解的字串。一個示例就是顯示屬性,設定選項卡上的螢幕解析度遊標。儘管每個遊標位置對應於不同的解析度(例如,640 x 480,1024 x 768),但是控制元件並不知道這種對應關係,因此不能將該資訊傳遞給 Active Accessibility。只有使用該控制元件的開發人員才能提供這種關係。

幸運的是,利用 Active Accessibility 2.0 的數值對映註釋,該任務極為簡單。要使用這種註釋,開發人員定義從遊標位置到顯示解析度的對映並將其傳遞給註釋服務。Active Accessibility 將控制元件內部值對映到應該顯示的屬性字串。

支援的對映

由於需要控制元件專用知識來支援對映,因此只有有限數量的控制元件和屬性支援數值對映註釋。

遊標數值對映:PROPID_ACC_VALUEMAP
由 LEACC 遊標(也稱為軌跡條)代理所支援,該屬性包含從內部遊標位置到人類可讀字串的對映。如果當前遊標值存在於數值對映中,將顯示對應的字串,替換預設的百分比字串(例如,"50")。

這在遊標用於從有限的離散選項中選擇一個選項的場合很有用。

ListView 和 TreeView 數值對映:PROPID_ACC_ROLEMAP, PROPID_ACC_STATEMAP

由 OLEACC ListView 和 TreeView 代理所支援,這些對映提供從狀態圖象索引到角色和狀態值的對映。

某些 ListViews 和 TreeViews 使用外觀如核取方塊和單選按鈕的狀態圖象來實現列表或核取方塊和單選選項樹。這些對映使這些狀態圖象對映到相應的角色(典型情況為 ROLE_SYSTEM_RADIOBUTTON 或 ROLE_SYSTEM_CHECKBOX)和附加狀態位(典型情況為 STATE_SYSTEM_CHECKED)。

註釋狀態值與 OLEACC(例如焦點和可見性)使用位 OR 運算子 (|) 計算出的狀態位相結合。

對映可以使用 TreeView 或 ListView 項的圖象索引、狀態圖象索引或覆蓋圖象索引作為關鍵字,並分別以 0、1 或 2 等索引關鍵字表示。

註釋對映格式

註釋對映包含一系列以分隔字元分隔的欄位

  • 大寫字母 'A':表示使用了該特殊編碼方案。未來的編碼方案可能支援附加字首。

  • 分隔字元:典型情況使用分號 (':'),但是這可以是除空 (NUL) 或空格以外的任何字元。由於該字元將用於分隔欄位的分隔符,因此不能用作對映值的一部分。

  • 表示使用哪個關鍵字的值:對於 TreeViewListView 角色和狀態對映,該關鍵字可以為表示各個圖象索引、狀態圖象索引或覆蓋圖象索引的 0、1 或 2。對於遊標或其他沒有提供關鍵字選項的控制元件,該值必須為 0。

  • 分隔符

  • 一系列鍵-值對,每對由下列內容組成:
    • 鍵字串:通常為數字,可以為十進位制或十六進位制(以 "0x" 字首開頭)。

    • 分隔符

    • 值字串:這是數值對映中的字串和角色和狀態對映中的數字(可以使用十進位制或十六進位制)。

    • 分隔符

對映字串的示例包括:

A:0:0:Cold:1:Warm:3:Hot:


如果數值對映應用於遊標控制元件,遊標在位置 1 時將顯示 "Warm"。請注意該示例對映中沒有值 2,因此在該位置時將顯示預設值(在遊標中,應該是百分比值 "33")。

A:1:0:34:1:0x2C:


該對映中的初始值 '1' 表示狀態圖象索引(而不是圖象索引或覆蓋圖象索引)將用作關鍵字。當用作 TreeView 的角色對映時,如果該項的狀態圖象索引為 0,則角色將以 ROLE_SYSTEM_LISTITEM(對應於十進位制值 34)顯示。對於狀態圖象索引為 1 的項,其角色將顯示為 ROLE_SYSTEM_CHECKBUTTON(對應於十六進位制值 0x2C)。具有其他狀態圖象索引的 TreeView 項將具有 TreeView 項的預設角色 ROLE_SYSTEM_OUTLINEITEM。

回撥註釋

回撥註釋為 Active Accessibility 2.0 支援的第三種註釋。它允許開發人員註冊回撥物件響應元素註釋屬性客戶請求。該回撥物件必須實現 IAccPropServer 介面並註冊為 Active Accessibility 註冊服務。一旦註冊,它將負責響應所有訪問元素屬性註釋的客戶請求。

要使用回撥註釋註釋物件屬性:

  • 獲得指向要註釋的訪問元素的 IAccessible 介面指標。

  • IAccIdentity 介面的 QI,並呼叫 GetIdentityString() 獲得訪問元素的標識字串。

  • 同時建立 AccPropServices 物件。

  • 建立實現 IAccPropServer 的 物件。

  • 呼叫 IAccPropServices::SetPropServer,傳遞標識字串,表示要過載屬性的 GUID,和指向 IAccPropServer 回撥物件的指標。

  • 當有客戶端請求訪問元素的註釋屬性時,將呼叫回撥物件提供正確的值。

使用直接註釋時,SetHwndPropServerSetHmenuPropServer 方法可用於指定 HWND/HMENU、物件 ID 和子 ID,而不是檢索標識字串並用其呼叫 SetPropServer。在容器物件上使用 SetPropServerSetHwndPropServerSetHmenuPropServer 時,開發人員還可以指定註釋應該應用於該容器的所有子元素。

下列屬性只能使用回撥註釋進行註釋,返回值通常為 VT_DISPATCH 變數中的 IAccessible

PROPID_ACC_FOCUS

PROPID_ACC_ION

PROPID_ACC_PARENT

PROPID_ACC_NAV_UP

PROPID_ACC_NAV_DOWN

PROPID_ACC_NAV_LEFT

PROPID_ACC_NAV_RIGHT

PROPID_ACC_NAV_PREV

PROPID_ACC_NAV_NEXT

PROPID_ACC_NAV_FIRSTCHILD

PROPID_ACC_NAV_LASTCHILD

示例 2:根據 ListView 項的需求提供自定義幫助字串

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-995868/,如需轉載,請註明出處,否則將追究法律責任。

相關文章