Featured

User Interface Developers: Please Have Mercy on Your Poor Users!

Woman screaming in rage,

This blog post is for any software engineers who are involved in programming or designing a user interface.

If someone performs a user interface action that should result in an instantaneous and clearly visible response they will only wait patiently for that response for a brief period of time.

If after a five second delay they do not see the expected clearly visible response they will perform the user interface action again, perhaps multiple times if the delay continues for another five seconds or so.

If for some reason there is a delay that prevents the expected instantaneous and clearly visible response, please, for the love of whatever deity or great power you follow, DO NOT PERFORM THE RESPONSE MULTIPLE TIMES.

The multiple user interface actions were not in any way a request to perform the response multiple times. They were multiple increasingly desperate attempts to get the response a single time.

For example, if the user is pressing enter on a desktop icon that starts a program that displays a message box before the main function is even called, they will press enter on the desktop icon multiple times if for some reason it takes between five and sixty seconds to start the application when it normally starts in far less than a second.

Trust me. The user has already started screaming at you by the time they have to hit enter on the desktop icon a third time because the message box still has not been displayed in response to the request to start the application that was made fifteen seconds earlier.

If you then start that application one time for each time they pressed the enter key on the desktop icon when your badly broken operating system finally realizes the user is desperately trying to start it the poor user might end up having a stroke because of the rage they are now experiencing!

Another example is opening a menu such as the start menu or an application menu. Normally this is a very quick operation that takes less than a second. So if five seconds after they pressed the key to open the menu the user does not see the menu, they will press the key to open it again. On the rare occasions when something delays the opening of the menu they may have pressed the open menu key four or five times before it is opened.

That does not mean they want the menu to be opened, then closed, then opened, then closed…

The multiple presses of the key to open the menu were multiple increasingly desperate attempts to open the menu once. By the second attempt the poor user is screaming at you. If you do the open menu, close menu, open menu, close menu, … foolishness it is very likely that the poor user might end up have a stroke because of the rage they are now experiencing!

These are problems I experience very often with Microsoft Windows. To be fair I have seen it with Linux and Mac OSX as well, but no where near as often as I see in in Windows.

Fuck you very much Microsoft for the wonderful user experience of Windows and every single Microsoft product I have every used! If I believed in hell I would wish for everyone responsible for these wonderful user experiences to suffer eternal torment in the hottest and most fiery section of hell!

Thank you for listening to me vent. I feel much better now.

Here is a song that expresses my heartfelt feelings towards Microsoft. Enjoy.

… you very much Microsoft
Featured

On the benefits of taking a course over learning by doing.

I am a self taught software engineer. It is something I take a great deal of pride in.

I started learning C programming language back in 1997. If I remember correctly I started by reading Sams Teach Yourself C in 21 Days and perhaps also C Programming Language by Brian W. Kernighan and Dennis M. Ritchie.

Then on January 5, 1999 I got a job working for Henter-Joyce (now Freedom Scientific) as an Associate Software Engineer. My responsibilities included writing code in the JAWS Scripting Language which a proprietary programming language that is used by the JAWS screen reader.

I quickly decided that I was not content with just writing code in the JAWS Scripting Language; I wanted to be able to modify the JAWS internals.

At that time almost all of the JAWS internal code was in the C++ programming language. Therefore I decided to teach myself C++.

To learn C++ I did the following.

  • I bought a copy of Sams Teach Yourself C++ in 21 Days and began reading it.
  • I wrote an application called SysInfo in C++ as a aid to our technical support department. SysInfo would gather information such as Video Card information, OS, memory, and send it to technical support via email. SysInfo was very similar to the current Microsoft System Information Tool.

This plan was so successful that I was promoted to Software Engineer in January 2000. I have used C++ as my primary programming language since then.

I never stopped learning. I have tried to keep up to date with new language standards and new technologies since then. But I always learned by doing. If the task I was working on required that I learn something new I would use Google and Stack Overflow and get the job done.

This has been my preferred method of gaining new knowledge until very recently.

On August 1, 2021 my knowledge of JavaScript was minimal. The last time I needed to use JavaScript as part of my job it took me two weeks to fix a bug that required that I change fewer than 10 lines of code.

Then I realized that there are some serious flaws with a browser extension for Google Chrome and Mozilla Firefox released by my employer that I am currently responsible for maintaining that necessitated a complete rewrite of the extension. I tried to make the necessary changes and found much to my horror that I could not even get started.

I had previously bought a lifetime membership to Eduonix and some courses on Udemy with the vague idea of taking the courses some day. However, I had made very minimal use of these educational resources.

I let my employer know what was going on and I was given permission to spend some time when I would normally be working on taking courses in JavaScript. I then spent every day for the next two weeks learning JavaScript.

