다음을 통해 공유


컨테이너 브라우저

애플리케이션은 DsBrowseForContainer 함수를 사용하여 Active Directory 도메인 서비스의 컨테이너를 탐색하는 데 사용할 수 있는 대화 상자를 표시할 수 있습니다. 대화 상자에는 컨테이너가 트리 형식으로 표시되고 사용자가 키보드와 마우스를 사용하여 트리를 탐색할 수 있습니다. 사용자가 대화 상자에서 항목을 선택하면 사용자가 선택한 컨테이너의 ADsPath가 제공됩니다.

DsBrowseForContainer 는 대화 상자에 대한 데이터가 포함된 DSBROWSEINFO 구조체에 대한 포인터를 사용하고 선택한 항목의 ADsPath를 반환합니다.

pszRoot 멤버는 트리의 루트 컨테이너를 포함하는 유니코드 문자열에 대한 포인터입니다. pszRootNULL이면 트리에 전체 트리가 포함됩니다.

pszPath 멤버는 선택한 개체의 ADsPath를 받습니다. 대화 상자가 처음 표시될 때 표시할 특정 컨테이너를 지정하고 선택할 수 있습니다. 이 작업은 선택할 항목의 ADsPath로 pszPath를 설정하고 dwFlags에서 DSBI_EXPANDONOPEN 플래그를 설정하여 수행됩니다.

BFFCallBack 함수를 구현하여 런타임에 대화 상자의 내용과 동작을 제어할 수도 있습니다. BFFCallBack 함수는 애플리케이션에서 구현되며 특정 이벤트가 발생할 때 호출됩니다. 애플리케이션은 이러한 이벤트를 사용하여 대화 상자의 항목과 대화 상자의 실제 내용이 표시되는 방식을 제어할 수 있습니다. 예를 들어 애플리케이션은 DSBM_QUERYINSERT 알림을 처리할 수 있는 BFFCallBack 함수를 구현하여 대화 상자에 표시되는 항목을 필터링할 수 있습니다. DSBM_QUERYINSERT 알림이 수신되면 DSBITEM 구조체의 pszADsPath 멤버를 사용하여 삽입할 항목을 확인합니다. 애플리케이션에서 항목을 표시해서는 안 된다고 판단되면 다음 단계를 수행하여 항목을 숨길 수 있습니다.

  1. DSBITEM 구조체의 dwMask 멤버에 DSBF_STATE 플래그를 추가합니다.
  2. DSBITEM 구조체의 dwStateMask 멤버에 DSBS_HIDDEN 플래그를 추가합니다.
  3. DSBITEM 구조체의 dwState 멤버에 DSBS_HIDDEN 플래그를 추가합니다.
  4. BFFCallBack 함수에서 0이 아닌 값을 반환합니다.

애플리케이션은 특정 항목을 숨기는 것 외에도 DSBM_QUERYINSERT 알림을 처리하여 항목에 대해 표시되는 텍스트와 아이콘을 수정할 수 있습니다. 자세한 내용은 DSBITEM을 참조하세요.

BFFCallBack 함수는 BFFM_INITIALIZED 알림을 사용하여 대화 상자의 핸들을 가져올 수 있습니다. 애플리케이션은 이 핸들을 사용하여 BFFM_ENABLEOK 같은 메시지를 대화 상자로 보낼 수 있습니다. 대화 상자로 보낼 수 있는 메시지에 대한 자세한 내용은 BFFCallBack을 참조하세요.

대화 상자 핸들을 사용하여 대화 상자의 컨트롤에 직접 액세스할 수도 있습니다. DSBID_BANNERDSBROWSEINFO 구조체의 pszTitle 멤버가 표시되는 정적 텍스트 컨트롤의 식별자입니다. DSBID_CONTAINERLIST 트리 내용을 표시하는 데 사용되는 트리 뷰 컨트롤의 식별자입니다. 가능한 경우 이러한 항목을 사용하여 향후 애플리케이션 호환성 문제를 방지해야 합니다.

다음 C++ 코드 예제에서는 DsBrowseForContainer 함수를 사용하여 컨테이너 브라우저 대화 상자를 만들고 BFFCallBack 함수를 구현하는 방법을 보여 줍니다. BFFCallBackDSBM_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;
}