I’m often asked about the relationship among Normal (same as Visible), Unavailable, and Offscreen, and Invisible AA States. Here’s my best guess at an explanation.

What the docs say

Starting with the MSAA Docs on Object State Constants, the following terms are defined as follows:

  • STATE_SYSTEM_NORMAL - Indicates that the object does not have another state assigned to it.
  • STATE_SYSTEM_INVISIBLE - The object is programmatically hidden. For example, menu itmes are programmatically hidden until a user activates the menu. Because objects with this state are not available to users, client applications should not communicate information about the object to users. However, if client applications find an object with this state, they should check to see if STATE_SYSTEM_OFFSCREEN is also set. If this second state is defined, then clients can communicate the information about the object to users. For example, a list box can have both STATE_SYSTEM_INVISIBLE and STATE_SYSTEM_OFFSCREEN set. In this case, the client application can communicate all items in the list to users.
  • STATE_SYSTEM_UNAVAILABLE – The object is unavailable.
  • STATE_SYSTEM_OFFSCREEN - The object is clipped, or scrolled out of view, but not programmatically hidden. If the user makes the viewport larger, more of the object will be visible on the computer screen.

Simple explanations for each term

Normal just implies that the control is visible and available. If no state bits are set by the server developer, the out parameter for the IAccessible::get_accState is 0. When the client calls GetStateText for a 0 out parameter, Normal is returned. Obviously, Normal is #defined as 0.

Unavailable means that the control is either unavailable or disabled. For example, the Start -> Run dialog s OK button is unavailable when the combo box is empty. Although I can visually see the button, it is grayed-out and disabled, such that I cannot press the button (or perform the default action).

Offscreen occurs when the object is either normal or unavailable, but it has been scrolled off the screen. Increase the screen resolution or window size would cause the object to come into view.

An Invisible object is programmatically hidden, implying that I cannot see it on the screen.

Although these explanations seem simple enough on their own, combinations of such states are much more interesting…

Possible combinations

Normal cannot be and’ed with any other state by definition.

Offscreen and Unavailable: The control is unavailable, but is scrolled off the screen. In the previous example, suppose the Run dialog were resizeable. If I were to resize the dialog such that the unavailable OK button were offscreen, I would expect this button to have both Offscreen and Unavailable states set.

Invisible and Unavailable: In my opinion, a control would never have these two bits set at the same time. Invisible seems to have a higher precedence than unavailable. If a control were invisible, it isn t on the screen. An unavailable control must be on the screen to be grayed-out.

Having said that, a member of my team today gave me an interesting scenario where this could be true. Suppose a control were unavailable and the user performed some action that caused it to disappear. If the user were to revert this action (suppose unchecking a checkbox), the control would reappear in an unavailable state. He concluded that both bits should be set. I kinda disagree with this, considering a control cannot be invisible and grayed-out at the same time. However, I hope that the client would check for the invisible bit before checking for any unavailable or offscreen bits, which leads me to the last combination…

Invisible and Offscreen: The definitions from the MSAA docs, as referenced above, state that

However, if client applications find an object with this state, they should check to see if STATE_SYSTEM_OFFSCREEN is also set. If this second state is defined, then clients can communicate the information about the object to users. For example, a list box can have both STATE_SYSTEM_INVISIBLE and STATE_SYSTEM_OFFSCREEN set. In this case, the client application can communicate all items in the list to users.

Offscreen means the control is programmatically accessible, but invisible means the control is not programmatically accessible. Seems like there’s a paradox here.

I’ve found an interesting issue in the Windows Explorer -> View -> Folders tree view. The child tree view item of a collapsed parent item (suppose the item has been expanded and collapsed at least once to generate the AA object) has the Invisible and Offscreen bits set. However, so does any tree view item (child or parent) that is offscreen. In my opinion, it seems that clients need to check for the offscreen bit whenever invisible is set to determine if the object is really invisible or just offscreen in cases such as this one.

Hope this helps!