MSelect
asked on
How to get dynamically the Pidl of the current item of a SHBROWSEFORFOLDER list
Hello,
Still working with SHBrowseForFolder with the NEW STYLE flag, it's possible to rename a folder.
Nevertheless, in that case, the BFFM_SELCHANGED message is not sent to the BrowseCallbackProc callback function and, consequently, it's impossible to get the new folder name to display it in a status static control for example.
Therefore, I have subclassed the "SHBROWSEFORFOLDER SHELLNAMESPACE CONTROL" so that I can intercept the WM_NOTIFY messages sent to it by its "SYSTREEVIEW32" child, one of these messages being the name change.
'MODULE
Public NormalProcSHBROWSER&, hWndSHBROWSER&, hWndLIST&
Public Type NMHDR
hwndFrom As Long
idFrom As Long
Code As Long
End Type
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length&)
Function BrowseCallbackProc&(ByVal hwnd&, ByVal Msg&, ByVal lParam&, ByVal lpData&)
Dim Child&, TXT$
On Error Resume Next
Select Case Msg
Case BFFM_INITIALIZED
.....
'Get the hWnd of the SHBROWSEFORFOLDER and SYSTREEVIEW32 windows
Child = GetWindow(hwnd, 5)
Do While Child <> 0
TXT = Space(255): x = GetClassName(Child, TXT, 255): TXT = UCase$(Left$(TXT, x))
if TXT = "SHBROWSEFORFOLDER SHELLNAMESPACE CONTROL" Then
hWndSHBROWSER = Child
Child = GetWindow(hWndSHBROWSER, 5)
Do While Child <> 0
TXT = Space(255): x = GetClassName(Child, TXT, 255): TXT = UCase$(Left$(TXT, x))
If TXT = "SYSTREEVIEW32" Then hWndLIST = Child: Exit Do
Child = GetWindow(Child, 2)
Loop
Exit Do
End if
Child = GetWindow(Child, 2)
Loop
'Subclass SHBROWSEFORFOLDER
NormalProcSHBROWSER = SetWindowLong(hWndSHBROWSE R, -4, AddressOf WinProcSHBROWSER)
Case BFFM_SELCHANGED
GetPathNameText lParam
End Select
End Function
Function GetPathNameText$(pidl&)
Dim x&, TXT$
TXT = Space(260)
x = SHGetPathFromIDListA(pidl, TXT)
If x = 1 Then TXT = Left$(TXT, InStr(TXT, Chr$(0)) - 1)
GetPathNameText = TXT
End Function
Function WinProcSHBROWSER&(ByVal hwnd&, ByVal Msg&, ByVal wParam&, ByVal lParam&)
Dim NM As NMHDR, x&
If Msg = WM_NOTIFY Then
CopyMemory NM, ByVal lParam, Len(NM)
If NM.Code = -460 Then
If NM.hwndFrom = hWndLIST Then
'HERE I KNOW THAT THE NAME OF THE FOLDER displayed in the current item HAS CHANGED.
'I should want to now retrieve the Pidl of the current item of the
' SYSTREEVIEW32 to Call GetPathNameText
'or use it to send a forced BFFM_SELCHANGED notification to the to the BrowseCallbackProc
' function even if the selection has not really changed.
'HOW TO KNOW THE CURRENT Pidl ????????????????????
End If
End If
End If
WinProcSHBROWSER = CallWindowProc(NormalProcS HBROWSER, hwnd, Msg, wParam, lParam)
End Function
Or maybe another solution exist ???
Thank you for your help,
Philippe
Still working with SHBrowseForFolder with the NEW STYLE flag, it's possible to rename a folder.
Nevertheless, in that case, the BFFM_SELCHANGED message is not sent to the BrowseCallbackProc callback function and, consequently, it's impossible to get the new folder name to display it in a status static control for example.
Therefore, I have subclassed the "SHBROWSEFORFOLDER SHELLNAMESPACE CONTROL" so that I can intercept the WM_NOTIFY messages sent to it by its "SYSTREEVIEW32" child, one of these messages being the name change.
'MODULE
Public NormalProcSHBROWSER&, hWndSHBROWSER&, hWndLIST&
Public Type NMHDR
hwndFrom As Long
idFrom As Long
Code As Long
End Type
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length&)
Function BrowseCallbackProc&(ByVal hwnd&, ByVal Msg&, ByVal lParam&, ByVal lpData&)
Dim Child&, TXT$
On Error Resume Next
Select Case Msg
Case BFFM_INITIALIZED
.....
'Get the hWnd of the SHBROWSEFORFOLDER and SYSTREEVIEW32 windows
Child = GetWindow(hwnd, 5)
Do While Child <> 0
TXT = Space(255): x = GetClassName(Child, TXT, 255): TXT = UCase$(Left$(TXT, x))
if TXT = "SHBROWSEFORFOLDER SHELLNAMESPACE CONTROL" Then
hWndSHBROWSER = Child
Child = GetWindow(hWndSHBROWSER, 5)
Do While Child <> 0
TXT = Space(255): x = GetClassName(Child, TXT, 255): TXT = UCase$(Left$(TXT, x))
If TXT = "SYSTREEVIEW32" Then hWndLIST = Child: Exit Do
Child = GetWindow(Child, 2)
Loop
Exit Do
End if
Child = GetWindow(Child, 2)
Loop
'Subclass SHBROWSEFORFOLDER
NormalProcSHBROWSER = SetWindowLong(hWndSHBROWSE
Case BFFM_SELCHANGED
GetPathNameText lParam
End Select
End Function
Function GetPathNameText$(pidl&)
Dim x&, TXT$
TXT = Space(260)
x = SHGetPathFromIDListA(pidl,
If x = 1 Then TXT = Left$(TXT, InStr(TXT, Chr$(0)) - 1)
GetPathNameText = TXT
End Function
Function WinProcSHBROWSER&(ByVal hwnd&, ByVal Msg&, ByVal wParam&, ByVal lParam&)
Dim NM As NMHDR, x&
If Msg = WM_NOTIFY Then
CopyMemory NM, ByVal lParam, Len(NM)
If NM.Code = -460 Then
If NM.hwndFrom = hWndLIST Then
'HERE I KNOW THAT THE NAME OF THE FOLDER displayed in the current item HAS CHANGED.
'I should want to now retrieve the Pidl of the current item of the
' SYSTREEVIEW32 to Call GetPathNameText
'or use it to send a forced BFFM_SELCHANGED notification to the to the BrowseCallbackProc
' function even if the selection has not really changed.
'HOW TO KNOW THE CURRENT Pidl ????????????????????
End If
End If
End If
WinProcSHBROWSER = CallWindowProc(NormalProcS
End Function
Or maybe another solution exist ???
Thank you for your help,
Philippe
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
A small comment : the title of the question should be :
How to get and display dynamically the name of the selected folder in a SystreeView32 control
How to get and display dynamically the name of the selected folder in a SystreeView32 control
ASKER
...but it doesn't work perfectly :
Public Type TVITEM
mask As Long
hItem As Long
state As Long
statemask As Long
Text As String 'other solution is "Text as Long" to be used as pointer
Textmax As Long
iImage As Long
iSelectedimage As Long
cChildren As Long
lParam As Long
End Type
Public Type NMTVDISPINFO
hdr As NMHDR
item As TVITEM
End Type
Const TVN_FIRST = -400
Const TVN_ENDLABELEDIT = TVN_FIRST - 60
Function WinProcSHBROWSER&(ByVal hwnd&, ByVal Msg&, ByVal wParam&, ByVal lParam&)
Dim NM As NMHDR, Buffer as String, DI As NMTVDISPINFO, TV As NMTREEVIEW
If Msg = WM_NOTIFY Then
CopyMemory NM, ByVal lParam, Len(NM)
If NM.Code = TVN_ENDLABELEDIT Then
If NM.hwndFrom = hWndLIST Then
WinProcSHBROWSER = CallWindowProc(NormalProcS
CopyMemory DI, ByVal lParam, Len(DI)
Buffer = DI.item.Text
Exit Function
End If
End If
End If
WinProcSHBROWSER = CallWindowProc(NormalProcS
End Function
Unfortunately, THE STRING GOT IN THE Buffer VARIABLE IS ONLY 1-character long, i.e. "M" instead of "MyFolder" or "S" instead of "Second folder" ...
Same result if TVITEM.Text is declared as Long and then
Buffer = Space(260)
and then call lstrcpy Buffer, DI.item.Text
What's wrong ????
Thank you for your possible help ... though my problem seems to be not really interesting for anybody else :-)
Philippe