Skip to content

No longer access MS Office ribbons, status bars and context menus via UIA for Office <= 2013#10981

Merged
feerrenrut merged 7 commits into
nvaccess:masterfrom
lukaszgo1:I9252
May 1, 2020
Merged

No longer access MS Office ribbons, status bars and context menus via UIA for Office <= 2013#10981
feerrenrut merged 7 commits into
nvaccess:masterfrom
lukaszgo1:I9252

Conversation

@lukaszgo1

@lukaszgo1 lukaszgo1 commented Apr 11, 2020

Copy link
Copy Markdown
Contributor

Link to issue number:

Fixes #9252
Fixes #4207
Improves #7067

Summary of the issue:

Accessing MS Office ribbons via UIA especially for Older versions of Office has certain disadvantages:

Description of how this pull request fixes the issue:

IAccessible is used for these controls for Office <=2013. To do that it has been necessary to workaround some IAccessible specific issues:

In both cases AccValue contains non localized description of the control which made it possible to workaround them.

Testing performed:

In Office 365, Office 2010 and Office 2013:

  • Tabbed through the ribbon both expanded and collapsed ensured that focus changes are reported and that for Office 2010 and 2013 it is accessed via IAccessible whereas for 365 via UIA.
  • Ensured that context menu items are properly reported for both Office versions.
  • Ensured that status bar is recognized as such when pressing appropriate NVDA command.

Additionally for Office 2010 and 2013:

  • Made sure that ribbon and status bar is reported when focus moves to them for the first time.
  • Navigated between ribbon sections using CTRL+arrows ensured that sections are consistently reported regardless of the type of their first control.

Known issues with pull request:

  • It would be beneficial not to use UIA even for Office 2016 to have consistent reporting of sections there. At present this cannot be done because when ribbons are collabsed NVDA fails to report focus changes when accessed via IAccessible. This however seems to be a bug in NVDA rather than these controls not firing events - when I've added additional logging to event handler they are received but ignored later on. I haven't investigated further I believe this should be done in a follow up PR.

Change log entry:

Section: Bug fixes

  • In Office 2013 and older:
    • Ribbons are announced when focus moves to them for the first time.
    • Context menu items are once again reported properly.
    • Ribbon sections are consistently announced when navigating with Control+arrows.

@LeonarddeR

Copy link
Copy Markdown
Collaborator

@dkager would you be able to test with 2013?

@lukaszgo1

Copy link
Copy Markdown
Contributor Author

I've finally been able to got hold of the machine with 2013 remotely,, and can confirm that these fixes works there. I've updated the description accordingly. @michaelDCurran @feerrenrut I believe this would benefit from longer cycle of being in master - I've tested it of course but with changes like these there are often some edge cases.

Comment thread source/_UIAHandler.py Outdated
# FIX ME!
# Quick testing shows that prorer focus event are emitted yet they are ignored by NVDA.
if(
appModule.productName.startswith("Microsoft Office")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why isn't this code in the appmodule as per appModule.isBadUIAWindow above?

Also note, earlier lines indicate that appModule may be None

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because all Office applications share the common product name but does not share single executable. Doing this at the appModule level would require separate module for at least:

  • Word
  • Excel
  • Outlook
  • Powerpoint
  • Visio
  • Project
  • Access

and there is no "guarantee that all Office apps are covered whereas using product name is safe.

Comment thread source/_UIAHandler.py Outdated
# and not being able to report ribbon sections when they starts with an edit field (#7067)
# The last problem also exiists for Office 2016, however using IAccessible for collabsed ribbons
# causes NVDA not to report focus changes.
# FIX ME!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't leave 'Fix me' in. Please clarify this comment to specify the things fixed, and the remaining problems. Remaining problems should should have an issue number for more in depth discussion.

You can clarify this by:

  • Avoid writting "this". Above, 'this class' is ambiguous, I assume it relates to the window class?
  • Start lines with 'fixes:' or 'remaining issue:'
'NetUIHWND is used for some controls in MS office.
IAccessible should be used in place of UIA for NetUIHWND classes in office versions before 2016:
- Fixes: 'lack of focus reporting (#4207)'
- Fixes: 'strange reporting of context menu items (#9252)'
- Fixes: 'not being able to report ribbon sections when they start with an edit field (#7067)'
- Remaining issue #XYZ: In office 2016, similar to #7067, ribbon sections that start with an edit fields are not reported. When using IAccessible for collapsed ribbons stops focus changes being reported. Testing shows that focus events are emitted but ignored.

Comment thread source/NVDAObjects/IAccessible/msOffice.py Outdated
Comment thread source/NVDAObjects/IAccessible/msOffice.py Outdated
@AppVeyorBot

Copy link
Copy Markdown

See test results for failed build of commit 7cfc6ccda0

@lukaszgo1

Copy link
Copy Markdown
Contributor Author

@feerrenrut I've hopefully clarified the commends and addressed your other concerns. This is ready for another look.

Comment thread source/_UIAHandler.py Outdated
Comment on lines +541 to +559
if windowClass == "NetUIHWND":
# NetUIHWND is used for various controls in MS Office.
# IAccessible should be used for NetUIHWND in versions older than 2016
# Fixes: lack of focus reporting (#4207),
# Fixes: strange reporting of context menu items(#9252),
# fixes: not being able to report ribbon sections when they starts with an edit field (#7067)
# Note that #7067 is not fixed for Office 2016 and never.
# Using IAccessible for NetUIHWND controls causes focus changes not to be reported
# when the ribbon is collapsed.
# Testing shows that these controls emits proper events but they are ignored by NVDA.
if(
appModule.productName.startswith(("Microsoft Office", "Microsoft Outlook"))
and int(appModule.productVersion.split(".")[0]) < 16
):
parentHwnd = winUser.getAncestor(hwnd, winUser.GA_PARENT)
while parentHwnd:
if winUser.getClassName(parentHwnd) in ("Net UI Tool Window", "MsoCommandBar",):
return False
parentHwnd = winUser.getAncestor(parentHwnd, winUser.GA_PARENT)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

App module might be None. The following suggestion makes this check when matching the window class name, and names the checks for isOfficeApp and isBefore2016Version

		if windowClass == "NetUIHWND" and appModule:
			# NetUIHWND is used for various controls in MS Office.
			# IAccessible should be used for NetUIHWND in versions older than 2016
			# Fixes: lack of focus reporting (#4207),
			# Fixes: strange reporting of context menu items(#9252),
			# fixes: not being able to report ribbon sections when they starts with an edit  field (#7067)
			# Note that #7067 is not fixed for Office 2016 and newer.
			# Using IAccessible for NetUIHWND controls causes focus changes not to be reported
			# when the ribbon is collapsed.
			# Testing shows that these controls emits proper events but they are ignored by NVDA.
			isOfficeApp = appModule.productName.startswith(("Microsoft Office", "Microsoft Outlook"))
			isBefore2016Version =  int(appModule.productVersion.split(".")[0]) < 16
			if isOfficeApp and isBefore2016Version:
				parentHwnd = winUser.getAncestor(hwnd, winUser.GA_PARENT)
				while parentHwnd:
					if winUser.getClassName(parentHwnd) in ("Net UI Tool Window", "MsoCommandBar",):
						return False
					parentHwnd = winUser.getAncestor(parentHwnd, winUser.GA_PARENT)

@lukaszgo1

Copy link
Copy Markdown
Contributor Author

@feerrenrut Done.

@feerrenrut feerrenrut left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @lukaszgo1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

5 participants