In just four hours this Monday I rewrote one quarter of the Browser Extension. There is only one reason I did not finish the project; I was temporarily reassigned to another project.

I am not claiming that my knowledge of JavaScript is anywhere near my knowledge of C++. However, after just two weeks my knowledge of JavaScript is roughly equivalent to my knowledge of C++ back in 2001.

Looking back, I find myself wishing that I had followed a more structured approach to learning C++ back in the halcyon days of yore.

Featured

JAWS Scripting Tip: Optional Parameters

JAWS is a screen reader developed by Freedom Scientific. It includes a scripting language that allows users to customize the behavior of JAWS.

Many programming languages such as C++, C#, and Modern JavaScript support the concept of optional function parameters for which you supply a default value for the parameter. In C++ this might be done as follows.

std::wstring GetFavoriteNumberMessage(int64_t number = 42)
{
    std::wstringstream message;
    message
        << L"Hello. My favorite number is "
        << number
        << L". What is your favorite number?\n";
    return message.str();
}

See source on godbolt.org.

The JAWS scripting language supports optional parameters using the optional keyword, as follows.


string function GetFavoriteNumberMessage(optional int number)
  var string message = FormatString(
    "Hello. My favorite number is %1. What is your favorite number?",
     number)
  return message
endFunction

However, there is no direct method of assigning a default value for the optional parameter. If you were to call the function is as without specifying a value for the number parameter the number will be inserted into the returned message as an empty string. This is most likely not the desired behavior.

When the caller does not specify the value of an optional parameter, it does not resolve to 0 or false within the function; this is a common misconception. Instead the unspecified parameter resolves to nullptr. The misconception that the unspecified parameter resolves to 0 or false is a result of the fact that when nullptr is typecast to an int the result is 0 or false. However, if the unspecified parameter is typecast to a string the result is an empty string. This is why in the above example the number will be inserted into the returned message as an empty string; the number parameter is typecast to a string by the FormatString function. If the unspecified parameter did resolve to 0 or false within the function it would be inserted to the returned message as 0!

This problem can be resolved as follows.

string function GetFavoriteNumberMessage(optional int number)
    if (!DidCallerSpecifyTheValueOfTheParameter(number))
      number = 42
    endIf
    var string message = FormatString(
      "Hello. My favorite number is %1. What is your favorite number?",
      number)
    return message
endFunction

Unfortunately, there is no DidCallerSpecifyTheValueOfTheParameter function in the JAWS scripting language, so do not bother looking it up. However, there is a function that can achieve the same goal.

Behind the scenes all variables in the JAWS scripting language are VARIANTs (yes we are aware that there are modern alternatives that are vastly superior but the JAWS scripting language is very old; it has its roots in the JAWS macro language that was included in JAWS for DOS). One benefit of a VARIANT is it supports the concept of a VARTYPE or variant type. Furthermore, there is a VT_EMPTY variant type. Finally, there is a rarely used GetVariantType built-in script function that “determines the type of a variable”.

Thus, it is possible to assign a default value for an optional parameter as follows.

string function GetFavoriteNumberMessage(optional int number)
    if (GetVariantType(number) == VT_EMPTY)
      number = 42
    endIf
    var string message = FormatString(
      "Hello. My favorite number is %1. What is your favorite number?",
      number)
    return message
endFunction

Note that some people may think this is unnecessary because it is enough to rely on the perceived unspecified parameter resolves to 0 or false behavior. This is wrong for two reasons.

  • As I have already pointed this perceived behavior is not what is actually happening. The unspecified parameter actually resolves to nullptr.
  • In many cases, even if the perceived unspecified parameter resolves to 0 or false behavior may not be what is desired.

Every other programming language that supports the concept of optional parameters; such as C++, C#, and Modern JavaScript ; allows the value of the optional parameters to be explicitly defined. The purpose of the following code block is to add the same capabilities to optional parameters in the JAWS Scripting Language.

if (GetVariantType(number) == VT_EMPTY)
  number = 42
endIf

This is the only way to assign a non nullptr value for an optional parameter in the JAWS Scripting Language. You should consider doing this even for parameters where the default value is 0 or nullptr because explicitly specifying the value of your default parameters rather that making people who read your code guess what the behavior will be is just being polite.

Note that using this technique is absolutely necessary when overriding a built-in script function such as the SayObjectTypeAndText function in your scripts. The default value of the includeContainerName is true, not false. Failure to do this when overriding the SayObjectTypeAndText function will change the behavior of your function from the default resulting in hard to find bugs.

Debugging Tip: How to Set a Breakpoint In a Windows API Function

Introduction

