在文本编辑器中支持 IAccesible 接口以进行插入符号移动的正确解决方案是什么?

我想从头开始实现一个支持 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 方法从 OS 请求插入符号,并且 OS 将 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"插入符号移动的对应文本");返回 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 将处理此调用并将 WM_GETOBJECT 消息发送到相应的窗口,具体取决于提供给 AccessibleObjectFromEvent() 的处理程序(应该是事件中包含的处理程序).

当您收到插入符号的 WM_GETOBJECT 时,您应该返回相应的 IAccessible 接口,该接口将报告正确的 accRole 和 accLocation.p>

如果您没有收到正确的 WM_GETOBJECT 消息,可能是因为您没有触发正确的事件.

您可以使用 Accessible Event Watcher 来检查是否发送了正确的事件:http://msdn.microsoft.com/en-us/library/windows/desktop/dd317979%28v=vs.85%29.aspx

请参阅 MSDN 上的 Active Accessibility Servers 开发人员指南:http://msdn.microsoft.com/en-us/library/windows/desktop/dd318053%28v=vs.85%29.aspx

编辑

此外,如果您使用 Riched20.dll 提供的标准插入符号(在 Rich Edit 作为实例中),文档规定与其他 UI 元素不同,它没有关联的窗口句柄.

I want to implement a text editor from scratch which supports IAccessible interface. I am using MFC and Win32 API.

When the caret position change in the standard text editors like Notepad, the corresponding letter, word or line to the caret movement is pronounced by client tools like Narrator, JAWS or etc. I don't know how to implement this feature. I search the internet and read the MSDN documentation.

I read in http://msdn.microsoft.com/en-us/library/dd317978.aspx and http://msdn.microsoft.com/en-us/library/dd373892.aspx that client asks for caret by AccessibleObjectFromWindow method from OS, and OS send WM_GETOBJECT to the application. WM_GETOBJECT messages received in the corresponding window callback function, but hWnd for caret movement event is NULL. I checked the thread message queue, but WM_GETOBJECT didn't receive at all in the thread message queue.

One method that has worked somewhat, but not the correct solution is to call

NotifyWinEvent( EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CLIENT, CHILDID_SELF )

when the caret move by user. And when client ask for the changed name, I return the corresponding text related to the caret movement.

HRESULT  CMyEditor::get_accName(VARIANT varChild, BSTR *pszName)
{
   *pszName = SysAllocString( L"CORESPONDING TEXT TO THE CARET MOVEMENT" );
   return S_OK;
}

解决方案

The client would use the SetWinEventHook() function to track the following events of the caret :

  • EVENT_OBJECT_CREATE
  • EVENT_OBJECT_DESTROY
  • EVENT_OBJECT_SHOW
  • EVENT_OBJECT_HIDE
  • EVENT_OBJECT_LOCATIONCHANGE
  • EVENT_OBJECT_FOCUS

If you use a custom control, you need to use NotifyWinEvent() to fire those events yourself, especially EVENT_OBJECT_LOCATIONCHANGE which should trigger the narration.

When the client handle thoses events, it should access the IAccessible interface of the object he's tracking using AccessibleObjectFromEvent().

As you say, Microsoft Active Accessibility would handle this call and send an WM_GETOBJECT message to the corresponding window depending on the handler given to AccessibleObjectFromEvent() (which should be the handler contained in the event).

When you receive the WM_GETOBJECT for the caret you should return the corresponding IAccessible interface which would report the proper accRole and accLocation.

If you're not receiving the right WM_GETOBJECT message it may be because you're not triggering the right events.

You can use the Accessible Event Watcher to check if the right events are sent : http://msdn.microsoft.com/en-us/library/windows/desktop/dd317979%28v=vs.85%29.aspx

See the Developer's Guide for Active Accessibility Servers on MSDN : http://msdn.microsoft.com/en-us/library/windows/desktop/dd318053%28v=vs.85%29.aspx

Edit

Also, if you're using the standard caret provided by Riched20.dll (in a Rich Edit as instance), the documentation stipulate that unlike other UI elements, it does not have an associated window handle.

相关文章