Server Annotation Sample

The following is an example of server annotation. Follow instructions in comments marked with /* TODO */.

//
//  Skeleton code for class which implements IAccPropServer
//

class CMyAccPropServer: public IAccPropServer
{
    ULONG               m_Ref;
    IAccPropServices *  m_pAccPropSvc;

public:

    AccServerBase( IAccPropServices * pAccPropSvc )
        : m_Ref( 1 ),
          m_pAccPropSvc( pAccPropSvc )
    {
        m_pAccPropSvc->AddRef();
    }

    ~AccServerBase()
    {
        m_pAccPropSvc->Release();
    }

    
    /* TODO: Addref/Release/QI go here...
     */

    HRESULT STDMETHODCALLTYPE GetPropValue ( 
        const BYTE *    pIDString,
        DWORD           dwIDStringLen,
        MSAAPROPID      idProp,
        VARIANT *       pvarValue,
        BOOL *          pfGotProp )
    {
        // Clear out params, in case we return early...
        pvarValue->vt = VT_EMPTY;
        *pfGotProp = FALSE;

        
        /*  TODO: if you need to access internal data structs, you should
         *  verify that they still exist here. If they no longer exist,
         *  return CO_E_DISCONNECTED.
         */

        // Figure out which child this request is for...
        HWND  hwnd;
        DWORD idObject;
        DWORD idChild;

        if( S_OK != m_pAccPropSvc->DecomposeHwndIdentityString( pIDString, dwIDStringLen,
                    & hwnd, & idObject, & idChild ) )
        {
            // problem decomposing identity string - return early...
            return S_OK;
        }

        
        /*  TODO: you need to determine which child ids you 
         *   want to handle   *  properties for. Change this 
         *   if or extend it into an if/else/if
         *   to handle each id you need.
         *  To handle all the children of an object, but not 
         *  the parent object itself, 
         *  use "if (idChild != CHILDID_SELF )" as the 
         *  condition.
         */

        if( idChild == CHILDID_SELF )
        {
            
            /*  TODO: change or extend this if(...) for each 
             *  property you are overriding.
             *  The constants for the properties are (from 
             *  oleacc.h):
             *    PROPID_ACC_NAME
             *    PROPID_ACC_VALUE
             *    PROPID_ACC_DESCRIPTION
             *    PROPID_ACC_ROLE
             *    PROPID_ACC_STATE
             *    PROPID_ACC_HELP
             *    PROPID_ACC_KEYBOARDSHORTCUT
             *    PROPID_ACC_DEFAULTACTION
             *    PROPID_ACC_FOCUS
             *    PROPID_ACC_SELECTION
             *    PROPID_ACC_PARENT
             *    PROPID_ACC_NAV_UP
             *    PROPID_ACC_NAV_DOWN
             *    PROPID_ACC_NAV_LEFT
             *    PROPID_ACC_NAV_RIGHT
             *    PROPID_ACC_NAV_PREV
             *    PROPID_ACC_NAV_NEXT
             *    PROPID_ACC_NAV_FIRSTCHILD
             *    PROPID_ACC_NAV_LASTCHILD
             */
            if( idProp == PROPID_ACC_ROLE )
            {
                
                /*  TODO: lookup or otherwise determine the 
                 *  value you want to return for this 
                 *  property of this child.
                 *  Note that idChild is a 1-based index of 
                 *  a child element, so you'll need to 
                 *  subtract 1 if you use 0-based indices.
                 *  If you have a value to return, set 
                 *  pvarValue to that value,
                 *  and set *pfGotProp to TRUE.
                 *  If you have no value to return, do 
                 *  nothing. (*pfGotProp
                 *  will be FALSE from above.)
                 */

                // e.g., pretend that everything is a menu 
                 * item:
                pvarValue.vt = VT_I4;
                pvarValue.lVal = ROLE_SYSTEM_MENUITEM;

                *pfGotProp = TRUE;
            }
        }

        return S_OK;
    }
};



[ ... ]

//
//  Skeleton code to register class which implements IAccPropServer
//
//  Do this after the corresponding HWND is created.
//
//  Perf tip: instead of doing this immediately after the HWND is created,
//  you can delay it until that HWND receives its first WM_GETOBJECT message.
//  This delays the CoCreate until necessary. You will need to subclass the
//  HWND to catch the WM_GETOBJECT. After registering, pass the WM_GETOBJECT
//  on to the original window proc for the HWND.
//


    IAccPropServices * pAccPropSvc = NULL;
    HRESULT hr;
    hr = CoCreateInstance( CLSID_AccPropServices, NULL, CLSCTX_SERVER, IID_IAccPropServices, (void **) & pAccPropSvc ) );
    if( hr == S_OK && pAccPropSvc )
    {
        CMyAccPropServer* pMyPropSrv = new CMyAccPropServer( pAccPropSvc );
        if( pMyPropSrv )
        {
            
            /*  TODO: extend this array if you are 
             *  overriding multiple properties.
             *  Make sure to update the length parameter 
             *  passed to SetHwndPropServer
             *  so that it matches the number of elements in 
             *  this array.
             */
            MSAAPROPID propids[ 1 ];
            propids[ 0 ] = PROPID_ACC_ROLE;

            
            /*  TODO: Specify the appropriate objid and 
             *  childid here. The idObject will
             *  nearly always be OBJID_CLIENT. Use a childid 
             *  of CHILD_CLIENT to refer to
             *  a container or an overall object, or use a 
             *  1-based index to refer to a
             *  specific child item in that container.
             *  To override properties of all elements in a 
             *  container, use CHILDID_SELF,
             *  and specify the ANNO_CONTAINER in the last 
             *  parameter.
             */
            pAccPropSvc->SetHwndPropServer( hwnd, OBJID_CLIENT, CHILDID_SELF, & propid, 1, pMyPropSrv, 0 );
            pMyPropSrv->Release();
            pAccPropSvc->Release();
        }
    }