This article is based on an EMail message I sent to the software development team at Vispero on August 26, 2008. I had just spent hours debugging an odd bug in JAWS®. When focus was in a particular window while JAWS was running I heard constant, rapid fire, beeping. I searched the JAWS source code for calls to the Beep and MessageBeep functions and was not able to determine the cause of the bug. I was at a loss. Then I asked the following question, is there a way I can just set breakpoints in the Beep and MessageBeep functions? This article discusses what I found during my quest for an answer to that question.

I am writing this article now because I encountered this issue again today and just spent five hours retracing my steps.

Note: After I wrote this article I learned that things are much easier in Visual Studio 2017 and Visual Studio 2019. In these versions of Visual Studio all that you need to do is open the “New Function Breakpoint” dialog box using the “Debug/New Breakpoint/Function Breakpoint…” menu item and enter the undecorated name of the function in the dialog box. If you are interested in learning how things used to be, follow me down the rabbit hole.

Falling down the rabbit hole

It turns out that it is possible to set a breakpoint in a Windows API function in Visual Studio. I do not know when this functionality was added to Visual Studio but I do know that it was available in Visual Studio 2005. The question is how.

The Set function breakpoints section of the Use breakpoints in the Visual Studio debugger page provides some relevant information; it provides very limited information on setting a breakpoint on a function with a known name. Simply use the “Debug/New Breakpoint/Function Breakpoint…” menu item to open the “New Function Breakpoint” dialog box and type a magical incantation in the “Function Name” edit.

Unfortunately, the information provided here is infuriating since it reveals that the feature is supported but it does not provide enough information to allow you to actually use the feature. In other words, it does not tell you what magical incantation to use.

Use the context operator in native C++.

{function, , [module]} [+]

Example: {MethodA, , App1.dll}+2

The article How Can I Debug Windows API Functions provides more information but it does not explain the context operator. It does reveal how to set a breakpoint in the MessageBeep function.

{,,USER32.DLL}_MessageBeep@4

This page mentions that you need to use the “decorated form of the function name” and suggests that you refer to the Viewing Decorated Names page for more information. The Viewing Decorated Names page in turn refers you to the Use a listing and Using DUMPBIN to View Decorated Names pages. Unfortunately, it turns out that neither of the techniques mentioned on the Viewing Decorated Names page will allow you to determine the decorated name for a function that is exported from a DLL. The DBH tool is supposed to be able to provide this information via the -d command-line option but in my tests using the following command it only provides undecorated names these days (bad Microsoft!).

dbh -s:srv*C:\SymbolCache*http://msdl.microsoft.com/Download/Symbols -d C:\Windows\System32\User32.dll enum *CreateWindowExW*

This command provides the following output.

Symbol Search Path: srv*C:\SymbolCache*http://msdl.microsoft.com/Download/Symbols

 index            address     name
     1            1007760 :   CreateWindowExW

Note that this is not the decorated name of the function since there is no @ character.

Unfortunately, I do not know an easy way to determine the “decorated form of the function name” other than to figure it out yourself using the information provided at Using Win32 calling conventions. Most Windows API function use the __stdcall calling convention. The general syntax for the decorated name of a __stdcall function is as follows.

_[UndecoratedFunctionName]@[SizeOfParametersInBytes]

This provides enough information for you to write the part of the magical incantation that comes after the } character, but what about the beginning of the magical incantation? Based on the example provided for the MessageBeep function one could assume that it should simply be the name of the DLL that implements the Windows API function, but is more information available?

Fortunately, the Context Operator in the Visual Studio Debugger (C++) page does provide a more detailed explanation for the first part of the magical incantation. This page reveals part of the syntax for the Context Operator.

{,,[module]} expression

Of course, this very annoyingly leaves a question unanswered. Why does this text between the { character and the } character start with two commas? What are you leaving out?

I have not been able to find official Microsoft documentation that answers that question yet. However, I do have an answer for you from Breaking on System Functions with the Context Operator. This page reveals that the full syntax of the Context Operator is as follows.

{[function],[source],[module]} expression

In most cases you will not need to worry about [function] and , you will only need to worry about the module and the expression.

Thus, the syntax for the magical incantation you will need to set the breakpoint is as follows.

{,,[module]}_[UndecoratedFunctionName]@[SizeOfParametersInBytes]

Pulling everything together.

To set a breakpoint in any Windows API function, such as the CreateWindowExW function, do the following.

  1. Look up the Windows API function in the Microsoft documentation. In the Requirements section the DLL the function is implemented in is provided; in this case it is User32.dll.
  2. Determine the size of the function parameters in bytes, as follows.
ParameterSize in bits on a 32-bit systemSize in bytes on a 32-bit systemSize in bits on a 64-bit systemSize in bytes on a 64-bit system
DWORD dwExStyle324324
LPCWSTR lpClassName324648
LPCWSTR lpWindowName324648
DWORD dwStyle324324
int X324324
int Y324324
int nWidth324324
int nHeight324324
HWND hWndParent324648
HMENU hMenu324648
HINSTANCE hInstance324648
LPVOID lpParam324648
Totals4868
  1. Fill in the blanks.

