我想从头开始实现一个支持IAccessible接口的文本编辑器。我正在使用MFC和Win32 API。
当插入符号在记事本等标准文本编辑器中的位置发生变化时,插入符号移动对应的字母、单词或行将由叙述者、JAWS等客户端工具读出。我不知道如何实现这个功能。我上网搜索并阅读了MSDN文档。
我在http://msdn.microsoft.com/en-us/library/dd317978.aspx和http://msdn.microsoft.com/en-us/library/dd373892.aspx中读到客户端通过操作系统的AccessibleObjectFromWindow方法请求插入符号,操作系统将WM_GETOBJECT发送到应用程序。在相应的窗口回调函数中接收到WM_GETOBJECT消息,但是插入符号移动事件的hWnd为NULL。我检查了线程消息队列,但是WM_GETOBJECT在线程消息队列中根本没有收到。
有一种方法在一定程度上起了作用,但不是正确的解决方案,那就是调用
NotifyWinEvent( EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CLIENT, CHILDID_SELF )
当插入符号被用户移动时。当客户端要求更改名称时,我返回与插入符号移动相关的相应文本。
HRESULT CMyEditor::get_accName(VARIANT varChild, BSTR *pszName)
{
*pszName = SysAllocString( L"CORESPONDING TEXT TO THE CARET MOVEMENT" );
return S_OK;
}
客户端将使用SetWinEventHook()函数来跟踪插入符号的以下事件:
- EVENT_OBJECT_CREATE
- EVENT_OBJECT_DESTROY
- EVENT_OBJECT_SHOW
- EVENT_OBJECT_HIDE
- EVENT_OBJECT_LOCATIONCHANGE
- EVENT_OBJECT_FOCUS
如果你使用自定义控件,你需要使用NotifyWinEvent()来触发这些事件,特别是EVENT_OBJECT_LOCATIONCHANGE,它应该触发叙述。
当客户端处理这些事件时,应该使用AccessibleObjectFromEvent()访问他正在跟踪的对象的IAccessible接口。
正如你所说的,Microsoft Active Accessibility将处理这个调用,并根据给AccessibleObjectFromEvent()的处理程序(应该是事件中包含的处理程序)向相应的窗口发送一个WM_GETOBJECT消息。
当你收到插入符号的WM_GETOBJECT时,你应该返回相应的IAccessible接口,该接口将报告适当的accRole和accLocation。
如果你没有收到正确的WM_GETOBJECT消息,这可能是因为你没有触发正确的事件。
你可以使用Accessible Event Watcher来检查是否发送了正确的事件:http://msdn.microsoft.com/en-us/library/windows/desktop/dd317979%28v=vs.85%29.aspx
请参阅MSDN上活动辅助服务器的开发人员指南:http://msdn.microsoft.com/en-us/library/windows/desktop/dd318053%28v=vs.85%29.aspx
编辑
此外,如果您使用的是由richhed20 .dll提供的标准插入符号(在Rich Edit作为实例中),文档规定与其他UI元素不同,它没有关联的窗口句柄。