Partager via


Container Browser

Une application peut utiliser la fonction DsBrowseForContainer pour afficher une boîte de dialogue qui peut être utilisée pour parcourir les conteneurs dans un service domaine Active Directory. La boîte de dialogue affiche les conteneurs dans un format d’arborescence et permet à l’utilisateur de naviguer dans l’arborescence à l’aide du clavier et de la souris. Lorsque l’utilisateur sélectionne un élément dans la boîte de dialogue, l’ADsPath du conteneur sélectionné par l’utilisateur est fourni.

DsBrowseForContainer prend un pointeur vers une structure DSBROWSEINFO qui contient des données sur la boîte de dialogue et retourne l’ADsPath de l’élément sélectionné.

Le membre pszRoot est un pointeur vers une chaîne Unicode qui contient le conteneur racine de l’arborescence. Si pszRoot a la valeur NULL, l’arborescence contient l’arborescence entière.

Le membre pszPath reçoit l’ADsPath de l’objet sélectionné. Il est possible de spécifier un conteneur particulier à afficher et à sélectionner lorsque la boîte de dialogue est affichée pour la première fois. Pour ce faire, définissez pszPath sur l’ADsPath de l’élément à sélectionner et définissez l’indicateur DSBI_EXPANDONOPEN dans dwFlags.

Le contenu et le comportement de la boîte de dialogue peuvent également être contrôlés au moment de l’exécution en implémentant une fonction BFFCallBack . La fonction BFFCallBack est implémentée par l’application et est appelée lorsque certains événements se produisent. Une application peut utiliser ces événements pour contrôler la façon dont les éléments de la boîte de dialogue sont affichés, ainsi que le contenu réel de la boîte de dialogue. Par exemple, une application peut filtrer les éléments affichés dans la boîte de dialogue en implémentant une fonction BFFCallBack qui peut gérer la notification DSBM_QUERYINSERT . Lorsqu’une notification DSBM_QUERYINSERT est reçue, utilisez le membre pszADsPath de la structure DSBITEM pour déterminer l’élément sur le point d’être inséré. Si l’application détermine que l’élément ne doit pas être affiché, elle peut le masquer en effectuant les étapes suivantes.

  1. Ajoutez l’indicateur DSBF_STATE au membre dwMask de la structure DSBITEM .
  2. Ajoutez l’indicateur DSBS_HIDDEN au membre dwStateMask de la structure DSBITEM .
  3. Ajoutez l’indicateur DSBS_HIDDEN au membre dwState de la structure DSBITEM .
  4. Retourne une valeur différente de zéro à partir de la fonction BFFCallBack .

En plus de masquer certains éléments, une application peut modifier le texte et l’icône affichés pour l’élément en gérant la notification DSBM_QUERYINSERT . Pour plus d’informations, consultez DSBITEM.

La fonction BFFCallBack peut utiliser la notification BFFM_INITIALIZED pour obtenir le handle de la boîte de dialogue. L’application peut utiliser ce handle pour envoyer des messages, tels que BFFM_ENABLEOK, à la boîte de dialogue. Pour plus d’informations sur les messages qui peuvent être envoyés à la boîte de dialogue, consultez BFFCallBack.

Le handle de boîte de dialogue peut également être utilisé pour obtenir un accès direct aux contrôles dans la boîte de dialogue. DSBID_BANNER est l’identificateur du contrôle de texte statique dans lequel s’affiche le membre pszTitle de la structure DSBROWSEINFO . DSBID_CONTAINERLIST est l’identificateur du contrôle d’arborescence utilisé pour afficher le contenu de l’arborescence. L’utilisation de ces éléments doit être évitée, si possible, pour éviter de futurs problèmes de compatibilité des applications.

L’exemple de code C++ suivant montre comment utiliser la fonction DsBrowseForContainer pour créer la boîte de dialogue du navigateur de conteneurs et implémenter une fonction BFFCallBack . BFFCallBack utilise la notification DSBM_QUERYINSERT pour remplacer le nom d’affichage de chaque élément par le nom unique de l’élément.

#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;
}