Condividi tramite


Browser contenitore

Un'applicazione può usare la funzione DsBrowseForContainer per visualizzare una finestra di dialogo che può essere usata per esplorare i contenitori in un servizio di dominio Active Directory. La finestra di dialogo visualizza i contenitori in un formato albero e consente all'utente di spostarsi all'interno dell'albero usando la tastiera e il mouse. Quando l'utente seleziona un elemento nella finestra di dialogo, viene fornito il percorso ADsPath del contenitore selezionato dall'utente.

DsBrowseForContainer accetta un puntatore a una struttura DSBROWSE INFO che contiene dati sulla finestra di dialogo e restituisce il percorso ADsPath dell'elemento selezionato.

Il membro pszRoot è un puntatore a una stringa Unicode che contiene il contenitore radice dell'albero. Se pszRoot è NULL, l'albero conterrà l'intero albero.

Il membro pszPath riceve l'ADsPath dell'oggetto selezionato. È possibile specificare un determinato contenitore da visualizzare e selezionare quando viene visualizzata per la prima volta la finestra di dialogo. Questa operazione viene eseguita impostando pszPath su ADsPath dell'elemento da selezionare e impostando il flag DSBI_EXPANDONOPEN in dwFlags.

Il contenuto e il comportamento della finestra di dialogo possono anche essere controllati in fase di esecuzione implementando una funzioneBFFCallBack. La funzione BFFCallBack viene implementata dall'applicazione e viene chiamata quando si verificano determinati eventi. Un'applicazione può usare questi eventi per controllare la modalità di visualizzazione degli elementi nella finestra di dialogo, nonché il contenuto effettivo della finestra di dialogo. Ad esempio, un'applicazione può filtrare gli elementi visualizzati nella finestra di dialogo implementando una funzione BFFCallBack in grado di gestire la notifica di DSBM_QUERYINSERT. Quando viene ricevuta una notifica di DSBM_QUERYINSERT, utilizzare il membro pszADsPath della strutturaDSBITEMper determinare quale elemento deve essere inserito. Se l'applicazione determina che l'elemento non deve essere visualizzato, può nascondere l'elemento eseguendo la procedura seguente.

  1. Aggiungere il flag di DSBF_STATE al membro dwMask della strutturaDSBITEM.
  2. Aggiungere il flag di DSBS_HIDDEN al membro dwStateMask della strutturaDSBITEM.
  3. Aggiungere il flag DSBS_HIDDEN al membro dwState della strutturaDSBITEM.
  4. Restituisce un valore diverso da zero dalla funzioneBFFCallBack.

Oltre a nascondere determinati elementi, un'applicazione può modificare il testo e l'icona visualizzati per l'elemento gestendo la notifica DSBM_QUERYINSERT. Per altre informazioni, vedere DSBITEM.

La funzioneBFFCallBackpuò usare la notifica di BFFM_INITIALIZED per ottenere l'handle della finestra di dialogo. L'applicazione può usare questo handle per inviare messaggi, ad esempio BFFM_ENABLEOK, alla finestra di dialogo. Per altre informazioni sui messaggi che è possibile inviare alla finestra di dialogo, vedere BFFCallBack.

L'handle della finestra di dialogo può essere usato anche per ottenere l'accesso diretto ai controlli nella finestra di dialogo. DSBID_BANNER è l'identificatore per il controllo testo statico in cui viene visualizzato il membro pszTitle del struttura DSBROWSEINFO. DSBID_CONTAINERLIST è l'identificatore del controllo visualizzazione albero utilizzato per visualizzare il contenuto della struttura ad albero. L'uso di questi elementi deve essere evitato, se possibile, per evitare futuri problemi di compatibilità delle applicazioni.

Nell'esempio di codice C++ seguente viene illustrato come usare la funzioneDsBrowseForContainerper creare la finestra di dialogo del browser del contenitore e implementare una funzioneBFFCallBack. Il BFFCallBack usa la notifica di DSBM_QUERYINSERT per modificare il nome visualizzato per ogni elemento con il nome distinto dell'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;
}