最近的工作是给开源的DUILib支持Accessibility, 一些经验记录并分享下。

 
微软的Accessibility其实Windows平台上一个挺重要的东西, 尽管在国内不受重视,但是如果你的软件要出口欧美,Accessibility是必须的, 不然国外正规单位(政府,学校,大公司等)是禁止采购的。
 
如果我们的软件用的是Winodws标准控件,一般Accessibility是系统默认内置支持的 (当然这也不是一定的,据我测试系统的Date Time Picker控件是不支持MSAA的)。因为系统标准控件在展现和行为上的一些限制以及自绘的复杂性,越来越多的软件使用DirectUI技术,关于使用DirectUI的理由,更多参见<<如何让窗口控件半透明>>和<<软件换肤的原理>>.
 
国内最有名的的DirectUI界面库当然是开源的DUILib (尽管这套库已停止更新), 实际上我以前在自己业余写点东西时, 也参考过它, 具体参见<<开源一套DirectUI界面库>>。对于开源的DUILib, 个人觉得它有挺多优点, 也有挺多缺点, 我们重点说缺点, 因为这是我们改进的方向。
 
1。扩展性差
    DUILib只实现了一些基本的控件,好的DirectUI库可以通过基本控件组合来轻松实现复杂控件,而要达到这个效果, 很多时候我们需要拦截子控件的消息, 尽管DUILib提供了delegate机制来子类化子控件, 但是这样消息拦来拦去实在太不方便了,很多时候自己都转晕了。个人觉的这里我们可以引入WPF的隧道和冒泡机制, 这个东西对DirectUI界面库实在太重要了。
 
2。不支持Layered窗口
要完美支持Layered窗口,意味着所有的Render全都要支持Alpha通道, DUILib使用GDI, 如果没有特殊处理,意味着没法完美支持Layered窗口, 我这篇也谈到过这个问题<<如何基于纯GDI实现alpha通道的矢量和文字绘制>>。
 
3。大数据时性能不行
DUILib很多时候只适合做些简单的界面,本身控件基类很庞大,数据量方面对于几百条数据还行,但是对于成千上万条数据就吃不消了,这时我们需要引入WPF的虚表机制。
 
 

4。不支持图文排版

尽管DUILib支持简单的HTML排版, 但是毕竟太简单,如果我们要在QQ那样的聊天窗口里引入就吃不消了, 另外它渲染HTML那个代码我是吃不消看的。
 
5. 基本不支持Accessibility
 
6。其他
接口和属性定义太随意, 采用导出类的方式也不好扩充, 渲染方面最好能在GDI/GDI+/Direct2D方面进行切换,最好将核心控件和扩展控件分离开, 编辑器也太简陋。
 
今天我们重点说Accessibility,一个界面库要完整支持Accessibility, 要包括太多东西 (具体可以参见控制面板里的"轻松访问中心"),我估计只有微软自己做的到(比如WPF),这也是很多人推荐系统标准控件而排斥DirectUI的理由。我们说的Accessibility很多时候只是简化版, 下面我们说重点的几条。
 
1。键盘支持
键盘支持简单来说就是即使我没有鼠标, 我也能通过通过键盘完成所有操作。它主要包括键盘导航和控件的键盘支持。键盘导航主要是指我可以通过一些热键(如F6)可以在不同窗口(Panel)之间进行焦点切换, 我可以通过Tab/Shift+Tab在窗口内不同控件之间进行焦点导航。控件的键盘支持也是很多国内DirectUI库所缺失的,比如:
Dialog: Enter执行默认, ESC退出并关闭
Button:空格执行
CheckBox:空格取反
Radio:空格取反,上下左右键切换选中项
TabCtrl:焦点选中时上下左右切换, 焦点没选中时Ctrl+Tab/Ctrl+Tab+Shift切换Tab页
Menu:上下左右导航,Enter执行, ESC取消关闭, 具体参见<<DirectUI中模态对话框和菜单的原理>>
....
总之,DUILib在键盘支持这块已经做了不少工作,但是还有挺多事要做,每个控件都要完整支持键盘是个很精细的活。
 
