容器浏览器
应用程序可使用 DsBrowseForContainer 函数来显示可用于浏览 Active Directory 域服务中容器的对话框。 该对话框会以树格式显示容器,并允许用户使用键盘和鼠标浏览整个树。 当用户在对话框中选择某一项目时,将提供用户所选容器的 ADsPath。
DsBrowseForContainer 使用指向 DSBROWSEINFO 结构的指针,而该结构包含有关此对话框的数据,且会返回所选项目的 ADsPath。
pszRoot 成员为一个指向包含树的根容器的 Unicode 字符串的指针。 如果 pszRoot 为 NULL,树则包含整个树。
pszPath 成员会接收所选对象的 ADsPath。 首次显示对话框时,可指定可见以及要选择的特定容器。 为此,可将 pszPath 设为要选择的项目的 ADsPath,并在 dwFlags 中设置 DSBI_EXPANDONOPEN 标志。
此外,还可通过实现 BFFCallBack 函数以便在运行时控制对话框的内容和行为。 BFFCallBack 函数由应用程序实现,并在出现某些事件时进行调用。 应用程序可使用这些事件来控制对话框中项目的显示方式,以及对话框的实际内容。 例如,应用程序可通过实现能处理 DSBM_QUERYINSERT 通知的 BFFCallBack 函数来筛选对话框中显示的项目。 收到 DSBM_QUERYINSERT 通知时,请使用 DSBITEM 结构的 pszADsPath 成员来确定要插入的项目。 如果应用程序确定不应显示该项目,则可通过执行以下步骤来隐藏该项目。
- 将 DSBF_STATE 标志添加到 DSBITEM 结构的 dwMask 成员。
- 将 DSBS_HIDDEN 标志添加到 DSBITEM 结构的 dwStateMask 成员。
- 将 DSBS_HIDDEN 标志添加到 DSBITEM 结构的 dwState 成员。
- 从 BFFCallBack 函数返回一个非零值。
除隐藏某些项目之外,应用程序还可通过处理 DSBM_QUERYINSERT 通知来修改为此项目显示的文本和图标。 有关详细信息,请参阅 DSBITEM。
BFFCallBack 函数可使用 BFFM_INITIALIZED 通知来获取对话框的句柄。 应用程序可使用此句柄将消息(如 BFFM_ENABLEOK)发送到对话框。 有关可发送到对话框的消息的详细信息,请参阅 BFFCallBack。
对话框句柄还可用于直接访问对话框中的控件。 DSBID_BANNER 为 DSBROWSEINFO 结构的 pszTitle 成员显示的静态文本控件的标识符。 DSBID_CONTAINERLIST 为用于显示树内容的树视图控件的标识符。 如果可能,应避免使用这些项目,以免未来出现应用程序兼容性问题。
以下 C++ 代码示例演示了如何使用 DsBrowseForContainer 函数来创建容器浏览器对话框,以及实现 BFFCallBack 函数。 BFFCallBack 使用 DSBM_QUERYINSERT 通知将每个项目的显示名称更改为此项目的可分辨名称。
#include <shlobj.h>
#include <dsclient.h>
#include <atlbase.h>
/**********
WideCharToLocal()
***********/
int WideCharToLocal(LPTSTR pLocal, LPWSTR pWide, DWORD dwChars)
{
*pLocal = NULL;
size_t nWideLength = 0;
wchar_t *pwszSubstring;
nWideLength = wcslen(pWide);
#ifdef UNICODE
if(nWideLength < dwChars)
{
wcsncpy_s(pLocal, pWide, dwChars);
}
else
{
wcsncpy_s(pLocal, pWide, dwChars-1);
pLocal[dwChars-1] = NULL;
}
#else
if(nWideLength < dwChars)
{
WideCharToMultiByte( CP_ACP,
0,
pWide,
-1,
pLocal,
dwChars,
NULL,
NULL);
}
else
{
pwszSubstring = new WCHAR[dwChars];
wcsncpy_s(pwszSubstring,pWide,dwChars-1);
pwszSubstring[dwChars-1] = NULL;
WideCharToMultiByte( CP_ACP,
0,
pwszSubstring,
-1,
pLocal,
dwChars,
NULL,
NULL);
delete [] pwszSubstring;
}
#endif
return lstrlen(pLocal);
}
/**********
BrowseCallback()
***********/
int CALLBACK BrowseCallback(HWND hWnd,
UINT uMsg,
LPARAM lParam,
LPARAM lpData)
{
switch(uMsg)
{
case DSBM_QUERYINSERT:
{
BOOL fReturn = FALSE;
DSBITEM *pItem = (DSBITEM*)lParam;
/*
If this is to the root item, get the distinguished name
for the object and set the display name to the
distinguished name.
*/
if(!(pItem->dwState & DSBS_ROOT))
{
HRESULT hr;
IADs *pads;
hr = ADsGetObject(pItem->pszADsPath ,
IID_IADs, (LPVOID*)&pads);
if(SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
hr = pads->Get(CComBSTR("distinguishedName"),
&var);
if(SUCCEEDED(hr))
{
if(VT_BSTR == var.vt)
{
WideCharToLocal(pItem->szDisplayName,
var.bstrVal,
DSB_MAX_DISPLAYNAME_CHARS);
pItem->dwMask |= DSBF_DISPLAYNAME;
fReturn = TRUE;
}
VariantClear(&var);
}
pads->Release();
}
}
return fReturn;
}
break;
}
return FALSE;
}
/***********
BrowseForContainer()
************/
HRESULT BrowseForContainer(HWND hwndParent,
LPOLESTR *ppContainerADsPath)
{
HRESULT hr = E_FAIL;
DSBROWSEINFO dsbi;
OLECHAR wszPath[MAX_PATH * 2];
DWORD result;
if(!ppContainerADsPath)
{
return E_INVALIDARG;
}
ZeroMemory(&dsbi, sizeof(dsbi));
dsbi.hwndOwner = hwndParent;
dsbi.cbStruct = sizeof (DSBROWSEINFO);
dsbi.pszCaption = TEXT("Browse for a Container");
dsbi.pszTitle = TEXT("Select an Active Directory container.");
dsbi.pszRoot = NULL;
dsbi.pszPath = wszPath;
dsbi.cchPath = sizeof(wszPath)/sizeof(OLECHAR);
dsbi.dwFlags = DSBI_INCLUDEHIDDEN |
DSBI_IGNORETREATASLEAF|
DSBI_RETURN_FORMAT;
dsbi.pfnCallback = BrowseCallback;
dsbi.lParam = 0;
dsbi.dwReturnFormat = ADS_FORMAT_X500;
// Display the browse dialog box.
// Returns -1, 0, IDOK, or IDCANCEL.
result = DsBrowseForContainer(&dsbi);
if(IDOK == result)
{
// Allocate memory for the string.
*ppContainerADsPath = (OLECHAR*)CoTaskMemAlloc(
sizeof(OLECHAR)*(wcslen(wszPath) + 1));
if(*ppContainerADsPath)
{
wcscpy_s(*ppContainerADsPath, wszPath);
// Caller must free using CoTaskMemFree.
hr = S_OK;
}
else
{
hr = E_FAIL;
}
}
else
{
hr = E_FAIL;
}
return hr;
}