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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Presetting starting folder of SHBrowseForFolder() 2

Status
Not open for further replies.

genio1981

Programmer
May 23, 2003
8
US
I apologize in advance if this topic has already been covered, but I have searched this forum up and down and have not found a relating question/answer.

this is what I have:
//
//PathChange - selects a path to a folder that contains MP3s
//and sets that string path to a global var... g_strPath
//when program starts, g_strPath is set to the current Directory.
void PathChange(HWND hwnd)
{
LPITEMIDLIST pidlSelected = NULL;
BROWSEINFO bi = {0};
LPMALLOC pMalloc = NULL;
char pszDisplayName[MAX_PATH];
char szDir[MAX_PATH];

if(SHGetMalloc(&pMalloc) == NO_ERROR)
{
memset(&bi, 0, sizeof(BROWSEINFO));
bi.hwndOwner = hwnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = pszDisplayName;
bi.lpszTitle = "Choose a folder that contains MP3s...";
bi.ulFlags = BIF_EDITBOX | BIF_VALIDATE;
bi.lpfn = NULL;

pidlSelected = SHBrowseForFolder(&bi);
if(pidlSelected != NULL)
{
if(SHGetPathFromIDList(pidlSelected, szDir))
{
g_strPath = szDir;
}
pMalloc->Free(pidlSelected);
}
pMalloc->Release();
}
}

I would like to have the Browse dialog begin by having the g_strPath folder selected instead of "My Computer"... anyone help me with this?
 
Change the current directory to the directory you want to use

_chdir will do that


[sub]I REALLY hope that helps.[/sub]
Will
 
I tried changing the directory with _chdir()... and while the function succeeded in changing the current working directory, it did not set the directory for the SHBrowseForFolder() function. When I call SHBrowseForFolder(), it still opens with "My Computer" pre-selected, which makes it a hassle to navigate through the directory structure each time to get to a certain directory.

Take Winamp, for example (v2), when you click add directory button, and you select a directory... then when you click the add directory button again, you do not have to re-navigate through the folders to select the folder you previously selected.

This is what I am trying to do. Sorry if I wasnt very clear in my question before. Thanks for your help though... if you could aid me in this task, I would be most appreciative.

Chase

Still Learning! :)
 
SHBrowseForFolder returned the value you need (pidlSelected). Don't free it yet, you can use that value and assign into bi.pidlRoot

Btw, Winamp doesn't use SHBrowseForFolder

-- AirCon --
 
OK, that works. Now as I have been looking all through MSDN, I have found the way to get the path from a pidl, however, no way to get the pidl from a path. Would you happen to know how to do this? The very first time I run my SHBrowseForFolder() function, Im still starting at "My Computer"... I already know what the current working directory is, how would I be able to start from there instead?

Still Learning! :)
 
You have to create it yourself by using "Shell Namespace". I've been looking for this too, but I couldn't find (yet) how to create it.

But I have my own method and it works for me. This is how I do it:
Copy from memory location pointed by pidlSelected as a string, 512 bytes long is enough (I think), save it as a file. The next time, read the file (as string), allocate memory with the same length, copy the string into that memory. Then assign the pointer returned by allocate memory into bi.pidlRoot

Regards

-- AirCon --
 
See thread222-498611. Although the thread belongs to VB forum and all the code is written in VB, but it does exactly what you want.

You need to setup a BrowseCallback procedure for doing this. The code will give you the idea how to select the starting folder using BFFM_SETSELECTION message to the dialog when the dialog box is being initialized.

Hope this will help you.
 
