Fungsi SHBrowseForFolderA (shlobj_core.h)

Menampilkan kotak dialog yang memungkinkan pengguna memilih folder Shell.

Sintaks

PIDLIST_ABSOLUTE SHBrowseForFolderA(
  [in] LPBROWSEINFOA lpbi
);

Parameter

[in] lpbi

Jenis: LPBROWSEINFO

Penunjuk ke struktur BROWSEINFO yang berisi informasi yang digunakan untuk menampilkan kotak dialog.

Nilai kembali

Jenis: PIDLIST_ABSOLUTE

Mengembalikan PIDL yang menentukan lokasi folder yang dipilih relatif terhadap akar namespace. Jika pengguna memilih tombol Batalkan dalam kotak dialog, nilai yang dikembalikan adalah NULL.

Ada kemungkinan bahwa PIDL yang dikembalikan adalah pintasan folder daripada folder. Untuk diskusi lengkap tentang kasus ini, lihat bagian Keterangan.

Keterangan

Untuk Windows Vista atau yang lebih baru, disarankan agar Anda menggunakan IFileDialog dengan opsi FOS_PICKFOLDERS daripada fungsi SHBrowseForFolder. Ini menggunakan dialog Buka File dalam mode pilih folder dan merupakan implementasi yang disukai.

Anda harus menginisialisasi Model Objek Komponen (COM) sebelum memanggil SHBrowseForFolder. Jika Anda menginisialisasi COM menggunakan CoInitializeEx, Anda harus mengatur bendera COINIT_APARTMENTTHREADED dalam parameter dwCoInit-nya . Anda juga dapat menggunakan CoInitialize atau OleInitialize, yang selalu menggunakan utas apartemen. Jika Anda memerlukan fungsionalitas seret dan letakkan, OleInitialize disarankan karena menginisialisasi OLE yang diperlukan serta COM.

Catatan Jika COM diinisialisasi menggunakan CoInitializeEx dengan bendera COINIT_MULTITHREADED, SHBrowseForFolder gagal jika aplikasi panggilan menggunakan bendera BIF_USENEWUI atau BIF_NEWDIALOGSTYLE dalam struktur BROWSEINFO .
 
Adalah tanggung jawab aplikasi panggilan untuk memanggil CoTaskMemFree untuk membebaskan IDList yang dikembalikan oleh SHBrowseForFolder ketika tidak lagi diperlukan.

Ada dua gaya kotak dialog yang tersedia. Gaya yang lebih lama ditampilkan secara default dan tidak dapat diubah ukurannya. Gaya yang lebih baru menyediakan sejumlah fitur tambahan, termasuk kemampuan seret dan letakkan dalam kotak dialog, penyusunan ulang, penghapusan, menu pintasan, kemampuan untuk membuat folder baru, dan perintah menu pintasan lainnya. Awalnya, ini lebih besar dari kotak dialog yang lebih lama, tetapi pengguna dapat mengubah ukurannya. Untuk menentukan kotak dialog menggunakan gaya yang lebih baru, atur bendera BIF_USENEWUI di anggota ulFlags dari struktur BROWSEINFO .

Jika Anda menerapkan fungsi panggilan balik, yang ditentukan dalam anggota lpfn struktur BROWSEINFO , Anda menerima handel ke kotak dialog. Salah satu penggunaan handel jendela ini adalah untuk mengubah tata letak atau isi kotak dialog. Karena tidak dapat diubah, memodifikasi kotak dialog gaya yang lebih lama relatif mudah. Mengubah kotak dialog gaya yang lebih baru jauh lebih sulit, dan tidak disarankan. Tidak hanya memiliki ukuran dan tata letak yang berbeda dari gaya lama, tetapi dimensi dan posisi kontrolnya berubah setiap kali diubah ukurannya oleh pengguna.

Jika bendera BIF_RETURNONLYFSDIRS diatur di anggota ulFlags dari struktur BROWSEINFO , tombol OK tetap diaktifkan untuk item "\server", serta "\server\share" dan item direktori. Namun, jika pengguna memilih item "\server", meneruskan PIDL yang dikembalikan oleh SHBrowseForFolder ke SHGetPathFromIDList gagal.

Pemfilteran Kustom

