View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002947 | MMW v4 | Other | public | 2007-03-27 09:53 | 2008-09-22 19:16 |
Reporter | jiri | Assigned To | |||
Priority | urgent | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | 3.0 | ||||
Fixed in Version | 3.1 | ||||
Summary | 0002947: Make MM accessible to blind users | ||||
Description | Since the lists and trees we use in MM are based on non-standard component, these parts aren't prepared to be used by screen-readers or some other special applications. This should be resolved if possible. | ||||
Tags | No tags attached. | ||||
Fixed in build | 1186 | ||||
|
Marco Zehe [marco.zehe at googlemail.com] gave us a detailed description of how to implement this using his code. Here is a complete description from him: Hi Jiri, here are the steps: 1. In the interface uses clause, change the first line this way: uses Windows, {$ifndef COMPILER_10_UP} MSAAIntf, // MSAA support for Delphi up to 2005 {$else} oleacc, // MSAA support in Delphi 2006 or higher {$endif COMPILE_10_UP} Messages, SysUtils, Classes, Graphics, Controls, Forms, ImgList, ActiveX, StdCtrls, Menus, Printers, 2. In TBaseVirtualTree, in the private section, right above the "// common events" line, add: // MSAA support FAccessible: IAccessible; // The IAccessible interface to the window itself. FAccessibleItem: IAccessible; // The IAccessible to the item that currently has focus. FAccessibleName: string; // The name the window is given for screen readers. 3. Further down, below the procedure WMGetDlgCode, insert: procedure WMGetObject(var Message: TMessage); message WM_GETOBJECT; 4. Further down, in the public section, above the Property CheckImages, insert: property Accessible: IAccessible read FAccessible write FAccessible; property AccessibleItem: IAccessible read FAccessibleItem write FAccessibleItem; property AccessibleName: string read FAccessibleName write FAccessibleName; 5. further down, in the class TVirtualSTringTree, in the published section, add: property AccessibleName; 6. In the implementation section, add the unit VTAccessibilityFactory to the uses clause, right after StdActns. 7. Above the TBaseVirtualTree.WMHScroll method, insert the method implementation: procedure TBaseVirtualTree.WMGetObject(var Message: TMessage); begin // Create the IAccessibles for the tree view and tree view items, if necessary. if FAccessible = nil then FAccessible := GetAccessibilityFactory.CreateIAccessible(Self); if FAccessibleItem = nil then FAccessibleItem := GetAccessibilityFactory.CreateIAccessible(Self); if Cardinal(Message.LParam) = OBJID_CLIENT then if Assigned(Accessible) then Message.Result := LresultFromObject(IID_IAccessible, Message.WParam, FAccessible) else Message.Result := 0; end; //---------------------------------------------------------------------------------------------------------------------- 8. Now, we need to add a few NotifyWinEvent calls to some of the Doxxx-Functions for certain events. They are always inserted at the very bottom of the method, right above the closing end;: a) TBaseVirtualTree.DoChecked, NotifyWinEvent(EVENT_OBJECT_STATECHANGE, Handle, OBJID_CLIENT, CHILDID_SELF); b) TBaseVirtualTre.DoCollapsed: NotifyWinEvent(EVENT_OBJECT_STATECHANGE, Handle, OBJID_CLIENT, CHILDID_SELF); c) TBaseVirtualTree.DoExpanded: NotifyWinEvent(EVENT_OBJECT_STATECHANGE, Handle, OBJID_CLIENT, CHILDID_SELF); d) TBaseVirtualTree.DoFocusChange: NotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, Handle, OBJID_CLIENT, CHILDID_SELF); NotifyWinEvent(EVENT_OBJECT_NAMECHANGE, Handle, OBJID_CLIENT, CHILDID_SELF); NotifyWinEvent(EVENT_OBJECT_VALUECHANGE, Handle, OBJID_CLIENT, CHILDID_SELF); NotifyWinEvent(EVENT_OBJECT_STATECHANGE, Handle, OBJID_CLIENT, CHILDID_SELF); NotifyWinEvent(EVENT_OBJECT_SELECTION, Handle, OBJID_CLIENT, CHILDID_SELF); NotifyWinEvent(EVENT_OBJECT_FOCUS, Handle, OBJID_CLIENT, CHILDID_SELF); e) TBaseVirtualTree.MainColumnChanged: NotifyWinEvent(EVENT_OBJECT_NAMECHANGE, Handle, OBJID_CLIENT, CHILDID_SELF); f) TCustomVirtualStringTree.DoNewText: NotifyWinEvent(EVENT_OBJECT_NAMECHANGE, Handle, OBJID_CLIENT, CHILDID_SELF); NotifyWinEvent(EVENT_OBJECT_FOCUS, Handle, OBJID_CLIENT, CHILDID_SELF); 9. Optionally, you can add the following to VirtualTreesReg.pas, to make the AccessibleName property show up in Object Inspector: Change line: 'Hint*', 'On*Hint*', 'On*Help*']); to ['AccessibleName', 'Hint*', 'On*Hint*', 'On*Help*']); That's it! I'm attaching three units: 1. VTAccessibilityFactory.pas - is used by VirtualTrees.pas after the above changes and manages all IAccessibles and provides the right one for each instance. 2. VTAccessibility.pas - Provides IAccessibles for the tree itself (where AccessibleName is given to tell the screen reader what tree this is), AccessibleItem for single nodes, AccessibleMultiColumnItem for multi-column nodes. This should cover most usage scenarios out of the box already. If I understood you correctly, the only place you actually use images is for denoting whether an item in the main navigation pane is an album, artist etc. Since the nodes are already categorized usually, this is a piece of information not essential. So the first step should be to integrate the above changes and the VTAccessibility unit in the project and see how it goes. 3. I also include the MSAAIntf.pas if you're using a version of Delphi earlier than 2006. I tested it with Delphi 5, and it works great. I hope this makes it clear what would be needed! Let me know how it goes! Regards, Marco |
|
The files mentioned by Marco are uploaded to FTP. Additionally, some more things should be done when we implement this: A. AccessibleName property has been added to give each tree a meaningful name. We should fill them in, preferrably reusing some existing strings whenever possible (or use some common strings in some cases, like 'list' or 'tree'). These should be also localized, but .po tools should take care of this automatically. B. ImageIndexes is exactly what you guessed: Within any particular tree, provide me with the index numbers and their meanings, and I'll adjust a case statement. This would be in the unit to include in your project. I.e. we probably provide Marco with a list of icons in the main tree, for other VT instances it shouldn't be necessary. |
|
Btw, I assigned this issue Urgent priority, but I don't consider it _that_ urgent, in case some problems will arise, just let me know and we can discuss deferring this issue. |
|
Will be in 1186 |