views:

25

answers:

2

Hi,

I'm trying to detect if a screen reader is attached to my application so that I can improve the experience for blind and low vision users. I'm using this win32 api (http://msdn.microsoft.com/en-us/library/ms724947%28VS.85%29.aspx), and specifying SPI_GETSCREENREADER as the uiAction. Call looks something like this:

int iAction = 70; // SPI_GETSCREENREADER constant;
int iParam = 0;
int iUpdate = 0;
bool result = false;
bool bReturn = SystemParametersInfo(iAction, iParam, &result, iUpdate);

If JAWS is running, or for that matter the magnification utility, this API reports that a screen reader is attached. However, if I only have the built in screen reader running (MS Narrator), this API reports that no screen reader is attached.

Is this really happening? Did the folks over at Microsoft really decide not to report the built in screen reader as a screen reader?

+1  A: 

I can’t test the code out but sadly you are probably correct. Narrator is a very basic screen reader that provides almost no useful functionality other than allowing you to see if your main screen reader has crashed. Rumor has it that Microsoft wanted to make it a full featured screen reader when it was originally released but backed off do to possible antitrust issues from companies that were already producing Screen Readers. Note this is what I’ve heard on some of the blindness email lists I used to be on but cannot verify whether there’s any truth to it. If it is true it would explain why Narrator has limped along with no real improvements for as long as I can remember. I wouldn’t worry about Narrator, if a user is using your application they will be using a decent screen reader such as Jaws. I’ve been using screen reading software all my life and have never known anyone to use Narrator as a primary screen reader. If you wish to test with a free screen reader I would recommend NVDA In my experience it isn’t quite as good as jaws but is a quite usable screen reader without the high price tag.

Jared
+1  A: 

If anyone falls into this horrible trap. Narrator sets a mutex when it starts running (this is totally not documented, but it appears to work if you need to detect ms narrator)

wstring m_wstrMutexKey = L"NarratorRunning";

// security attributes are part of windows API for CreateMutex
LPSECURITY_ATTRIBUTES securityAttributes = new _SECURITY_ATTRIBUTES();
securityAttributes->bInheritHandle = false;
securityAttributes->lpSecurityDescriptor = NULL;
securityAttributes->nLength = sizeof(LPSECURITY_ATTRIBUTES);

// initialize values
bool isRunning = false;

// CreateMutex returns a windows application HANDLE
HANDLE m_applicationHandle = CreateMutex(securityAttributes, false, m_wstrMutexKey.c_str());

// This should never happen
if (m_applicationHandle == NULL) {
    isRunning = false;
}
// This condition indicates that narrator is running. 
if (GetLastError() == ERROR_ALREADY_EXISTS) {
    isRunning = true;
}

if (isRunning)
{
    cout<<"Narrator is running.";
} else {
    cout<<"No Mutex found. Narrator is not running.";
}

delete(securityAttributes);
abudker