Browse for Folder: Difference between revisions
From NSIS Wiki
Jump to navigationJump to search
mNo edit summary |
mNo edit summary |
||
Line 61: | Line 61: | ||
StrCpy $2 0 | StrCpy $2 0 | ||
StrCpy $3 0 | StrCpy $3 0 | ||
loop: ; BFFM_SETSELECTION is buggy and does scroll to the new item so we find the treeview and do it manually | loop: ; BFFM_SETSELECTION is buggy and does not scroll to the new item so we find the treeview and do it manually | ||
FindWindow $2 "" "" $R1 $2 ; Assuming SysTreeView32 is a grandchild when using BIF_NEWDIALOGSTYLE | FindWindow $2 "" "" $R1 $2 ; Assuming SysTreeView32 is a grandchild when using BIF_NEWDIALOGSTYLE | ||
IntCmp 0 $2 done | IntCmp 0 $2 done |
Revision as of 14:05, 15 September 2016
Author: Anders (talk, contrib) |
This function displays the folder browser UI so the user can choose a file-system folder. You can specify a root folder or use "" for the default root (deskop). You can also set the initial selection if desired.
Code
!include LogicLib.nsh !include WinMessages.nsh ; WM_USER !define TV_FIRST 0x1100 !define /math TVM_GETNEXTITEM ${TV_FIRST} + 10 !define /math TVM_SELECTITEM ${TV_FIRST} + 11 !define /math TVM_ENSUREVISIBLE ${TV_FIRST} + 20 !define TVGN_FIRSTVISIBLE 0x5 !define TVGN_CARET 0x9 !define BFFM_INITIALIZED 1 !if "${NSIS_CHAR_SIZE}" > 1 !define /math BFFM_SETSELECTION ${WM_USER} + 103 !else !define /math BFFM_SETSELECTION ${WM_USER} + 102 !endif Function SHParseDisplayName ; NSIS 2.51+ INPUT:Path OUTPUT:Pidl Exch $1 Push $2 System::Call 'SHELL32::SHParseDisplayName(w r1, p 0, *p 0r2, i 0, *i 0)i' ${If} $2 P= 0 System::Call 'SHELL32::ILCreateFromPath(t r1)p.r2' ; SHParseDisplayName is XP+, this works everywhere but is not as clever ${EndIf} StrCpy $1 $2 Pop $2 Exch $1 FunctionEnd Function BrowseForFolder ; NSIS 2.51+ INPUT:RootPath, HeadingText, InitialPathSelection OUTPUT:Path System::Store S Pop $3 ; InitialPathSelection or "" Pop $2 ; HeadingText Pop $1 ; RootPath or "" !macro BrowseForFolder_PathToPidl Path Pidl StrCpy ${Pidl} "" ${If} "${Path}" != "" Push "${Path}" Call SHParseDisplayName Pop ${Pidl} ${EndIf} !macroend !insertmacro BrowseForFolder_PathToPidl $1 $6 !insertmacro BrowseForFolder_PathToPidl $3 $5 System::Get "(p.R1, i.R2, p, p.R3)i R8R8" ; BFFCALLBACK Pop $R9 System::Call '*(&t261 "")p.r7' ; pszDisplayName buffer System::Call '*(p $hwndparent, pr6, pr7, t r2, i 0x41, kR9, pr5, i)p.r8' ; BROWSEINFO struct System::Call 'SHELL32::SHBrowseForFolder(t)(pr8)p.r9' ; Using the (t) hack to force the correct A/W function BFFCALLBACK_loop: StrCmp $R8 "callback1" 0 BFFCALLBACK_done ${If} $R2 = ${BFFM_INITIALIZED} ${AndIf} $R3 P<> 0 SendMessage $R1 ${BFFM_SETSELECTION} 0 $R3 System::Store S StrCpy $2 0 StrCpy $3 0 loop: ; BFFM_SETSELECTION is buggy and does not scroll to the new item so we find the treeview and do it manually FindWindow $2 "" "" $R1 $2 ; Assuming SysTreeView32 is a grandchild when using BIF_NEWDIALOGSTYLE IntCmp 0 $2 done FindWindow $3 "SysTreeView32" "" $2 IntCmp 0 $3 loop SendMessage $3 ${TVM_GETNEXTITEM} ${TVGN_CARET} 0 $4 IntCmp 0 $3 done System::Call 'USER32::PostMessage(p$3,i${TVM_ENSUREVISIBLE},p0,p$4)' done: System::Store L ${EndIf} StrCpy $R8 0 ; Yep, the return value is in the same place as the callback id System::Call $R9 goto BFFCALLBACK_loop BFFCALLBACK_done: System::Free $R9 ${If} $9 Z<> 0 System::Call 'SHELL32::SHGetPathFromIDList(p r9, t.s)i' System::Call 'OLE32::CoTaskMemFree(p r9)' ${Else} Push "" ; Error/cancel, return empty string ${EndIf} System::Call 'OLE32::CoTaskMemFree(p r5)' System::Call 'OLE32::CoTaskMemFree(p r6)' System::Free $7 System::Free $8 System::Store L FunctionEnd
Example
Section Push "$Profile" Push "Hello World" Push "$AppData" Call BrowseForFolder Pop $0 DetailPrint BrowseForFolder=$0 SectionEnd