Win32: A screen reader isn't announcing an update to a status string or error string

This article is referenced directly by Microsoft Accessibility Insights for Windows. Microsoft Accessibility Insights for Windows can help spotlight many accessibility issues in UI, and guide you to the relevant UI framework-specific code sample to help you resolve the issue. Learn more about Microsoft Accessibility Insights for Windows.

Problem

My app UI can change to show an important update to status string or error string. A screen reader doesn't announce that string when the update occurs, and so my customers are not made aware of that important information which is now available.

Suggested Fix

Consider making the label associated with the status or error string, a LiveRegion. A LiveRegion is an area of your app's UI where updates to that area should be announced by a screen reader at the time the updates occur. The UI Automation (UIA) property associated with LiveRegions, is LiveSetting.

Code Sample: Setting the label to be a LiveRegion.

// At the top of the C++ file.
#include <initguid.h>
#include "objbase.h"
#include "uiautomation.h"
IAccPropServices* _pAccPropServices = NULL;


// Run when the UI is created.
HRESULT hr = CoCreateInstance(
    CLSID_AccPropServices,
    nullptr,
    CLSCTX_INPROC,
    IID_PPV_ARGS(&_pAccPropServices));
if (SUCCEEDED(hr))
{
    // Set up the status label to be an assertive LiveRegion. The assertive property 
	// is used to request that the screen reader announces the update immediately. 
	// And alternative setting of polite requests that the screen reader completes 
	// any in-progress announcement before announcing the LiveRegion update.

    VARIANT var;
    var.vt = VT_I4;
    var.lVal = Assertive; 

    hr = _pAccPropServices->SetHwndProp(
        GetDlgItem(hDlg, IDC_LABEL_STATUS),
        OBJID_CLIENT,
        CHILDID_SELF,
        LiveSetting_Property_GUID, 
        var);
}


// Run when the text on the label changes. Raise a UIA LiveRegionChanged 
// event so that a screen reader is made aware of a change to the LiveRegion.
// Make sure the updated text is set on the label before making this call.
NotifyWinEvent(
    EVENT_OBJECT_LIVEREGIONCHANGED, 
    GetDlgItem(hDlg, IDC_LABEL_STATUS), 
    OBJID_CLIENT, 
    CHILDID_SELF);


// Run when the UI is destroyed.
if (_pAccPropServices != nullptr)
{
    // We only added the one property to the hwnd.
    MSAAPROPID props[] = { LiveSetting_Property_GUID };
    HRESULT hr = _pAccPropServices->ClearHwndProps(
        GetDlgItem(hDlg, IDC_LABEL_STATUS),
        OBJID_CLIENT,
        CHILDID_SELF,
        props,
        ARRAYSIZE(props));

    _pAccPropServices->Release();
    _pAccPropServices = NULL;
}