Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

SHBrowseForFolder - how to set initial directory 1

Status
Not open for further replies.

shetlandbob

Programmer
Mar 9, 2004
528
GB
Hello,

I'm using the SHBrowseForFolder dialog to enable the user to select a dir, this works and I've included the code below. (if user selects ok then dir is set into CString resultsDir).

Code:
void CMyDlg::OnFileSetpath()
{
  BROWSEINFO      bi;
  LPMALLOC        pMalloc = NULL;    
  LPITEMIDLIST    pidl;
  char            acStr[MAX_PATH];
  
  if  ( SHGetMalloc ( &pMalloc) != NOERROR )  return; 

  ZeroMemory ( &bi, sizeof ( BROWSEINFO ));

  bi.pidlRoot = NULL; 
  bi.pszDisplayName = acStr;
  bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_RETURNFSANCESTORS | BIF_USENEWUI;
  bi.lpszTitle = "Please Select Directory";
[COLOR=green]//  bi.lpfn = BrowseCallBackProc;
[/color]
  if  ( pidl = SHBrowseForFolder ( &bi ))
  {
    if  ( SHGetPathFromIDList ( pidl, acStr )) resultsDir.Format ( "%s", acStr );

    pMalloc->Free   (pidl);
  }
  if ( pMalloc ) pMalloc->Release();   
}

The problem I'm having is getting it to open at a default directory, I understand you have to use the callback function
Code:
int CALLBACK BrowseCallBackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
  switch(uMsg)
  {
    case BFFM_INITIALIZED:
      ::SendMessage( hwnd, BFFM_SETSELECTION, TRUE, lpData );
       break;
  }
  return 0;
}

However when I include the commented out lines above (i.e.)
Code:
  bi.lpfn = BrowseCallBackProc;
this it wont compile, it complains with the following::

Code:
MenuInput.cpp(32) : error C2440: '=' : cannot convert from 'int (__stdcall CTPP9Dlg::* )(HWND,UINT,LPARAM,LPARAM)' to 'BFFCALLBACK'
        There is no context in which this conversion is possible

I've looked on MSDN and through forums etc..... but as far as I can see this is the way to do it?? Any ideas what I'm doing wrong???
 
Hmmm...can't help you there as I apparently aint using the same version of things as you (for example I do not have the BIF_USENEWUI flag).

In VC6 this works perfectly (note the setting of the bi.lParam attribute):
Code:
int CALLBACK BrowseCallBackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
  switch(uMsg)
  {
    case BFFM_INITIALIZED:
      ::SendMessage( hwnd, BFFM_SETSELECTION, TRUE, lpData );
       break;
  }
  return 0;
}

void CSHBFFTestDlg::OnButton1() 
{
  BROWSEINFO      bi;
  LPMALLOC        pMalloc = NULL;    
  LPITEMIDLIST    pidl;
  char            acStr[MAX_PATH];
  CString initialDir("C:\\SomeDir");
  CString resultsDir;

  if  ( SHGetMalloc ( &pMalloc) != NOERROR )  return; 

  ZeroMemory ( &bi, sizeof ( BROWSEINFO ));

  bi.pidlRoot = NULL; 
  bi.pszDisplayName = acStr;
  bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_RETURNFSANCESTORS;
  bi.lpszTitle = "Please Select Directory";
  bi.lParam = (long)(LPCTSTR)initialDir;
  bi.lpfn = BrowseCallBackProc;

  if  ( pidl = SHBrowseForFolder ( &bi ))
  {
    if  ( SHGetPathFromIDList ( pidl, acStr )) resultsDir.Format ( "%s", acStr );

    pMalloc->Free   (pidl);
  }
  if ( pMalloc ) pMalloc->Release();   	
}

/Per

"It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure."
 
Ok,

I figured it out, I needed to set the lParam value as you mentioned (thanks).

But i'd make a stupid mistake in declaring the callback function in my header file! For any future reference its:

Code:
extern int CALLBACK BrowseCallBackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);

also the "BIF_USENEWUI" flag is for a newer style of dialog, it helps you create directory's as well. Plus a few other things.
 
>But i'd make a stupid mistake in declaring the callback function in my header file!

You mean as a method of the class? That you can do if you make it a static method.

/Per

"It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure."
 
Yes thats what I had done.

Cheers for the info, good to know for the future.
 
Out of curiosity do you get a compilation warning on the line that you set "bi.lparam"??

i.e. the warning:

Code:
warning C4311: 'type cast' : pointer truncation from 'LPCTSTR' to 'unsigned long'
 
Nope.

Are you running on a 64-bit system? Ie where the size of a pointer (64 bits) is greater than the size of a long (32 bits). I don't believe C4311 exists in my configuration.


A side note: In real life I'd set it like
Code:
bi.lParam = reinterpret_cast<long>(static_cast<LPCTSTR>(initialDir));
just to clarify the casts.


/Per

&quot;It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure.&quot;
 
No its not a 64 bit system, (good old windows 2000 32bit), however when I follow the guidelines in link you provided then I can fix the warning???

I'm a bit confused about all this????

But thanks again.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top