2。读屏软件和自动化测试的支持。 
ScreenReader(读屏器)主要是给盲人用的, 程序可以实时的把获得焦点的控件和系统发生的事件播报出来, 很多读屏软件都需要收费,还好Win7之后系统已自带读屏软件(控制面板\轻松访问\轻松访问中心\启动讲述人)。自动化测试时也需要工具能够理解我们界面中包含的元素类型和位置, 以及模拟操作事件等。
 
DirectUI要支持读屏和自动化测试一般有2种方式, MSAA和UI Automation。 MSAA是比较古老的方式,主要就是实现IAccessible接口;UI Automation是微软特意给WPF新增加的。MSAA出来的时候还是Win95, 因为历史原因有一些限制, 比如不支持Text控件,没法描述复杂控件等, 所以微软后来引入了UI Automation, 具体参见<<Windows GUI自动化测试技术的比较和展望>>。 
 
MSAA最大的优点是稳定, 所以我在DUILib里采用MSAA来实现ScreenReader的支持。简单说下几个关键点:
(a) 每个控件啊实现IAccessible接口的Proxy对象尽量独立,里面保存一个控件指针的引用,这样即使控件销毁了,Proxy对象可以依旧存在(系统仍可能会访问这个对象)。
(b) 按照控件的层次体系,实现每种控件的Proxy类(实现IAccessible接口)。
(c) WM_GETOBJECT请求OBJID_CLIENT时返回根节点的Proxy对象, 焦点变化时通知触发事件NotifyWinEvent(EVENT_OBJECT_FOCUS, m_hWndPaint, (LPARAM)m_pFocus, CHILDID_SELF), 窗口收到WM_GETOBJECT消息时根据ObjectID(这里是控件指针)找到该控件, 然后返回该控件的Proxy。 (这是关键,这个问题郁闷了我好久的...) 
 
3。高对比(high contrast)的支持
高对比,主要是给色盲用,这个东西一般自绘程序都不会支持, 即使你是用标准控件,因为一般会用自己漂亮的图片和色彩来表现界面, 高对比实现的关键点是你在画每个元素时要通过GetSystemColor来获取颜色。据我测绘除了微软自己的程序, 其他越是漂亮的软件越是不支持高对比(即使如QQ和Chrome)。
 
4。高DPI的支持
随着Surface Pro和高分辨率设备的流行,程序对高DPI的支持正变得越来越重要, 具体参见<<关于Windows高DPI的一些简单总结>>。传统的基于标准控件的程序要支持高DPI是在太难了,所以微软才有了DWM虚拟化。但是DirectUI对高DPI的支持有着天然的优势, 我们完全可以在界面库这层让程序完美支持高DPI, 界面的渲染主要是文字,矢量和图片, 文字和矢量完全可以通过无损缩放绘画实现,图像可以通过适当缩放和换图来实现。
 
总结下,尽管我N次吐槽基于GDI的DirectUI界面库会随着XP的淡出而逐渐失去市场, 但是实际工作中还是要经常和GDI打交道,外面招聘单位还是有不少Windows客户端的开发岗位。 在这"移动互联和"Web前端"横行的"大数据"时代,很多同事开始向移动App和大数据转型, 尽管这几年PC客户端的开发人员是只出不进, 但是只要Windows存在一天,我们的工作就还是有价值的..

http://www.cnblogs.com/weiym/p/4098579.html