If you are debugging a 32-bit application the magical incantation is as follows.

{,,User32.dll}_CreateWindowExW@48

If you are debugging a 64-bit application the magical incantation is as follows.

{,,User32.dll}_CreateWindowExW@68
  1. Enter the appropriate magical incantation in the “Function Name” edit of the “New Function Breakpoint” dialog box and press the OK button.

Note that in order for this to work you will need to set up Visual Studio to use the Microsoft symbol server. To do this select the “Debug/Options…” menu item to open the Debugging section of the “Options” dialog box. Then select “Debugging/Symbols” in the tree view. Next press tab to move focus to the “Symbol file (.pdb) locations” check list box and check the “Microsoft Symbol Servers” item. Then press the OK button.

References

Down the Rabbit Hole (CC BY-SA 2.0) by Valerie Hinojosa

On writing code with debugging in mind

/*************************************************
*                                                *
* .=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-. *
* |                   ______                   | *
* |                .-"      "-.                | *
* |               /            \               | *
* |   _          |              |          _   | *
* |  ( \         |,  .-.  .-.  ,|         / )  | *
* |   > "=._     | )(__/  \__)( |     _.=" <   | *
* |  (_/"=._"=._ |/     /\     \| _.="_.="\_)  | *
* |         "=._"(_     ^^     _)"_.="         | *
* |             "=\__|IIIIII|__/="             | *
* |            _.="| \IIIIII/ |"=._            | *
* |  _     _.="_.="\          /"=._"=._     _  | *
* | ( \_.="_.="     `--------`     "=._"=._/ ) | *
* |  > _.="                            "=._ <  | *
* | (_/                                    \_) | *
* |                                            | *
* '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=' *
*                                                *
*    ABANDON ALL HOPE, ALL YE WHO ENTER HERE     *
*************************************************/
ASCII art image of a skull and crossbones with the text “abandon all hope, all ye who enter here” displayed below the skull and crossbones.

One factor of code quality that does not get enough attention is how easy is it to debug the code. No matter how skilled the team that writes the software, there will be bugs. When these bugs are found some poor soul will need to debug the code to determine the cause of the bug. Unfortunately this can quickly turn into a nightmare because many functions are not debuggable. Sometimes even well designed code is so difficult to debug that it causes the poor soul who has to debug it to abandon all hope.

Non-Debuggable Function

The following function is very simple. At first glance it seems to be a concise and well designed function. However, it is a major contributor to the debugging this application is a nightmare problem.


inline bool CCoolAppDocument::IsValidStartOffset(long nOffset) const
{
    return nOffset >=0 && nOffset < GetLength();
}

You may be wondering, how can this innocent, one-line function cause someone to abandon all hope?

When the function works as expected (meaning it returns the value you expect) it cannot. However, when the function returns false when you think it should return true the nightmare begins. The most critical piece of information that might explain why this function is not returning the expected value, the document length, is hidden away within a function call. As a result, there is no way you can look at parameter and variable values in the debugger watch window and know why the function is behaving in the way that it is.

Debuggable Function

The following function does exactly the same thing but it can be debugged in a microsecond.


inline bool CCoolAppDocument::IsValidStartOffset(long nOffset) const
{
    const auto documentLength = GetLength();
    return (nOffset >=0 && nOffset < documentLength);
}

All you have to do to debug this function is look at the value of the nOffset parameter and the documentLength variable in the watch window and then the reason for the unexpected behavior is immediately obvious.

In the case of today’s nightmare that inspired this article, the problem was that both the nOffset parameter and the documentLength variable happened to be equal to 296.

Additional Comments

I know that some of you are wondering whether I am aware that some debuggers will provide the return value of a function that was just called. The answer is of course I am aware of that. However, as far as I know not all debuggers support this functionality. In addition, this functionality is not as easy to use or as intuitive as the watch variable feature.

To me it just makes sense to make a very small change to make it possible to diagnose problems with the more intuitive and easier to use watch variable feature of the debugger.

Using a select element to change the active stylesheet for a web page.

