Comment les applications doivent utiliser les spécificateurs d’affichage
Pour afficher domaine Active Directory objets Service, utilisez des spécificateurs d’affichage pour obtenir des données d’affichage localisées pour les objets de classe et d’attribut. Cela permet d’utiliser des noms d’affichage et des icônes localisés et d’éviter la localisation inutile des données d’affichage.
Noms d’affichage
Les propriétés classDisplayName et attributeDisplayNames des objets spécificateur d’affichage pour les paramètres régionaux appropriés doivent être utilisées pour obtenir le texte d’affichage des noms de classes et d’attributs. N’utilisez pas les propriétés cn, classDisplayName ou ldapDisplayName des objets classSchema ou attributeSchema pour obtenir des étiquettes de texte d’affichage, car ces valeurs ne sont pas localisées. Pour plus d’informations sur la façon de récupérer du texte localisé pour un objet de classe, consultez l’exemple de code suivant.
Icônes
La propriété iconPath des objets spécificateur d’affichage pour les paramètres régionaux appropriés doit être utilisée pour obtenir l’icône à afficher pour un objet de classe. Pour plus d’informations, consultez Icônes de classe. Si aucune icône localisée n’est spécifiée pour un objet de classe, une icône par défaut doit être affichée pour l’élément.
Création d’objets
Dans la mesure du possible, utilisez les Assistants de création d’objets appropriés pour créer de nouveaux objets. Pour plus d’informations, consultez Appel d’Assistants création à partir de votre application.
L’exemple de code suivant montre comment obtenir le texte d’affichage d’une classe et un attribut d’une classe.
#include <atlbase.h>
/**************************************************************************
GetClassDisplaySpecifierContainer()
**************************************************************************/
HRESULT GetClassDisplaySpecifierContainer(LPWSTR pwszClass,
LCID locale,
IADs **ppads)
{
if((NULL == pwszClass) || (NULL == ppads))
{
return E_INVALIDARG;
}
*ppads = NULL;
// If no locale is specified, use the default system locale.
if(0 == locale)
{
locale = GetSystemDefaultLCID();
if(0 == locale)
{
return E_FAIL;
}
}
// Verify that it is a valid locale.
if(!IsValidLocale(locale, LCID_SUPPORTED))
{
return E_INVALIDARG;
}
HRESULT hr;
IADs *padsRoot = NULL;
hr = ADsOpenObject( L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)&padsRoot);
if(SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
// Get the DN to the configuration container.
hr = padsRoot->Get(CComBSTR(L"configurationNamingContext"), &var);
if(SUCCEEDED(hr))
{
WCHAR wszPath[MAX_PATH * 2];
// Build the string to bind to the container for the
// specified locale in the DisplaySpecifiers container.
swprintf_s(wszPath,
L"LDAP://cn=%s-Display,cn=%x,cn=DisplaySpecifiers,%s",
pwszClass,
locale,
var.bstrVal);
VariantClear(&var);
// Bind to the container.
hr = ADsOpenObject( wszPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)ppads);
}
padsRoot->Release();
}
return hr;
}
/**************************************************************************
GetClassDisplayLabel()
**************************************************************************/
HRESULT GetClassDisplayLabel(LPWSTR pwszClass,
LCID locale,
BSTR *pbstrClassLabel)
{
if((NULL == pwszClass) || (NULL == pbstrClassLabel))
{
return E_INVALIDARG;
}
*pbstrClassLabel = NULL;
HRESULT hr;
IADs *padsDispSpec;
hr = GetClassDisplaySpecifierContainer(pwszClass, locale, &padsDispSpec);
if(SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
// Get the classDisplayName property value.
hr = padsDispSpec->Get(CComBSTR(L"classDisplayName"), &var);
if(SUCCEEDED(hr))
{
if(VT_BSTR == var.vt)
{
// Do not free the BSTR. The caller will handle it.
*pbstrClassLabel = var.bstrVal;
}
else
{
VariantClear(&var);
hr = E_FAIL;
}
}
padsDispSpec->Release();
}
return hr;
}
/**************************************************************************
GetAttributeDisplayLabel()
**************************************************************************/
HRESULT GetAttributeDisplayLabel(LPWSTR pwszClass,
LPWSTR pwszAttribute,
LCID locale,
BSTR *pbstrAttributeLabel)
{
if( (NULL == pwszClass) ||
(NULL == pwszAttribute) ||
(NULL == pbstrAttributeLabel))
{
return E_INVALIDARG;
}
*pbstrAttributeLabel = NULL;
HRESULT hr;
IADs *padsDispSpec;
hr = GetClassDisplaySpecifierContainer(pwszClass, locale, &padsDispSpec);
if(SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
// Get the attributeDisplayNames property values
hr = padsDispSpec->GetEx(CComBSTR(L"attributeDisplayNames"), &var);
if(SUCCEEDED(hr))
{
LONG lStart,
lEnd,
i;
SAFEARRAY *psa;
VARIANT varItem;
VariantInit(&varItem);
psa = V_ARRAY(&var);
// Get the lower and upper bound.
hr = SafeArrayGetLBound(psa, 1, &lStart);
hr = SafeArrayGetUBound(psa, 1, &lEnd);
/*
The attributeDisplayNames values take the form
"<attribute name>,<display name>". Enumerate the values, looking
for the one that begins with the specified attribute name.
*/
for(i = lStart; i <= lEnd; i++)
{
hr = SafeArrayGetElement(psa, &i, &varItem);
if(SUCCEEDED(hr))
{
WCHAR wszTemp[MAX_PATH];
wcsncpy_s(wszTemp,
V_BSTR(&varItem),
lstrlenW(pwszAttribute) + 1);
if(0 == lstrcmpiW(pwszAttribute, wszTemp))
{
LPWSTR pwszDisplayLabel;
/*
The proper value was found. Now, parse the value, looking
for the first comma, which delimits the attribute name
from the display name.
*/
for( pwszDisplayLabel = V_BSTR(&varItem);
*pwszDisplayLabel;
pwszDisplayLabel = CharNextW(pwszDisplayLabel))
{
if(',' == *pwszDisplayLabel)
{
/*
The delimiter was found. Set the string
pointer to the next character, which is the
first character of the display name.
*/
pwszDisplayLabel = CharNextW(pwszDisplayLabel);
break;
}
}
if(*pwszDisplayLabel)
{
// Copy the display name to the output.
*pbstrAttributeLabel = CComBSTR(pwszDisplayLabel).Detach();
hr = S_OK;
}
/*
Release the item variant because the break prevents
it from getting released by the VariantClear call below.
*/
VariantClear(&varItem);
break;
}
VariantClear(&varItem);
}
}
}
padsDispSpec->Release();
}
return hr;
}