如何给开源的DUILib支持Accessibility(论述了DUILib的六个缺点,很精彩)的更多相关文章

  1. 如何给开源的DUILib支持Accessibility

    最近的工作是给开源的DUILib支持Accessibility, 一些经验记录并分享下. 微软的Accessibility其实Windows平台上一个挺重要的东西, 尽管在国内不受重视,但是如果你的软 ...

  2. 利用cocoapods管理开源项目,支持 pod install安装整个流程记录(github公有库)

    利用cocoapods管理开源项目,支持 pod install安装整个流程记录(github公有库),完成预期的任务,大致有下面几步: 1.代码提交到github平台 2.创建.podspec 3. ...

  3. 重磅发布:阿里开源 OpenJDK 长期支持版本 Alibaba Dragonwell

    原文地址:https://yq.aliyun.com/articles/694603 本文作者:阿里开源  本文来自云栖社区合作伙伴"阿里系统软件技术",了解相关信息可以关注&qu ...

  4. ipython, 一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数

    一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数. 若用的是fish s ...

  5. 微软开源PowerShell并支持Linux和OS X

    [微软在开源的道路上加速度了] 从一开始的各种对抗,各种通吃,到现在开始做服务,包罗万象.果然,换了主力,大有不同. 微软今天还宣布开源其.NET框架,令.NET Core能在Linux和OS X上运 ...

  6. 【原创开源】网络版二代双通道示波器开源发布,支持电脑,手机和Pad等各种OS平台访问

    前言感谢大家的支持,提前奉上今年的国庆福利. 一代示波器发布于3年前,去年年底的时候发布了二代示波器,软件性能已经比较强劲,但依然有值得升级改进的地方,经过今年这半年多努力,在二代示波器的基础上再推出 ...

  7. CAT 3.0 开源发布,支持多语言客户端及多项性能提升

    项目背景 CAT(Central Application Tracking),是美团点评基于 Java 开发的一套开源的分布式实时监控系统.美团点评基础架构部希望在基础存储.高性能通信.大规模在线访问 ...

  8. 微软开源 PowerShell 并支持 Linux 和 OS X

    微软近日宣布开源 PowerShell,开始支持 Linux 和 OSX.PowerShell 是面向 Windows 和 Windows Server 的自动化平台和可扩展脚本语言,可帮助用户简化系 ...

  9. EasyDarwin开源流媒体服务器支持basic基本认证和digest摘要自定义认证

    本文转自EasyDarwin开源团队成员的博客:http://blog.csdn.net/ss00_2012/article/details/52330838 在前面<EasyDarwin拉流支 ...

随机推荐

  1. 【转】三星8552 手机提示升级系统 完成后重启 开机画面一直停留在三星的LOGO 一闪一闪 怎么办

    原文网址:http://ask.zol.com.cn/q/309501.html 楼主你好,手机出现这种情况的话,可以先将电池取下来重新安装,如果不能的话,可以在关机状态下按住电源键+音量下键之后进入 ...

  2. POJ3581---Sequence 后缀树组

    题意:n个数字组成的序列,第一个数字最大,,把序列分成3部分,每个部分分别翻转,输出翻转后字典序最小的序列.. 后缀数组变一下,,先求出 第一个分割的位置,,然后再求一次后缀数组,,求出第二个位置.. ...

  3. hdu2444The Accomodation of Students

    思路: 二分图判断+最大匹配模板 二分图判断的方法很好想,没有离散的基础凭空给你个图让你判断也很容易想到染色法,简单的介绍下就是用queue来做,标记一个点为x则他所有的邻点都为x',然后递归的执行下 ...

  4. java——Arrays.asList()方法

    Arrays.asList() 是将数组作为列表 问题来源于: public class Test { public static void main(String[] args) { int[] a ...

  5. 【KMP】Period

    KMP算法 Next[]函数深入理解,Next[]当前字符前匹配字符数,串长n-Next[i]=串内循环子串的长度p. 本题求子循环串内循环节数. Problem Description For ea ...

  6. Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1) 错误 解决方案(android-ndk)

    在android里做ndk编程的时候,碰到个随机性错误 错误信息如下: 05-06 15:59:44.411: A/libc(3347): Fatal signal 11 (SIGSEGV) at 0 ...

  7. cocos2dx--cocos2dx3.1.1执行报无法解析的外部符号

    使用cocos2dx3.1.1和VS2012 新建了一个名为test的工程.放在D:\cocos2dx\cocos2d-x-3.1.1\projects下 编译通过,没问题 用cocostudio的场 ...

  8. rhel6.4 using centos source

    rhel 默认的 yum 依赖于 rhn,要注册收费才能 update,改用 centos 的源: rpm -e yum* --nodeps rpm -qa | grep yum | xargs rp ...

  9. gulp前端自动化构建工具新手入门篇

    很久没有更新博文了. 经过了一次年前吐血的赶项目,终于在年后回血了.趁着有空,新学到了一个前端自动化构建工具-gulp. 现在我们通过这3个问题来学习一下: 1.什么是gulp? 2.为什么要用gul ...

  10. DataTable循环删除行

    1.如果只是想删除datatable中的一行,可以用DataRow的delete,但是必须要删除后让DataTable知道,所以就要用 到.AcceptChanges()方法,原因是这种删除只是标识性 ...