This article discusses the use of a select element to change the active stylesheet for a web page. It also provides step by step instructions on how to create the select element.

  • Add a link element to the head of your web page. Set the rel attribute to “stylesheet,” the href attribute to the URL of the default stylesheet you wish to use for your web page, and the id attribute to a unique value.

    Code Example:

    <link
      rel="stylesheet"
      href="https://www.w3.org/StyleSheets/Core/Swiss"
      id="W3C-Core-Styles" />
    

  • Add the select element. Set the value attribue of each option element to the URL of the stylesheet and the contents of each option element to the text you wish to be displayed for the combo box.

    Code Example:

    <select id="SeclectW3CCoreStyle">
    <option
      value="https://www.w3.org/StyleSheets/Core/Chocolate">
    Chocolate
    </option>
    <option
      value="https://www.w3.org/StyleSheets/Core/Midnight">
    Midnight
    </option>
    <option
      value="https://www.w3.org/StyleSheets/Core/Modernist">
    Modernist
    </option>
    <option
      value="https://www.w3.org/StyleSheets/Core/Oldstyle">
    Oldstyle
    </option>
    <option
      value="https://www.w3.org/StyleSheets/Core/Steely">
    Steely
    </option>
    <option
      value="https://www.w3.org/StyleSheets/Core/Swiss">
    Swiss
    </option>
    <option
      value="https://www.w3.org/StyleSheets/Core/Traditional">
    Traditional
    </option>
    <option
      value="https://www.w3.org/StyleSheets/Core/Ultramarine">
    Ultramarine
    </option>
    </select>
    

    Typically, I add this select element, along with a lable and the Set Style button, to the footer at the bottom of the page.

  • Add a Set Style button, as follows.

    Code Example:

    <input
      id="SetW3CCoreStyleButton"
      onclick="SetStyle('SeclectW3CCoreStyle', 'W3C-Core-Styles')"
      type="button"
      value="Set Style" />
    

  • Add the following JavaScript code to a script element in your page or to a .js file on your website.

    function isEmptyOrSpaces(str){
      if (str == null){
        return true;
      }
      if (str.length == 0){
        return true;
      }
      if (str.trim() === ''){
        return true;
      }
      return false;
    }
    
    function SetStyle(selectStyleElementId, linkElementId){
      console.log(
        "SetStyle('" + selectStyleElementId
        + "', '" + linkElementId
        + "') called.");
      let seclectStyleElement =  document.getElementById
        selectStyleElementId);
      if (!seclectStyleElement){
        console.log(
          "Could not find the '" + selectStyleElementId
          + "' element.");
        return false;
      }
      let seclectedStyle = seclectStyleElement.value;
      if (isEmptyOrSpaces(seclectedStyle)){
        console.log("Could not get the selected style.");
        return false;
      }
      let linkElement = document.getElementById(linkElementId);
      if (!linkElement){
        console.log(
          "Could not find the '" + linkElementId
          + "' element.");
        return false;
      }
      linkElement.setAttribute("href", seclectedStyle);
      return true;
    }
    

This example is fully functional. It does lack one key feature, the ability to store the selected style in a cookie. The article Store and Retrieve Cookies demonstrates the use of the localStorage.setItem and localStorage.getItem functions.

Modify the SetStyle function by adding the folloing line just above the ‘return true;’ line at the bottom of the function.


window.localStorage.setItem(
  "SeclectedStyle", seclectedStyle);

Note that the localStorage object is only supported on modern web browsers. That said, the Local storage with Window.localStorage page provides JavaScript code to emulate the feature for older browsers.

The next step is to set the style and the selected item in the select element when the web page loads. To acomplish this you need to add the following function.


function SetStyleFromCookie(selectStyleElementId, linkElementId){
  console.log(
    "SetStyleFromCookie('" + selectStyleElementId + "', '" + linkElementId + "') called.");
  let seclectedStyle = window.localStorage.getItem(
    "SeclectedStyle");
  if (isEmptyOrSpaces(seclectedStyle)){
    console.log(
      "Failed to get the value of the 'SeclectedStyle' cookie. Using the default value.");
    seclectedStyle = 'https://www.w3.org/StyleSheets/Core/Swiss';
  }
  let linkElement = document.getElementById(linkElementId);
  if (!linkElement){
    console.log("Could not find the '" + linkElementId + "' element.");
    return false;
  }
  linkElement.setAttribute("href", seclectedStyle);
  let seclectStyleElement =  document.getElementById(selectStyleElementId);
  if (!seclectStyleElement){
    console.log("Could not find the '" + selectStyleElementId + "' element.");
    return false;
  }
  seclectStyleElement.value = seclectedStyle;
  return true;
}

Finally, use the following code to call the SetStyleFromCookie function when the web page is loaded.


window.addEventListener('DOMContentLoaded', (event) => {
  SetStyleFromCookie('SeclectW3CCoreStyle', 'W3C-Core-Styles');
});

References

To see this code in action, go to Using a select element to change the active stylesheet for a web page.

Providing Accessibility Information in a .NET Windows Forms application

Windows Forms applications provide two mechanisms for providing accessibility information.