Pada Windows XP, SHBrowseForFolder mendukung pemfilteran kustom pada konten kotak dialog. Untuk membuat filter kustom, ikuti langkah-langkah ini.
  1. Atur bendera BIF_NEWDIALOGSTYLE di anggota ulFlags struktur BROWSEINFO yang diarahkan oleh parameter lpbi .
  2. Tentukan fungsi panggilan balik di anggota lpfn dari struktur BROWSEINFO yang sama.
  3. Kode fungsi panggilan balik untuk menerima pesan BFFM_INITIALIZED dan BFFM_IUNKNOWN. Pada penerimaan pesan BFFM_IUNKNOWN, parameter lParam fungsi panggilan balik berisi pointer ke implementasi kotak dialog IUnknown. Panggil QueryInterface pada IUnknown tersebut untuk mendapatkan pointer ke instans IFolderFilterSite.
  4. Buat objek yang mengimplementasikan IFolderFilter.
  5. Panggil IFolderFilterSite::SetFilter, meneruskan ke pointer ke IFolderFilter Anda. Metode IFolderFilter kemudian dapat digunakan untuk menyertakan dan mengecualikan item dari pohon.
  6. Setelah filter dibuat, antarmuka IFolderFilterSite tidak lagi diperlukan. Panggil IFolderFilterSite::Release jika Anda tidak memiliki penggunaan lebih lanjut untuk itu.

Berurusan dengan Pintasan

Catatan Bagian ini hanya berlaku untuk Sistem Windows 2000 dan yang lebih lama. Secara default, sistem Windows XP dan yang lebih baru mengembalikan PIDL target pintasan daripada pintasan itu sendiri, selama bendera BIF_NOTRANSLATETARGETS tidak diatur dalam struktur BROWSEINFO .
 
Jika SHBrowseForFolder mengembalikan PIDL ke pintasan, mengirim PIDL tersebut ke SHGetPathFromIDList mengembalikan jalur pintasan itu sendiri daripada jalur targetnya. Jalur ke target pintasan dapat diperoleh dengan menggunakan antarmuka IShellLink seperti yang ditunjukkan dalam contoh ini.
#include 

// Macros for interface casts
#ifdef __cplusplus
#define IID_PPV_ARG(IType, ppType) IID_##IType, reinterpret_cast(static_cast(ppType))
#else
#define IID_PPV_ARG(IType, ppType) &IID_##IType, (void**)(ppType)
#endif

// Retrieves the UIObject interface for the specified full PIDL
STDAPI SHGetUIObjectFromFullPIDL(LPCITEMIDLIST pidl, HWND hwnd, REFIID riid, void **ppv)
{
    LPCITEMIDLIST pidlChild;
    IShellFolder* psf;

    *ppv = NULL;

    HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlChild);
    if (SUCCEEDED(hr))
    {
        hr = psf->GetUIObjectOf(hwnd, 1, &pidlChild, riid, NULL, ppv);
        psf->Release();
    }
    return hr;
}
 
#define ILSkip(pidl, cb)       ((LPITEMIDLIST)(((BYTE*)(pidl))+cb))
#define ILNext(pidl)           ILSkip(pidl, (pidl)->mkid.cb)
 
HRESULT SHILClone(LPCITEMIDLIST pidl, LPITEMIDLIST *ppidl)
{
    DWORD cbTotal = 0;

    if (pidl)
    {
        LPCITEMIDLIST pidl_temp = pidl;
        cbTotal += sizeof (pidl_temp->mkid.cb);

        while (pidl_temp->mkid.cb) 
        {
            cbTotal += pidl_temp->mkid.cb;
            pidl_temp += ILNext (pidl_temp);
        }
    }
    
    *ppidl = (LPITEMIDLIST)CoTaskMemAlloc(cbTotal);
    
    if (*ppidl)
        CopyMemory(*ppidl, pidl, cbTotal);
 
    return  *ppidl ? S_OK: E_OUTOFMEMORY;
}
 
// Get the target PIDL for a folder PIDL. This also deals with cases of a folder  
// shortcut or an alias to a real folder.
STDAPI SHGetTargetFolderIDList(LPCITEMIDLIST pidlFolder, LPITEMIDLIST *ppidl)
{
    IShellLink *psl;
	
    *ppidl = NULL;
    
    HRESULT hr = SHGetUIObjectFromFullPIDL(pidlFolder, NULL, IID_PPV_ARG(IShellLink, &psl));
    
    if (SUCCEEDED(hr))
    {
        hr = psl->GetIDList(ppidl);
        psl->Release();
    }
    
    // It's not a folder shortcut so get the PIDL normally.
    if (FAILED(hr))
        hr = SHILClone(pidlFolder, ppidl);
    
    return hr;
}

