Introduction

This article presents a no-frills, cut-n-paste solution to the age-old problem of browsing for a folder. There are several classes out here that offer much more customization and a plethora of features, but I'm sure one more example won't hurt.

When to use this solution

The benefit of this approach over some of the others here is that this implementation is a direct wrapper function for SHBrowseForFolder. As such, you can use it in console applications that don't use MFC, such as unit-testing applications that could benefit from not hard-coding an output location for test results.

So, in short, if you're looking for eye candy, check out XFolderDialog or some of the other folder dialogs here. Otherwise, read on.

Using the code

To use this code, you need to include the following standard files:

#include"shlobj.h"#include<string>

The GetFolder function

Params

folderpath - A reference to the string that will contain the folder path if successful.

Conclusion

Well, that's really all there is to it. If this code saves time for even one person out here, then the few minutes spent writing this was well worth it. Enjoy!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Walter Storm is currently a principal software engineer doing quantitative research for a private hedge fund. Originally from Tunkhannock, PA., he has a B.S. in Aerospace Engineering from Embry-Riddle Aeronautical University[^], and an M.S. in Systems Engineering from SMU[^]. He has been professionally developing software in some form or another since January of 2001.

Great dialog, we've been using it since '07; but in my specific case I want to suppress the grey 'tooltip' popup the shows lower right offset from tree item that is being moused-over - it occludes the drive, folder desccriptions...

Tried finding flags or methods to disable option, but to no avail. Any ideas?

The code was just what I wanted - simple to use and works great. Your time in doing the article and code helped me and I appreciate it! I programmed from Fortran through many languages - a lot of code - but always non-GUI data-in > data-out type tasks. As an engineer that took up Visual C++ and MFC and GUI tasks after retirement, I rely on the WEB for a lot of help ... and The Code Project (and others) come through again and again.

As MSDN states, the path buffer must be at least MAX_PATH characters in size.
Use TCHAR instead of char in order to allocate output buffer.
You can also allocate it dynamically in order to be more polite to the memory.

I couldn't yet find a way to preset the box to a specific folder. If you have deep nested folders and want to go ub/down just one or two levels, it is annoying to have to walk down rather than starting at a certain folder.

sheesh! I think we have more comments than lines of code on this! Nevertheless, all the better. I do believe there are flags/params for the BROWSEINFO struct that will specify this, I'll look into it and add an arg to the fcn. Check back tomorrow.

I have something for what you are looking for. It's a wrapper class called CShellHelpers that execute all the commands needed to :

1 - Set the starting path of SHBrowseForFolder before opening of the dialog
2 - Then Retrieve the selected path when the dialog is closed

With this wrapper, you can go up from your starting location. It use the BFFM_INITIALIZED message in the BrowseCtrlCallback function to sets the startup folder location.

There are also some other functions like :
1 - Retrieve the icon belonging to the selected folder.
2 - Shell context menu for a given path.
3 - Retrieve volume serial number
4 - Shell About..

Whenever I need to browse for a folder, I use it!
I don't remember when I did this code. From what I can remember, I took some portion of code here and there and assembled it to make this wrapper. The class is still in constant devellopment and is not really ready for release to public but since I came across this discussion, I thought it would be kind from me to let you have my code. I included a small example that show how it work.

Email me if you want to have it. I can't find the damn button to "Add files" to this post!

MSDN: "To close the COM library gracefully, each successful call to OleInitialize, including those that return S_FALSE, must be balanced by a corresponding call to OleUninitialize."

Roland Pibinger wrote:

CoTaskMemFree is the counterpart to SHGetPathFromIDList?

Well, here's how it works (so I think)... The ::SHBrowseForFolder will return a pointer to a ITEMIDLIST that's created using CoTaskAlloc under the hood, and the user is responsible for freeing the memory if the returned pointer is not NULL. So in essence, CoTaskMemFree is freeing allocated memory from SHBrowseForFolder, not SHGetPathFromIDList.

Your call to OleUninitialize() without regards to the result of OleInitialize() might be an incorrect interpretation of what MSDN states on the matter. Someone correctly pointed out that S_FALSE is actually a successful result for OleInitialize() and requires a balanced call to OleUninitialize() but the current revision of your code neglects to account for the other potential unsuccessful result codes from OleInitialize() that would not require a balanced call to OleUnitialize(). The SUCCEEDED macro might be in order here.

Contemplate this...

HRESULT hr;

hr=::OleInitialize(NULL);if (SUCCEEDED(hr)) {

TRACE("Got here 1, %d %d\n",hr,S_OK);

hr=::OleInitialize(NULL); if (SUCCEEDED(hr)) {

// Not an error TRACE("Got here 2, %d %d\n",hr,S_FALSE);

// These would be errors TRACE("%d %d %d %d\n",E_INVALIDARG,E_OUTOFMEMORY, E_UNEXPECTED,RPC_E_CHANGED_MODE);

I didn't need to Alloc, as SHBrowseForFolder does that, however I do need to free the memory, and I changed the code to use CoTaskMemFree. Should be current and undepricated now (As well as free of any memory leaks... )