In many cases the required accessibility information can be provided using the following properties of the Control Class in the System.Windows.Forms Namespace: the Control.AccessibleDefaultActionDescription Property, the Control.AccessibleDescription Property, the Control.AccessibleName Property, and the Control.AccessibleRole Property. This feature is almost enough to meet WCAG Success Criterion 4.1.2: Name, Role, Value. WCAG Success Criterion 4.1.2: Name, Role, Value requires that state information be provided as well. Unfortunately, there is not a property in the Control Class for state information.

In many cases, the built in Windows Forms support is sufficient and therefore there is no need to specifically provide state information.

If you do need to provide state information, it will take a bit more effort. In this case, you will need to use the AccessibleObject Class and the Control.CreateAccessibilityInstance Method.

Using the Accessible* Properties of the Control Class

The following code demonstrates the use of the Control.AccessibleDescription Property and the Control.AccessibleName Property of the Control Class.

In this case, the checkbox object provides the state. However, since an image is used instead of text, it does not provide the name. Therefore the Control.AccessibleDescription Property and the Control.AccessibleName Property of the Control Class are used. In addition, these properties suffice to meet WCAG Success Criterion 4.1.2: Name, Role, Value.

References

Using Direct Annotation in C++

Sometimes you will encounter a situation in which the existing accessibility support for an user interface element is almost good enough and you need to just make small changes to the existing support. For example, perhaps you just need to override the Name or Role properties. In these cases, fully implementing the IAccessible interface as described in Implementing a Microsoft Active Accessibility (MSAA) Server Using the Windows API and C++ may seem like a great deal of effort to achieve these improvements.

Fortunately, starting with Windows 7 there is an easier alternative, the Direct Annotation feature of the Dynamic Annotation API. The Dynamic Annotation API is extension to Microsoft Active Accessibility that makes it possible to customize existing IAccessible support without using subclassing or wrapping techniques. Direct Annotation is one of several features provided by the Dynamic Annotation API; it is the simplest of the features provided.

Direct Annotation makes it possible to customize the following properties.

Since Name, Role, Value, and State are included in the list of properties supported by the Direct Annotation feature, this feature is sufficient to meet WCAG Success Criterion 4.1.2: Name, Role, Value.

Implementation Details

The first step to using the Direct Annotation feature of the Dynamic Annotation API is to create an [IAccPropServices][] object using either the CoCreateInstance function or CoCreateInstanceEx function. Then you can use either the IAccPropServices::SetHwndProp method or the IAccPropServices::SetHwndPropStr method.

The following sample from Using Direct Annotation demonstrates the technique.



More complete examples can be found in the following locations.

Note that using the IAccPropServices::SetHwndProp method or the IAccPropServices::SetHwndPropStr method will not send WinEvents. It is your responsibility to send appropriate events by calling the NotifyWinEvent function after the IAccPropServices::SetHwndProp method or the IAccPropServices::SetHwndPropStr method has been called.

For example, if you use IAccPropServices::SetHwndPropStr method to set the Name property of an element, send an EVENT_OBJECT_NAMECHANGE event for that object after SetHwndPropStr returns.

The CWndWithCustomizedAccessibleInfo class and DirectAnnotation class both make the necessary calls to the NotifyWinEvent function for you.

Implementing a Microsoft Active Accessibility (MSAA) Server Using the Windows API and C++

The oldest and simplest of the Accessibility APIs used in Microsoft Windows is Microsoft Active Accessibility or MSAA. This article provides a brief introduction on how to implement a MSAA Server using the Windows API and the C++ programming language.

The IAccessible interface

The heart of MSAA is the IAccessible interface. This interface exposes methods and properties that allow an accessibility server to make a user interface element and its children accessible to accessibility client applications. The methods and properties of the IAccessible interface allow a Windows API application to meet WCAG Success Criterion 4.1.2: Name, Role, Value, which requires that an accessibility client be able to programmatically determine the Name, Role, Value, and States of all user interface components (including but not limited to: form elements, links and components generated by scripts).

The following table provides information the methods of the IAccessible interface that are used to expose each of these properties.

Property Method
Name IAccessible::get_accName
Role IAccessible::get_accRole
State IAccessible::get_accState
Value IAccessible::get_accValue

See the IAccessible interface page for a complete list of the members of the interface and a detailed description of each method. The Content of Descriptive Properties page provides information on the expected value of these properties.

The Name, Role, and State properties are required for all user interface components that can gain focus. The Value property may be required for some user interface components but not for others. More information on which members of the IAccessible interface should be implemented for a given user interface component can be found in the Choosing Which Properties to Support page.

How an accessibility client obtains an IAccessible object

An accessibility client use one of the following functions to obtain an IAccessible object.

See the Getting an Accessible Object Interface Pointer page for more information on these functions.

What happens when an accessibility client requests an IAccessible object?