// Get the target folder for a folder PIDL. This deals with cases where a folder
// is an alias to a real folder, folder shortcuts, the My Documents folder, and 
// other items of that nature.
STDAPI SHGetTargetFolderPath(LPCITEMIDLIST pidlFolder, LPWSTR pszPath, UINT cchPath)
{
    LPITEMIDLIST pidlTarget;
	
    *pszPath = 0;

    HRESULT hr = SHGetTargetFolderIDList(pidlFolder, &pidlTarget);
    
    if (SUCCEEDED(hr))
    {
        SHGetPathFromIDListW(pidlTarget, pszPath);   // Make sure it is a path
        CoTaskMemFree(pidlTarget);
    }
    
    return *pszPath ? S_OK : E_FAIL;
}

// Retrieves the UIObject interface for the specified full PIDLstatic 
HRESULT SHGetUIObjectFromFullPIDL(LPCITEMIDLIST pidl, HWND hwnd, REFIID riid, void **ppv)
{    
    LPCITEMIDLIST pidlChild;    
    IShellFolder* psf;    
    *ppv = NULL;    
    
    HRESULT hr = SHBindToParent(pidl, IID_IShellFolder, (LPVOID*)&psf, &pidlChild);    
    if (SUCCEEDED(hr))    
    {        
        hr = psf->GetUIObjectOf(hwnd, 1, &pidlChild, riid, NULL, ppv);        
        psf->Release();    
    }    
    return hr;
}

static HRESULT SHILClone(LPCITEMIDLIST pidl, LPITEMIDLIST *ppidl)
{    
    DWORD cbTotal = 0;    
    if (pidl)
    {        
        LPCITEMIDLIST pidl_temp = pidl;        
        cbTotal += pidl_temp->mkid.cb;        
        
        while (pidl_temp->mkid.cb)         
        {            
            cbTotal += pidl_temp->mkid.cb;            
            pidl_temp = ILNext(pidl_temp);        
        }    
    }    
    
    *ppidl = (LPITEMIDLIST)CoTaskMemAlloc(cbTotal);    
    if (*ppidl)        
        CopyMemory(*ppidl, pidl, cbTotal);    
        
    return  *ppidl ? S_OK: E_OUTOFMEMORY;
}
    
// Get the target PIDL for a folder PIDL. This also deals with cases of a folder  
// shortcut or an alias to a real folder.
static HRESULT SHGetTargetFolderIDList(LPCITEMIDLIST pidlFolder, LPITEMIDLIST *ppidl)
{    
    IShellLink *psl;    
    *ppidl = NULL;    
    
    HRESULT hr = SHGetUIObjectFromFullPIDL(pidlFolder, NULL, IID_IShellLink, (LPVOID*)&psl);    
    if (SUCCEEDED(hr))    
    {        
        hr = psl->GetIDList(ppidl);        
        psl->Release();    
    }    
    
    // It's not a folder shortcut so get the PIDL normally.    
    if (FAILED(hr))        
        hr = SHILClone(pidlFolder, ppidl);    
    return hr;
}

// Get the target folder for a folder PIDL. This deals with cases where a folder
// is an alias to a real folder, folder shortcuts, the My Documents folder, 
// and so on.
STDAPI SHGetTargetFolderPath(LPCITEMIDLIST pidlFolder, LPWSTR pszPath, UINT cchPath)
{    
    LPITEMIDLIST pidlTarget;    
    *pszPath = 0;    
    
    HRESULT hr = SHGetTargetFolderIDList(pidlFolder, &pidlTarget);    
    if (SUCCEEDED(hr))    
    {        
        SHGetPathFromIDListW(pidlTarget, pszPath);   
        
        // Make sure it is a path        
        CoTaskMemFree(pidlTarget);    
    }    
    
    return *pszPath ? S_OK : E_FAIL;
}

Catatan

Header shlobj_core.h mendefinisikan SHBrowseForFolder sebagai alias yang secara otomatis memilih versi ANSI atau Unicode dari fungsi ini berdasarkan definisi konstanta pra-prosesor UNICODE. Mencampur penggunaan alias encoding-netral dengan kode yang tidak mengodekan-netral dapat menyebabkan ketidakcocokan yang mengakibatkan kesalahan kompilasi atau runtime. Untuk informasi selengkapnya, lihat Konvensi untuk Prototipe Fungsi.

Persyaratan

Persyaratan Nilai
Klien minimum yang didukung Windows XP [hanya aplikasi desktop]
Server minimum yang didukung Windows 2000 Server [hanya aplikasi desktop]
Target Platform Windows
Header shlobj_core.h (termasuk Shlobj.h, Shlobj_core.h)
Pustaka Shell32.lib
DLL Shell32.dll (versi 4.0 atau yang lebih baru)

Lihat juga

Buka dan Simpan sebagai Kotak Dialog