Freigeben über


Containerbrowser

Eine Anwendung kann die Funktion DsBrowseForContainer verwenden, um ein Dialogfeld anzuzeigen, das zum Durchsuchen der Container in einem Active Directory-Domäne Dienst verwendet werden kann. Das Dialogfeld zeigt die Container in einem Strukturformat an und ermöglicht dem Benutzer, mithilfe der Tastatur und Maus durch die Struktur zu navigieren. Wenn der Benutzer ein Element im Dialogfeld auswählt, wird der vom Benutzer ausgewählte ADsPath des vom Benutzer ausgewählten Containers bereitgestellt.

DsBrowseForContainer verwendet einen Zeiger auf eine DSBROWSEINFO-Struktur , die Daten über das Dialogfeld enthält und die ADsPath des ausgewählten Elements zurückgibt.

Das pszRoot-Element ist ein Zeiger auf eine Unicode-Zeichenfolge, die den Stammcontainer der Struktur enthält. Wenn pszRootNULL ist, enthält die Struktur die gesamte Struktur.

Das pszPath-Element empfängt die ADsPath des ausgewählten Objekts. Es ist möglich, einen bestimmten Container anzugeben, der sichtbar und ausgewählt werden soll, wenn das Dialogfeld zuerst angezeigt wird. Dies erfolgt durch Festlegen von pszPath auf die ADsPath des Elements, das ausgewählt und das DSBI_EXPANDONOPEN Flag in dwFlags festgelegt wird.

Der Inhalt und das Verhalten des Dialogfelds können auch zur Laufzeit gesteuert werden, indem eine BFFCallBack-Funktion implementiert wird. Die BFFCallBack-Funktion wird von der Anwendung implementiert und wird aufgerufen, wenn bestimmte Ereignisse auftreten. Eine Anwendung kann diese Ereignisse verwenden, um zu steuern, wie die Elemente im Dialogfeld angezeigt werden, sowie den tatsächlichen Inhalt des Dialogfelds. Beispielsweise kann eine Anwendung die im Dialogfeld angezeigten Elemente filtern, indem sie eine BFFCallBack-Funktion implementieren, die die DSBM_QUERYINSERT Benachrichtigung behandeln kann. Wenn eine DSBM_QUERYINSERT Benachrichtigung empfangen wird, verwenden Sie das PszADsPath-Element der DSBITEM-Struktur , um zu bestimmen, welche Elemente eingefügt werden sollen. Wenn die Anwendung bestimmt, dass das Element nicht angezeigt werden soll, kann es das Element ausblenden, indem Sie die folgenden Schritte ausführen.

  1. Fügen Sie das DSBF_STATE Flag dem dwMask-Element der DSBITEM-Struktur hinzu.
  2. Fügen Sie dem DwStateMask-Element der DSBITEM-Struktur das DSBS_HIDDEN Flag hinzu.
  3. Fügen Sie dem dwState-Element der DSBITEM-Struktur das DSBS_HIDDEN Flag hinzu.
  4. Geben Sie einen nichtzero-Wert aus der BFFCallBack-Funktion zurück.

Zusätzlich zum Ausblenden bestimmter Elemente kann eine Anwendung den Text und das Symbol ändern, das für das Element angezeigt wird, indem sie die DSBM_QUERYINSERT Benachrichtigung behandeln. Weitere Informationen finden Sie unter DSBITEM.

Die BFFCallBack-Funktion kann die BFFM_INITIALIZED Benachrichtigung verwenden, um den Handle des Dialogfelds abzurufen. Die Anwendung kann diesen Handle verwenden, um Nachrichten zu senden, z. B. BFFM_ENABLEOK, an das Dialogfeld. Weitere Informationen zu den Nachrichten, die an das Dialogfeld gesendet werden können, finden Sie unter BFFCallBack.

Das Dialogfeld-Handle kann auch verwendet werden, um direkten Zugriff auf die Steuerelemente im Dialogfeld zu erhalten. DSBID_BANNER ist der Bezeichner für das statische Textsteuerelement, in dem das pszTitle-Element der DSBROWSEINFO-Struktur angezeigt wird. DSBID_CONTAINERLIST ist der Bezeichner des Strukturansichtssteuerelements, das zum Anzeigen des Strukturinhalts verwendet wird. Die Verwendung dieser Elemente sollte bei Bedarf vermieden werden, um zukünftige Anwendungskompatibilitätsprobleme zu verhindern.

Im folgenden C++-Codebeispiel wird gezeigt, wie Sie die Funktion DsBrowseForContainer verwenden, um das Containerbrowserdialogfeld zu erstellen und eine BFFCallBack-Funktion zu implementieren. Der BFFCallBack verwendet die DSBM_QUERYINSERT Benachrichtigung, um den Anzeigenamen für jedes Element in den unterschiedenen Namen des Elements zu ändern.

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