When an accessibility client requests an IAccessible object using the AccessibleObjectFromEvent, AccessibleObjectFromPoint, and AccessibleObjectFromWindow functions Microsoft Active Accessibility sends the WM_GETOBJECT message to the appropriate window procedure within the appropriate server application with the lParam parameter set to OBJID_CLIENT. Your Microsoft Active Accessibility (MSAA) server needs to handle this message.

Handling the WM_GETOBJECT Message

When your Microsoft Active Accessibility (MSAA) Server receives the WM_GETOBJECT message it should return the value obtained by passing the IAccessible interface of the object to the LresultFromObject function as follows.



The above code is from the Windows API Accessibility Server sample application.

For more information on handling the WM_GETOBJECT message see the following.

Events

Implementing the IAccessible interface is just one part of the puzzle. You also need to notify fire event notifications. This is done using the NotifyWinEvent function. See Event Constants, System-Level and Object-Level Events, and What Are WinEvents? for more information.

Additional Resources

Additional information can be found in the following locations.

Using Character or String Constants in a Template function

Using Character or String Constants in a Template function

Ben Key:

October 1, 2013; November 10, 2018

 


This article provides several techniques that may be used when creating template functions in which the character type is a template parameter and you must use character or string constants. It also provides the source code for several template functions and macros that may be used to implement one of the proposed solutions.

Problem Description

There are various data types that may be used to represent characters in C++. The most common of these are char and wchar_t. It often is necessary to write code that is capable of handling either type of character.

One alternative is to simply implement the function once for each character type that needs to be supported. There are obvious problems with this approach. The first problem is that this approach causes unnecessary code duplication. It also opens up the possibility that the different implementations of the function will diverge over time as changes are made in one implementation, for example in order to fix bugs, but not in the other implementations of the function.

Consider the following example.

The CommandLineToArgVector function parses a command line string such as that which might be returned by the GetCommandLine function. This function depends on a number of character constants: specifically NULCHAR (’\0’), SPACECHAR (’ ‘), TABCHAR (’), DQUOTECHAR (’”‘), and SLASHCHAR (’\’).

In order to support characters of both char and wchar_t it is necessary to implement the function twice as follows.


inline size_t CommandLineToArgVector(
    const char* commandLine,
    std::vector<std::string>& arg_vector)
{
    arg_vector.clear();
    /* Code omitted. */
    return static_cast<size_t>(arg_vector.size());
}

inline size_t CommandLineToArgVector(
    const wchar_t* commandLine,
    std::vector<std::wstring>& arg_vector)
{
    arg_vector.clear();
    /* Code omitted. */
    return static_cast<size_t>(arg_vector.size());
}

The obvious solution is to implement this as a template function that accepts the character type as a template parameter as follows.


template<typename CharType>
size_t CommandLineToArgVector(
    const CharType* commandLine,
    std::vector< std::basic_string<CharType> >& arg_vector)
{
    arg_vector.clear();
    /* Code omitted. */
    return static_cast<size_t>(arg_vector.size());
}

The only thing that prevents us from doing that is the existence of the character constants. How do you represent the constants so that they are can be of either data type?

Possible Solutions

As is often the case, there are many possible solutions to this problem. This article discusses several of them.

Widen

One possible solution is to make use of std::ctype::widen as follows.


template <typename CharType>
CharType widenChar(
    const char ch, const std::locale& loc = std::locale())
{
    const auto& cType = std::use_facet<std::ctype<CharType>>(loc);
    return cType.widen(ch);
}

This same technique can be extended for use with string literals as follows.


template<typename CharType>
std::basic_string<CharType> widenString(
    const char* str, const std::locale& loc = std::locale())
{
    std::basic_string<CharType> ret;
    if (str == nullptr || str[0] == 0)
    {
        return ret;
    }
    const auto& cType = std::use_facet<std::ctype<CharType>>(loc);
    auto srcLen = std::strlen(str);
    auto bufferSize = srcLen + 32;
    auto tmpPtr = yekneb::make_unique<CharType[]>(bufferSize);
    auto tmp = tmpPtr.get();
    cType.widen(str, str + srcLen, tmp);
    ret = tmp;
    return ret;
}

Then in the template function you can use the character constants in a character type neutral way as follows.


const CharType NULCHAR = widenChar<CharType>('\0');
const CharType SPACECHAR = widenChar<CharType>(' ');
const CharType TABCHAR =  widenChar<CharType>('\t');
const CharType DQUOTECHAR = widenChar<CharType>('\"');
const CharType SLASHCHAR =  widenChar<CharType>('\\');

The problem is that this requires a multibyte to wide character conversion for the wchar_t case. This may not be much of an issue for functions that are not used very often and are not performance critical. However the cost of the multibyte to wide character conversion would not be acceptable in performance critical situations.

