應用程式應如何使用顯示規範
若要顯示 Active Directory 網域 Service 物件,請使用顯示規範來取得類別和屬性物件的當地語系化顯示數據。 這可讓本地化的顯示名稱和圖示使用,並避免不必要的顯示數據當地語系化。
顯示名稱
適用於適當地區設定之顯示規範物件的 classDisplayName 和 attributeDisplayNames 屬性應該用來取得類別和屬性名稱的顯示文字。 請勿使用 classSchema 或 attributeSchema 物件的 cn、classDisplayName 或 ldapDisplayName 屬性來取得顯示文字卷標,因為這些值並未當地語系化。 如需如何擷取類別物件本地化文字的詳細資訊,請參閱下列範例程序代碼。
圖示
適當地區設定之顯示規範物件的iconPath屬性應該用來取得類別物件的圖示。 如需詳細資訊,請參閱 類別圖示。 如果未為類別物件指定本地化圖示,應該會顯示項目的預設圖示。
建立新物件
可能的話,請使用適當的物件建立精靈來建立新的物件。 如需詳細資訊,請參閱 從您的應用程式叫用建立精靈。
下列程式代碼範例示範如何取得類別的顯示文字和 類別的屬性。
#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;
}