Page 1 of 1
PathRequester to find a specific file
Posted: Fri Mar 29, 2013 7:29 pm
by SniffTheGlove
Hello,
Looking for a Windows Only implementation...
I am looking for a way to replicate how windows shows a path selector (just like PB PathRequester) however the OK button is disabled until a path is chosen that includes a specific file.
In Windows this happens when you are asked to select the location of an ini file during installation of some drivers.
EG I want the user to locate a specific file say myfile.ini
If I use PB OpenFileRequester then I can specify a file however the verification check only happens once a user clicks the OPEN button and as happens the file does not have to be there for the OPEN to process, so you have to add code into the cancellation to recall the OpenFileRequestor and so on.
I much prefer PathRequester but only for the OK to be enabled as soon ans a path is clicked on and that file resides in that path or if there is a way to disable the OPEN button in OpenFileRequester until a path is chosen that includes the specified file.
I hope you understand me.
Thanks
Re: PathRequester to find a specific file
Posted: Fri Mar 29, 2013 7:44 pm
by IdeasVacuum
...At the end of the day, it's just a form, you can code it yourself in 5 minutes.
Re: PathRequester to find a specific file
Posted: Sat Mar 30, 2013 4:32 am
by pwd
Slightly modified version of
this snippet.
Code: Select all
Procedure BrowseCallbackProc(hwnd, msg, lParam, lData)
szDir$ = Space(#MAX_PATH)
Select msg
Case #BFFM_INITIALIZED
SendMessage_(hwnd, #BFFM_SETSELECTION, #BFFM_INITIALIZED, lData)
SendMessage_(hwnd, #BFFM_ENABLEOK, 0, 0)
Case #BFFM_SELCHANGED
If SHGetPathFromIDList_(lParam, @szDir$)
SendMessage_(hwnd, #BFFM_SETSTATUSTEXT, 0, @szDir$)
If szDir$ = "PATH\TO\YOUR\file.ini"
SendMessage_(hwnd, #BFFM_ENABLEOK, 0, 1)
Else
SendMessage_(hwnd, #BFFM_ENABLEOK, 0, 0)
EndIf
EndIf
EndSelect
EndProcedure
Procedure.s BrowseForFolder(Style, Titel.s, Path.s)
Folder.s = Space(#MAX_PATH)
Dir.BROWSEINFO
Dir\hwndOwner = GetActiveWindow_()
Dir\pszDisplayName = @Folder
Dir\lpszTitle = @Titel
Dir\ulFlags = Style
Dir\lpfn = @BrowseCallbackProc()
Dir\lParam = @Path
result.l = SHBrowseForFolder_(@Dir)
SHGetPathFromIDList_(result, @Folder)
If Folder <> ""
If FileSize(Folder) = - 2
If Right(Folder, 1) <> "\" : Folder + "\" : EndIf
EndIf
EndIf
CoTaskMemFree_(result)
ProcedureReturn Folder
EndProcedure
Style = #BIF_STATUSTEXT | #BIF_BROWSEINCLUDEFILES
Debug BrowseForFolder(Style, "Please choose your path", "")
Re: PathRequester to find a specific file
Posted: Sat Mar 30, 2013 1:11 pm
by SniffTheGlove
Thanks PWD, that got me to a good starting point. I made a few changes to the code and it now does what I want.
I only have one issue if anybody knows how to correct it I will be grateful.
From the following code I have had to set a global variable so I can search for that file when a folder is selected. So is there a way to send the variable FileName.s to the BrowseCallbackProc procedure with out using a global variable from the BrowseForFolder procedure.
If you run this code then the file win.ini is located in the Windows folder...
Code: Select all
Global FileName.s = "win.ini"
Procedure BrowseCallbackProc(hwnd, msg, lParam, lData)
szDir$ = Space(#MAX_PATH)
Select msg
Case #BFFM_INITIALIZED
SendMessage_(hwnd, #BFFM_SETSELECTION, #BFFM_INITIALIZED, lData)
SendMessage_(hwnd, #BFFM_ENABLEOK, 0, 0)
Case #BFFM_SELCHANGED
If SHGetPathFromIDList_(lParam, @szDir$)
If ExamineDirectory(0, szDir$, "*." + GetExtensionPart(FileName.s))
While NextDirectoryEntry(0)
If LCase(DirectoryEntryName(0)) = LCase(Filename.s)
SendMessage_(hwnd, #BFFM_ENABLEOK, 0, 1)
Else
SendMessage_(hwnd, #BFFM_ENABLEOK, 0, 0)
EndIf
Wend
FinishDirectory(0)
EndIf
EndIf
EndSelect
EndProcedure
Procedure.s BrowseForFolder(Style, Titel.s, Path.s, FileName.s)
Folder.s = Space(#MAX_PATH)
Dir.BROWSEINFO
Dir\hwndOwner = GetActiveWindow_()
Dir\pszDisplayName = @Folder
Dir\lpszTitle = @Titel
Dir\ulFlags = Style
Dir\lParam = @Path
Dir\lpfn = @BrowseCallbackProc()
result.l = SHBrowseForFolder_(@Dir)
SHGetPathFromIDList_(result, @Folder)
If Folder <> ""
If FileSize(Folder) = - 2
If Right(Folder, 1) <> "\" : Folder + "\" : EndIf
EndIf
EndIf
CoTaskMemFree_(result)
ProcedureReturn Folder
EndProcedure
Style = 0
FullPathAndFileName.s = BrowseForFolder(Style, "Please choose your path", "C:\",FileName.s)
Debug FullPathAndFileName.s + FileName.s
.
Re: PathRequester to find a specific file
Posted: Sat Mar 30, 2013 6:44 pm
by luis
Since BROWSEINFO\lParam it's a custom parameter, probably you could just merge all the vars you want in path$ inside BrowseForFolder().
In the callback, split the string back into its components.
Or use a structure defined in BrowseForFolder() and store its address inside Dir\lParam.
Since you don't leave the procedure the struct should be accessible from the callback.
EDIT: Using your code, something like this:
Code: Select all
; Global FileName.s = "win.ini"
Structure T_BROWSE_DATA
Path$
FileName$
EndStructure
Procedure BrowseCallbackProc(hwnd, msg, lParam, *lData.T_BROWSE_DATA)
szDir$ = Space(#MAX_PATH)
FileName$ = *lData\FileName$
Path$ = *lData\Path$
Select msg
Case #BFFM_INITIALIZED
SendMessage_(hwnd, #BFFM_SETSELECTION, #BFFM_INITIALIZED, Path$)
SendMessage_(hwnd, #BFFM_ENABLEOK, 0, 0)
Case #BFFM_SELCHANGED
SendMessage_(hwnd, #BFFM_ENABLEOK, 0, 0)
If SHGetPathFromIDList_(lParam, @szDir$)
If ExamineDirectory(0, szDir$, "*." + GetExtensionPart(FileName$))
While NextDirectoryEntry(0)
If LCase(DirectoryEntryName(0)) = LCase(FileName$)
SendMessage_(hwnd, #BFFM_ENABLEOK, 0, 1)
EndIf
Wend
FinishDirectory(0)
EndIf
EndIf
EndSelect
EndProcedure
Procedure.s BrowseForFolder(Style, Titel.s, Path.s, FileName.s)
Protected MyData.T_BROWSE_DATA
MyData\Path$ = Path
MyData\FileName$ = FileName
Folder.s = Space(#MAX_PATH)
Dir.BROWSEINFO
Dir\hwndOwner = GetActiveWindow_()
Dir\pszDisplayName = @Folder
Dir\lpszTitle = @Titel
Dir\ulFlags = Style
Dir\lParam = @MyData ; -> this end up in *lData
Dir\lpfn = @BrowseCallbackProc()
result.l = SHBrowseForFolder_(@Dir)
SHGetPathFromIDList_(result, @Folder)
If Folder <> ""
If FileSize(Folder) = - 2
If Right(Folder, 1) <> "\" : Folder + "\" : EndIf
EndIf
EndIf
CoTaskMemFree_(result)
ProcedureReturn Folder
EndProcedure
Style = 0
FileName.s = "filename.ini"
FullPathAndFileName.s = BrowseForFolder(Style, "Please choose your path", "C:\", FileName)
Debug FullPathAndFileName + FileName
Re: PathRequester to find a specific file
Posted: Sun Mar 31, 2013 12:37 pm
by SniffTheGlove
Thanks Luis.
I went with the structure you posted. Works great