Coding Tips (JavaScript/CSS/VBA/Win32)

Useful code snippets, tips and some Windows applications

How To Have a Browse For Folder Dialog select One of the special folders as an initial Directory

So you use the SHBrowseForFolder function to display the Browse For Folder dialog, and would like it to select one of the Windows special folders on opening, like for example, My Documents, Favorites or My Music.

If you don't know it yet, Windows keeps the list of all special folders in the registry under the HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders key. Here is a function to retrieve the value of a special folder in the HKEY_CURRENT_USER registry:

int GetSpecialFolder(char *name, char *folder)
{
	HKEY m_hkey;
	TCHAR lpValue[MAX_PATH];
	DWORD dwType = REG_SZ;
	DWORD dwSize = MAX_PATH;
	char strFullKey[MAX_PATH];
	strcpy(strFullKey,
		"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");

	if(RegOpenKeyEx(HKEY_CURRENT_USER, strFullKey, 0,
		KEY_READ,&m_hkey)!=ERROR_SUCCESS)
			return GetLastError();

	if (RegQueryValueEx(m_hkey, name,  0,
		&dwType, (LPBYTE) lpValue,&dwSize)!= ERROR_SUCCESS)
			return GetLastError();

	RegCloseKey(m_hkey);
	strcpy(folder, lpValue);
	return 1;
}
The function takes two arguments: name for a special folder name, e.g. Personal for My Documents, or Favorites, and a folder to receive the path to the special folder.

BROWSEINFO structure has two members we are interested in: lpfn and lParam. Normally, you leave them at NULL and 0 to accept default values for an initial directory, which is usually My Computer. For our purposes, the lpfn member will contain the address of a BrowseCallbackProc function. This function has the following syntax:

int CALLBACK BrowseCallbackProc( HWND hwnd,
    UINT uMsg,
    LPARAM lParam,
    LPARAM lpData
);
Here is the listing of the function body:
   if (uMsg==BFFM_INITIALIZED)
   {
	   ::SendMessage(hWnd, BFFM_SETSELECTION, TRUE, lpData );
   }
   return 0;
A couple of caveats. For MFC, if this function is a member of your class, it has to be declared static. Also, the SendMessage function requires the use of the global unary scope operator (::). Otherwise, the compiler will assume that the SendMessage is a member function of the CWnd class.

Assuming that you have declared a TCHAR folder[MAX_PATH] variable and it received the path to a special folder from the GetSpecialFolder function, the final result will be as follows:

	bi.lpfn = BrowseCallbackProc;
	bi.lParam = (long)(LPCTSTR)folder;