Link to home
Start Free TrialLog in
Avatar of MSelect
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(hWndSHBROWSER, -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(NormalProcSHBROWSER, hwnd, Msg, wParam, lParam)
   
End Function

Or maybe another solution exist ???
Thank you for your help,
Philippe
Avatar of MSelect
MSelect

ASKER

I have rewritten the WinProcSHBROWSER function ... not to get the PiDl but directly the new edited text
...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(NormalProcSHBROWSER, hwnd, Msg, wParam, lParam)
                CopyMemory DI, ByVal lParam, Len(DI)
                Buffer = DI.item.Text
                Exit Function
            End If
        End If
    End If
    WinProcSHBROWSER = CallWindowProc(NormalProcSHBROWSER, hwnd, Msg, wParam, lParam)
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
ASKER CERTIFIED SOLUTION
Avatar of MSelect
MSelect

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of MSelect

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