Hi,
I have a small routine which populates drives and folders into a Treeview Control.
Even though FindFirstFile(while populating the tree) read the user's folder as C:\Users; the folder
ends up in the treeview control in a localized version. In my case C:\Brukere.
Now, if the user should check this folder(C:\Brukere) in order to search it for files(as the start
folder to search in), FindFirstFile fails to find anything. Works find if C:\Users is used.
Question #1:
Is there a way to prevent localized version of this folder to be added to the treeview?
Question #2:of this folder
Is there a way to detect that C:\Brukere is a special folder and then retrieve it's real name(C:\Users)?
Thanks for your help!
--
Regards,
Olav Bergesen
Hi Olav,
If you end up with a localized folder name to your treeview then
the result from FindFirstFile/FindNextFile must have been transformed by
something like the SHGetFileInfo api or similar. To prevent it you must find where it is occuring.
As a demo, here is some code that build a DisplayName
or LocalizedName if you prefer from a regular path name.
Also a routine that do reverse engineering to give a path name from a DisplayName.
Pierre
#COMPILE EXE '#Win 8.04#
#DIM ALL
#INCLUDE "Win32Api.inc"
'______________________________________________________________________________
FUNCTION GetDisplayName(BYVAL sPathName AS STRING) AS STRING 'Get localized DisplayName from a path name
LOCAL FileInfo AS SHFILEINFO
LOCAL sDisplayName AS STRING
LOCAL sBuildPath AS STRING
LOCAL SubPathCount AS LONG
LOCAL Looper AS LONG
IF ASC(sPathName, -1) = 92 THEN 'Is last character is a backslash
sPathName = LEFT$(sPathName, -1) 'Remove trailing backslash
END IF
SubPathCount = PARSECOUNT(sPathName, "\") 'Count the path parts, Ex: "C:\Folder1\Folder2\Folder3" will be 4
FOR Looper = 1 TO SubPathCount 'For every path name part
sBuildPath = sBuildPath & PARSE$(sPathName, "\", Looper) & "\" 'Incremental rebuild of sPathName, Ex: "C:\", "C:\User", "C:\User\Olav", "C:\User\Olav\Favorites"
SHGetFileInfo(BYVAL STRPTR(sBuildPath), 0, FileInfo, LEN(FileInfo), %SHGFI_DISPLAYNAME) 'Get DisplayName for this folder
sDisplayName = sDisplayName & FileInfo.szDisplayName & "\" 'Build a string for DisplayName
NEXT
FUNCTION = sDisplayName 'Let function return result
END FUNCTION
'______________________________________________________________________________
FUNCTION GetPathName(BYVAL sDisplayName AS STRING) AS STRING 'Get path name from localized DisplayName
LOCAL FolderData AS WIN32_FIND_DATA
LOCAL FileInfo AS SHFILEINFO
LOCAL sDriveList AS STRING
LOCAL sDrive AS STRING
LOCAL sBuildPath AS STRING
LOCAL hFile AS DWORD
LOCAL SubPathCount AS LONG
LOCAL ReturnedBytes AS LONG
LOCAL Looper AS LONG
IF ASC(sDisplayName, -1) = 92 THEN 'Is last character is a backslash
sDisplayName = LEFT$(sDisplayName, -1) 'Remove trailing backslash
END IF
SubPathCount = PARSECOUNT(sDisplayName, "\") 'Count the path parts, Ex: "C:\Folder1\Folder2\Folder3" will be 4
IF LEN(sDisplayName) THEN 'Check if we have something
'Doing the drive name part
sDriveList = NUL$(1024) 'Prepare a string big enough to receive drive list
ReturnedBytes = GetLogicalDriveStrings(LEN(sDriveList), BYVAL STRPTR(sDriveList)) 'Multi-string zero
FOR Looper = 1 TO ReturnedBytes \ 4 'Each drive returned is 4 bytes like "C:\" & $NUL
sDrive = PARSE$(sDriveList, $NUL, Looper) 'Like "C:\"
SHGetFileInfo(BYVAL STRPTR(sDrive), 0, FileInfo, LEN(FileInfo), %SHGFI_DISPLAYNAME) 'Get display name for this drive
IF LCASE$(PARSE$(sDisplayName, "\", 1)) = LCASE$(FileInfo.szDisplayName) THEN 'Is this part of sDisplayName equal to the DisplayName of the drive?
sBuildPath = sDrive 'Put drive path name instead of DisplayName, Ex: "C:\" will replace "Windows Seven (C:)"
EXIT FOR 'No need to continue
END IF
NEXT
'Doing the folder name part
IF SubPathCount > 1 THEN 'Verify that there is at least one folder name
FOR Looper = 2 TO SubPathCount 'For every folder
'sFirstFile = sBuildPath & "*" '
'hFile = FindFirstFile(BYVAL STRPTR(sFirstFile), FolderData)
hFile = FindFirstFile(sBuildPath & "*", FolderData) 'Get folder name
IF hFile <> %INVALID_HANDLE_VALUE THEN 'If valid folder name
DO 'Start FindNextFile loop
SHGetFileInfo(sBuildPath & FolderData.cFileName, 0, FileInfo, LEN(FileInfo), %SHGFI_DISPLAYNAME) 'Get DisplayName for this folder
IF LCASE$(PARSE$(sDisplayName, "\", Looper)) = LCASE$(FileInfo.szDisplayName) THEN 'Is this part of sDisplayName equal to the DisplayName of the folder?
sBuildPath = sBuildPath & FolderData.cFileName & "\" 'Build a string with folder name
FindClose(hFile) 'Job is done for this folder
ITERATE FOR 'Do next folder
END IF
LOOP WHILE FindNextFile(hFile, FolderData) 'Get next folder
FindClose(hFile) 'Clean up
END IF
NEXT
END IF
FUNCTION = sBuildPath 'Let function return result
END IF
END FUNCTION
'______________________________________________________________________________
FUNCTION PBMAIN() AS LONG
LOCAL sUserName AS STRING
LOCAL sPath AS STRING
LOCAL sDisplayName AS STRING
LOCAL UserNameLen AS LONG
UserNameLen = %UNLEN
sUserName = NUL$(UserNameLen) 'Init the string so it is big enough
GetUserName(BYVAL STRPTR(sUserName), UserNameLen)'Get Windows logged user name
sUserName = LEFT$(sUserName, UserNameLen - 1) 'Remove last $NUL
sPath = "C:\Users\" & sUserName & "\Favorites\" 'Build a folder name
sDisplayName = GetDisplayName(sPath) 'Get display name
MessageBox(%HWND_DESKTOP, sPath & $CRLF & $CRLF & "Convert path above to DisplayName:" & _
$CRLF & $CRLF & sDisplayName, "PathName to DisplayName", %MB_OK)
sPath = GetPathName(sDisplayName) 'Convert display name to path name
MessageBox(%HWND_DESKTOP, sDisplayName & $CRLF & $CRLF & "Convert DisplayName above to path:" & _
$CRLF & $CRLF & sPath, "DisplayName to PathName", %MB_OK)
END FUNCTION
'______________________________________________________________________________
'
[Added comments and did some minors corrections]
Hi,
Very nice. Looks like I can implement your suggestion. Many thanks!
And yes, there is a SHGetFileinfo under the %TVN_GetDispInfo event. I'll have a closer look at that
one.
--
Regards,
Olav Bergesen