Figure 2   IPerPropertyBrowsing Interface

 typedef struct tagCALPOLESTR {
            ULONG cElems;
            OLECHAR ** pElems;
} CALPOLESTR;

typedef struct tagCADWORD {
            ULONG cElems;
            DWORD * pElems;
} CADWORD;

interface IPerPropertyBrowsing : IUnknown
{
  HRESULT GetDisplayString(DISPID dispid, BSTR * lpbstr);
  HRESULT MapPropertyToPage(DISPID dispid, CLSID *lpclsid);
  HRESULT GetPredefinedStrings(DISPID dispid, CALPOLESTR *lpcasz, 
                               CADWORD *lpcadw);
  HRESULT GetPredefinedValue(DISPID dispid, DWORD dwCookie,
                             VARIANT *lpvarOut);
}

Figure 4   OnGetPredefinedStrings

 LPCTSTR g_szBobs[] = { 
  _T("Bob"), _T("Bobby"), _T("Robert") 
};
BOOL 
CBobCtrl::OnGetPredefinedStrings(DISPID dispid, 
                                 CStringArray* pStringArray,
                                 CDWordArray * pCookieArray)
{
  BOOL result = FALSE; 
  switch (dispid)
  {
  case dispidFirstName:
//  update string and cookie arrays 
//  and indicate that we have done it
    pStringArray->Add(g_szBobs[0]);
    pCookieArray->Add(0);
    pStringArray->Add(g_szBobs[1]);
    pCookieArray->Add(1);
    pStringArray->Add(g_szBobs[2]);
    pCookieArray->Add(2);
    result = TRUE;
    break;
  default:
//  allow base class to perform 
//  default mappings (usually none)
    result = COleControl::OnGetPredefinedStrings (dispid, 
                                                  pStringArray,
                                                  pCookieArray);
  }
  return result;
}

Figure 5   Standard OnGetPredefinedValue

 BOOL 
CBobCtrl::OnGetPredefinedValue(DISPID dispid, 
                               DWORD dwCookie, 
                               VARIANT * lpvarOut)
{
  USES_CONVERSION;
  BOOL result = FALSE; 
  switch (dispid)
  {
  case dispidFirstName:
// map dwCookie to the name and indicate 
// that we did it
    VariantInit(lpvarOut);
    lpvarOut->vt = VT_BSTR;
    assert(dwCookie < 3);
    lpvarOut->bstrVal = SysAllocString(T2COLE(
                            g_szBobs[dwCookie]));
    result = TRUE;
    break;
  default:
// allow base class to perform mappings
   result = COleControl::OnGetPredefinedValue(dispid, 
                                              dwCookie, 
                                              lpvarOut);
  }
  return result;
}

Figure 6   Custom OnGetPredefinedValue

 BOOL 
CBobCtrl::OnGetPredefinedValue(DISPID dispid,
                               DWORD dwCookie, 
                               VARIANT * lpvarOut)
{
  BOOL result = FALSE; 
  switch (dispid)
  {
  case dispidFirstName:
    VariantInit(lpvarOut);
    lpvarOut->vt = VT_I2;
    lpvarOut->iVal = short(dwCookie);
    result = TRUE;
    break line
  default:
    result = COleControl::OnGetPredefinedValue(dispid,
                                               dwCookie,
                                               lpvarOut);
  }
  return result;
}

Figure 7   OnGetDisplayString

 BOOL 
CBobCtrl::OnGetDisplayString(DISPID dispid, 
                             CString& strValue)
{
  BOOL result = FALSE; 
  switch (dispid)
  {
  case dispidFirstName:
//  update display string and indicate that 
//  we did it
    strValue = g_szBobs[m_firstName];
    result = TRUE;
    break;
  default:
//  allow base class to perform mappings
    result = COleControl::OnGetDisplayString(dispid, 
                                             strValue);
  }
  return result;
}

Figure 9   OnMapPropertyToPage

 BOOL 
CBobCtrl::OnMapPropertyToPage(DISPID dispid, 
                              CLSID *lpclsid, 
                              BOOL* pbPageOptional)
{
  BOOL result = FALSE; 
  switch (dispid)
  {
  case dispidLastName:
//  map dispid to a CLSID and indicate 
//  that we did it
    *lpclsid = CLastNamePropPage::guid;
    *pbPageOptional = TRUE;
    result = TRUE;
    break;
  default:
//  allow base class to perform mappings
    result = COleControl::OnMapPropertyToPage(dispid, 
                                              lpclsid, 
                                              pbPageOptional);
  }
  return result;
}