What is the correct solution to support IAccesible

2019-03-24 17:19发布

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;
}

1条回答
女痞
2楼-- · 2019-03-24 17:22

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.

查看更多
登录 后发表回答