hi all,
heres my VB Code but this does not work :(
Code:
Public Function BrowseForFolder(hwndOwner As Long, sPrompt As String) As String
     
     'declare variables to be used
     Dim iNull As Integer
     Dim lResult As Long
     Dim sPath As String
     Dim udtBI As BrowseInfo

    'initialise variables
     With udtBI
        'Set the owner window
        .hwndOwner = hwndOwner
        'lstrcat appends the two strings and returns the memory address
        .lpszTitle = lstrcat(sPrompt, "")
        'Return only if the user selected a directory
        .ulFlags = BIF_RETURNONLYFSDIRS

.pIDLRoot = lpIDList
Code:
     End With

    'Call the browse for folder API
     lpIDList = SHBrowseForFolder(udtBI)
     
    'get the resulting string path
     If lpIDList Then
        sPath = String$(MAX_PATH, 0)
        'Get the path from the IDList
        lResult = SHGetPathFromIDList(lpIDList, sPath)
        'free the block of memory
        'Call CoTaskMemFree(lpIDList)
        iNull = InStr(sPath, vbNullChar)
        If iNull Then sPath = Left$(sPath, iNull - 1)
     End If

    'If cancel was pressed, sPath = ""
    If Right(sPath, 1) <> &quot;\&quot; And Trim(sPath) <> &quot;&quot; Then
      sPath = sPath & &quot;\&quot;
    End If
    
     BrowseForFolder = sPath

End Function

the line in red is supposed to set the root directory right ?
i have this function written in a DLL and am calling it from a Standard EXE project. the variable &quot;lpIDList&quot; is declared as private in the DLL (scope global). does this make a difference.

pls help

__________
[cheers]
Niraj...
&quot;The unexpected success is not just an opportunity for innovation. It demands innovation.&quot;
[noevil]
 
ufobaby,
I am a little bit confused. I do not understand what do you want to do.
Do you want to set the root folder or the initial selected folder?

You are initializing the .pIDLRoot member by an initial value lpIDList.
This will not set the initial folder in the BFF dialog. Instead, it will set the root folder in the folder tree.

Moreover, I do not know how do you initialize the variable lpIDList. I don't think there is a simple method to get the pidl of a folder given its path.(although the function SHGetPathFromIDList does exactly reverse of it.)

In the last you say the variable lpIDList is declared private in the DLL(scope global). What does that mean?

By the way did you see the Thread222-498611?
 
hi,
now even i am confused now ....
i want the &quot;initial selected&quot; directory.

i tried the code which u pointed at ... gives a compile time error ..... &quot;Invalid Use of AddressOF Operator&quot;

any ideas ... ?

__________
[cheers]
Niraj...
&quot;The unexpected success is not just an opportunity for innovation. It demands innovation.&quot;
[noevil]
 
If you want the &quot;initial selected&quot; directory, then this code is right for you.

About the error message...
I just copy-pasted the code in vb and it ran just fine---without any errors. I have also directed another user in thread222-539456 to use this code and they got it working fine without any error.

I think the problem lies on your side. May be some copy-paste problem. Also make sure that you paste the right code in right module.(i.e. Form module and code module.)
I wish you to try again.
 
hi , thx
&quot;If you want the &quot;initial selected&quot; directory, then this code is right for you.

&quot;this code&quot; is which code ? the one which i submitted or the thread which u reffered to.

i have the entire contents written in a Class Module and later compiled in a DLL .. is that what creates a problem. ?



__________
[cheers]
Niraj...
&quot;The unexpected success is not just an opportunity for innovation. It demands innovation.&quot;
[noevil]
 
The code that I pointed...

And the problem also solves...
You should not paste the code in the class module.
Instead you should paste the code in a standard(bas) module.

You can only include the BrowseFolder function in the class module to make it a method of the class but the rest of the code including the BrowseCallbackProc function MUST be placed in the standard module.

See AddressOf operator in MSDN help. It states that the callback function whose address is being retrieved using AddressOf operator MUST reside only in a standard module not in a class or form module etc...
 
thx a ton Hypetia,

thx for that guidance and patience .... :)

jus wondering why is it that we can use AddressOf only for a function in .bas module ?

__________
[cheers]
Niraj...
&quot;The unexpected success is not just an opportunity for innovation. It demands innovation.&quot;
[noevil]
 
The reason that I understand is that all the code in the a standard module is loaded and is available for execution from the instance the vb program is loaded into memory for execution. This means that the addresses of the (callback) procedures are also available for passing to an API fucntion. There is only one copy of that function loaded into memory and its address can be retrieved from any where in the project provided a proper scope.

This is, however not true for class modules. The code for a class module is not loaded into memory until you create an object from that class. So if you reference a callback procedure address to an API, what procedure would that address refer to?(It does not even exist in memory)

Moreover if you have created multiple objects from a class then things become more complicated. Each object will have its own procedure (or method) loaded in memory and if you use AddressOf to get the address you won't know which object's callback procedure you are referring to.

To avoid these confusions the AddressOf operator is only made applicable to callback procedures in a standard module.
I want to mention one thing that this is only MY understanding about this issue. The actual reason may be somewhat different.

Here is an excerpt from MSDN about AddressOf operator.

&quot;AddressOf procedurename

The required procedurename specifies the procedure whose address is to be passed. It must represent a procedure in a standard module module in the project in which the call is made.&quot;


Moreover, this is a standard practice in writing ActiveX controls and DLLs that the callback procedure is always written in a single standard module and all the class instances share a single callback procedure.

There is another issue you should look for.

Since you are using this function in a ActiveX DLL. You should be careful while setting the .hWndOwner member of the BROWSEINFO structure passed to the BrowseForFolder function. I have used.

[tt]bi.hWndOwner = Screen.ActiveForm.hWnd[/tt]

Since your function resides in another project (the ActiveX DLL), Screen.ActiveForm will not refer to the active form of the calling (client) project. It will try to get the active form in the current project (ActiveX DLL) which may not exist at all and the active form of the calling project will not be referenced.
To avoid this flaw use this instead.

[tt]bi.hWndOwner = GetActiveWindow()[/tt]

having GetActiveWindow() declared in the DLL project...

GetActiveWindow function returns the handle of the active window in the current thread regardless of the current project. It will correctly retrieve the handle of the active window in the calling project to show the dialog modally.
 
ummm .. this makes more sense now ... thx for the explaination ...

i have passed the hWnd as a parameter for the function .. hence the calling from will pass the value like &quot;me.hwnd&quot; this solves the problem.

thx once again for everything...

__________
[cheers]
Niraj...
&quot;The unexpected success is not just an opportunity for innovation. It demands innovation.&quot;
[noevil]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top