IsKeyboardFocusable is true in Inspect Object but

2020-07-06 04:35发布

问题:

I'm learning UI Automation and I found that my "Inspect Object" clone is showing that IsKeyboardFocusable is always false even when it is true, all other information is identical (as you can see from image). Does anyone have any idea why I see this property as false when I retrieve the value?

回答1:

Within the Inspect Object application the latest version of Windows Automation COM API (3.0) is used to display all of these properties. But the default .NET UIAutomation implementation is not based on Windows Automation API 3.0 COM interfaces (it based on previous version of this COM API). Thus some properties is not functioned correctly . For example for Skype's contact list the AutomationElement.IsKeyboardFocusableProperty property says that getting values for this property is not supported at all. You can check this using the following code snippet:

object isKeyboardFocusable = listItem.GetCurrentPropertyValue(AutomationElement.IsKeyboardFocusableProperty, true);
if(isKeyboardFocusable == AutomationElement.NotSupported) {
    // we will always goes here
}

Right now, I do not know ways to avoid this behavior using the current .Net UIAutomation implementation.

The good news are that there is alternative UI Automation implementation in .NET that makes it possible to use the new Windows Automation API 3.0 COM interfaces, with their improved reliability and performance, while still using the same System.Windows.Automation classes as in earlier versions of UI Automation. This implementation is available as a project on CodePlex: UI Automation COM-to-.NET Adapter

So, tried this alternative implementation today, and with this alternative implementation the IsKeyboardFocusable property returns the same result as the Inspect Objects tool! Moreover now it is possible to use some extended properties which the Inspect Objects displays (e.g. LegacyIAccessible members).



回答2:

The internal implementation of IsKeyboardFocusable uses GetCurrentPropertyValue(property: AutomationElement.IsKeyboardFocusableProperty, ignoreDefaultValue: false) function. In the cases where it fails, it just return false (and in your case it fails). Therefore, I recommend you to use GetCurrentPropertyValue(property: AutomationElement.IsKeyboardFocusableProperty, ignoreDefaultValue: true) instead of IsKeyboardFocusable, so you'll know if it fails.

You can get exactly the same result as Inspect by using winapi. Olecc.dll give you IAccessible interface (There is more detailed description of this interface). An instance of that interface can have children instances, part of them can be focusable and part of them - not. If you create IAccessible from HWnd, you can't be sure that entire control are focusable or not focusable. To be sure, you should create IAccessible from point of screen - it gives you exactly the IAccessible that under that point (You can see on your screenshot, that Inspect uses point on screen - "How found - Mouse move (1120, 470)"). Also if you switch from UIAutomation mode to MSAA in the Inspect, you can see how IAccessible looks like.

But, if it's possible in your case, it is better to use alternative implementation of UIAutomation. It returns correct IsKeyboardFocusable value (unlike standard UIAutomation implementation). I didn't tested this library myself (I tested only IsKeyboardFocusable), but seems like it works fine, and it has the same types and interfaces as the standard implementation. As in the IAccessible case, you should create AutomationElement from a point, not from HWnd.

About your question - I don't know yet, why standard UIAutomation can't return AutomationElement.IsKeyboardFocusableProperty corretly in some cases. I think, it may be a bug.



回答3:

Have you tried this UI Automation spy tool: https://ddeltasolutions.000webhostapp.com/ ? I found cases where IsKeyboardFocusableProperty is true, for example the menu bar of Skype application.