The question is how to solve this problem without these performance issues.

Algorithm Traits

Another option is to create an algorithm traits class that includes functions that return each of the constants as follows.


template <typename CharType>
struct CommandLineToArgVector_Traits
{
    CharType NULCHAR();
    CharType SPACECHAR();
    CharType TABCHAR();
    CharType DQUOTECHAR();
    CharType SLASHCHAR();
    CharType* STRING();
};

template<>
struct CommandLineToArgVector_Traits<char>
{
    char NULCHAR()
    {
        return '\0';
    }
    char SPACECHAR()
    {
        return ' ';
    }
    char TABCHAR()
    {
        return '\t';
    }
    char DQUOTECHAR()
    {
        return '\"';
    }
    char SLASHCHAR()
    {
        return '\\';
    }
    char* STRING()
    {
        return "String";
    }
};

template<>
struct CommandLineToArgVector_Traits<wchar_t>
{
    wchar_t NULCHAR()
    {
        return L'\0';
    }
    wchar_t SPACECHAR()
    {
        return L' ';
    }
    wchar_t TABCHAR()
    {
        return L'\t';
    }
    wchar_t DQUOTECHAR()
    {
        return L'\"';
    }
    wchar_t SLASHCHAR()
    {
        return L'\\';
    }
    wchar_t* STRING()
    {
        return L"String";
    }
};

As you can see, it is a simple matter to incorporate string constants in the algorithm traits structure.

The algorithm traits structure can then be used as follows in your template function.


CommandLineToArgVector_Traits<CharType> traits;
const CharType NULCHAR = traits.NULCHAR();
const CharType SPACECHAR = traits.SPACECHAR();
const CharType TABCHAR =  traits.TABCHAR();
const CharType DQUOTECHAR = traits.DQUOTECHAR();
const CharType SLASHCHAR =  traits.SLASHCHAR();
const CharType* STRING = traits.STRING();

This solution does not have the same performance issues that the widenChar solution does but these performance gains come at the cost of a significant increase in the complexity of the code. In addition, there is now a need to maintain two implementations of the Algorithm Traits structure, which means that we are right back where we started from, though admittedly maintaining two implementations of the Algorithm Traits structure is a lot less work than maintaining two implementations of the algorithm.

It would be ideal to develop a solution that has the convenience and simplicity of the widenChar solution without the performance issues. The question is how.

Preprocessor and Template Magic

Fortunately it is possible to solve this problem using some preprocessor and template magic. I found this solution in the Stack Overflow article How to express a string literal within a template parameterized by the type of the characters used to represent the literal.

The solution is as follows.


template<typename CharType>
CharType CharConstantOfType(const char c, const wchar_t w);

template<>
char CharConstantOfType<char>(const char c, const wchar_t /*w*/)
{
    return c;
}
template<>
wchar_t CharConstantOfType<wchar_t>(const char /*c*/, const wchar_t w)
{
    return w;
}

template<typename CharType>
const CharType* StringConstantOfType(const char* c, const wchar_t* w);

template<>
const char* StringConstantOfType<char>(const char* c, const wchar_t* /*w*/)
{
    return c;
}
template<>
const wchar_t* StringConstantOfType<wchar_t>(const char* /*c*/, const wchar_t* w)
{
    return w;
}

#define _TOWSTRING(x) L##x
#define TOWSTRING(x) _TOWSTRING(x)
#define CHAR_CONSTANT(TYPE, STRING) CharConstantOfType<TYPE>(STRING, TOWSTRING(STRING))
#define STRING_CONSTANT(TYPE, STRING) StringConstantOfType<TYPE>(STRING, TOWSTRING(STRING))

Then in the template function you can use the character constants in a character type neutral way as follows.


const CharType NULCHAR = CHAR_CONSTANT(CharType, '\0');
const CharType SPACECHAR = CHAR_CONSTANT(CharType, ' ');
const CharType TABCHAR =  CHAR_CONSTANT(CharType, '\t');
const CharType DQUOTECHAR = CHAR_CONSTANT(CharType, '\"');
const CharType SLASHCHAR =  CHAR_CONSTANT(CharType, '\\');
const CharType* STRING = STRING_CONSTANT(CharType, "String");

Abracadabra. The problem is solved without any code duplication or performance issues.

Article Source Code

The source code for this article can be found on SullivanAndKey.com. The relevant files may be found at the following locations.

  • widen.h: Contains the source of widenChar and widenString.
  • ConstantOfType.h: Contains the source of CharConstantOfType and StringConstantOfType.
  • CmdLineToArgv.h: The header file for the CommandLineToArgVector function.
  • CmdLineToArgv.cpp: The source code for the CommandLineToArgVector function.