Compartir a través de


Container Browser

Una aplicación puede usar la función DsBrowseForContainer para mostrar un cuadro de diálogo que se puede usar para examinar los contenedores de un servicio de Dominio de Active Directory. El cuadro de diálogo muestra los contenedores en un formato de árbol y permite al usuario navegar por el árbol mediante el teclado y el mouse. Cuando el usuario selecciona un elemento en el cuadro de diálogo, se proporciona el ADsPath del contenedor seleccionado por el usuario.

DsBrowseForContainer toma un puntero a una estructura DSBROWSEINFO que contiene datos sobre el cuadro de diálogo y devuelve ADsPath del elemento seleccionado.

El miembro pszRoot es un puntero a una cadena Unicode que contiene el contenedor raíz del árbol. Si pszRoot es NULL, el árbol contendrá todo el árbol.

El miembro pszPath recibe el ADsPath del objeto seleccionado. Es posible especificar un contenedor determinado para que sea visible y seleccionado cuando se muestre por primera vez el cuadro de diálogo. Esto se logra estableciendo pszPath en ADsPath del elemento que se va a seleccionar y estableciendo la marca DSBI_EXPANDONOPEN en dwFlags.

El contenido y el comportamiento del cuadro de diálogo también se pueden controlar en tiempo de ejecución mediante la implementación de una función BFFCallBack . La aplicación implementa la función BFFCallBack y se llama cuando se producen determinados eventos. Una aplicación puede usar estos eventos para controlar cómo se muestran los elementos del cuadro de diálogo, así como el contenido real del cuadro de diálogo. Por ejemplo, una aplicación puede filtrar los elementos mostrados en el cuadro de diálogo mediante la implementación de una función BFFCallBack que pueda controlar la notificación de DSBM_QUERYINSERT . Cuando se recibe una notificación de DSBM_QUERYINSERT , use el miembro pszADsPath de la estructura DSBITEM para determinar qué elemento está a punto de insertarse. Si la aplicación determina que no se debe mostrar el elemento, puede ocultar el elemento realizando los pasos siguientes.

  1. Agregue la marca DSBF_STATE al miembro dwMask de la estructura DSBITEM .
  2. Agregue la marca DSBS_HIDDEN al miembro dwStateMask de la estructura DSBITEM .
  3. Agregue la marca DSBS_HIDDEN al miembro dwState de la estructura DSBITEM .
  4. Devuelve un valor distinto de cero de la función BFFCallBack .

Además de ocultar determinados elementos, una aplicación puede modificar el texto y el icono que se muestran para el elemento controlando la notificación de DSBM_QUERYINSERT . Para obtener más información, consulte DSBITEM.

La función BFFCallBack puede usar la notificación BFFM_INITIALIZED para obtener el identificador del cuadro de diálogo. La aplicación puede usar este identificador para enviar mensajes, como BFFM_ENABLEOK, al cuadro de diálogo. Para obtener más información sobre los mensajes que se pueden enviar al cuadro de diálogo, vea BFFCallBack.

El identificador del cuadro de diálogo también se puede usar para obtener acceso directo a los controles del cuadro de diálogo. DSBID_BANNER es el identificador del control de texto estático en el que se muestra el miembro pszTitle de la estructura DSBROWSEINFO . DSBID_CONTAINERLIST es el identificador del control de vista de árbol usado para mostrar el contenido del árbol. El uso de estos elementos debe evitarse, si es posible, para evitar problemas futuros de compatibilidad de aplicaciones.

En el siguiente ejemplo de código de C++ se muestra cómo usar la función DsBrowseForContainer para crear el cuadro de diálogo del explorador de contenedores e implementar una función BFFCallBack . BFFCallBack usa la notificación DSBM_QUERYINSERT para cambiar el nombre para mostrar de cada elemento al nombre distintivo del elemento.

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