Sign in to follow this  
Followers 0
ProgAndy

Shell ListView Demo

9 posts in this topic

I wnated to create a FTP-Client with AutoIt, but I gave up. Now I publish the Listview I created to display the local files:

It can handle opening dirs and go up. Also displays a drive selection and original file icons.

#include <GuiImageList.au3>
#include <GUIListView.au3>

#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>

Global Const $tagSHFILEINFO = "dword hIcon; int iIcon; DWORD dwAttributes; CHAR szDisplayName[255]; CHAR szTypeName[80];"
Global Const $SHGFI_USEFILEATTRIBUTES = 0x10
Global Const $SHGFI_SYSICONINDEX = 0x4000
Global Const $FILE_ATTRIBUTE_NORMAL = 0x80
Global Const $SHGFI_SMALLICON = 0x1
Global Const $SHGFI_LARGEICON = 0x0


Global Const $FOLDER_ICON_INDEX = _GUIImageList_GetFileIconIndex(@SystemDir, 0, 1)
Global Const $NOICON_ICON_INDEX = _GUIImageList_GetFileIconIndex("nb lgl", 0, 0)



Opt("GUIOnEventMode", 1)
#Region ### START Koda GUI section ### Form=D:\Dokumente\Dateien von Andreas\AutoIt3\FTP\GUI_MAIN.kxf
Global $GUI_MAIN = GUICreate("Au3FTP", 882, 586, 193, 125)
GUISetOnEvent(-3,"GUI_Close")

Global $inpLocalDirectory = GUICtrlCreateInput("", 8, 28, 369, 20, $ES_READONLY)
Global $ListView1 = GUICtrlCreateListView("Name|Datum|Größe", 8, 48, 369, 489)

Global $SHELLLISTVIEWHANDLE = GUICtrlGetHandle($ListView1) ; Get the Handle

GUICtrlSendMsg($ListView1, 0x101E, 0, 200)
GUICtrlSendMsg($ListView1, 0x101E, 1, 75)
GUICtrlSendMsg($ListView1, 0x101E, 2, 50)
GUIRegisterMsg($WM_NOTIFY, "_SHLV_WM_NOTIFY")

_GUICtrlListView_SetImageList($ListView1, _GUIImageList_GetSystemImageList(), 1)
Global $DIRECTORY_LOCAL = "" ; Start with Selection of drives :)
_SHLV_PopulateLocalListView($SHELLLISTVIEWHANDLE,$DIRECTORY_LOCAL)


GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###



While 1
    Sleep(100)
WEnd

Func GUI_Close()
    Exit
EndFunc

; Prog@ndy
Func _SHLV_PopulateLocalListView($hListView1,ByRef $DIRECTORY_LOCAL)
    If $DIRECTORY_LOCAL = "" Then
        Local $drives = DriveGetDrive("ALL")
        GUICtrlSetData($inpLocalDirectory, "Drive Selection")
        _GUICtrlListView_BeginUpdate($hListView1)
        _GUICtrlListView_DeleteAllItems($hListView1)
        For $i = 1 To $drives[0]
            _GUICtrlListView_AddItem($hListView1, StringUpper($drives[$i]) & "\", _GUIImageList_GetFileIconIndex($drives[$i] & "\"))
        Next
        _GUICtrlListView_EndUpdate($hListView1)
        Return
    EndIf
    If StringRight($DIRECTORY_LOCAL, 1) <> "\" Then $DIRECTORY_LOCAL &= "\"
    If DriveStatus(StringLeft($DIRECTORY_LOCAL, 3)) <> "READY" Then Return 0 * MsgBox(16 + 8192, 'Error on Drive Access', "Drive " & StringLeft($DIRECTORY_LOCAL, 3) & " not ready!")
    GUICtrlSetData($inpLocalDirectory, $DIRECTORY_LOCAL)
    $files = _SHLV__FileListToArray2($DIRECTORY_LOCAL, "*", 2)
    _GUICtrlListView_BeginUpdate($hListView1)
    _GUICtrlListView_DeleteAllItems($hListView1)
    _GUICtrlListView_SetItemCount($hListView1,$files[0])
    _GUICtrlListView_AddItem($hListView1, "[..]", 1)
    If IsArray($files) Then
        For $i = 1 To $files[0]
            $item = _GUICtrlListView_AddItem($hListView1, $files[$i], $FOLDER_ICON_INDEX)
            _GUICtrlListView_AddSubItem($hListView1, $item, __SHLV_FormatFilesize(DirGetSize($DIRECTORY_LOCAL & $files[$i], 2)), 2)
        Next
    EndIf
    Local $foldercount
    $files = _SHLV__FileListToArray2($DIRECTORY_LOCAL, "*", 1)
    _GUICtrlListView_EndUpdate($hListView1)
    _GUICtrlListView_BeginUpdate($hListView1)
    _GUICtrlListView_SetItemCount($hListView1,$files[0]+$foldercount)
    If IsArray($files) Then
        For $i = 1 To $files[0]
            $item = _GUICtrlListView_AddItem($hListView1, $files[$i], _GUIImageList_GetFileIconIndex($files[$i]))
            _GUICtrlListView_AddSubItem($hListView1, $item, __SHLV_FileDateString2Calc(FileGetTime($DIRECTORY_LOCAL & $files[$i], 0, 1)), 1)
            _GUICtrlListView_AddSubItem($hListView1, $item, __SHLV_FormatFilesize(FileGetSize($DIRECTORY_LOCAL & $files[$i])), 2)
        Next
    EndIf
    _GUICtrlListView_EndUpdate($hListView1)
EndFunc   ;==>_SHLV_PopulateLocalListView

; Prog@ndy
Func __SHLV_FormatFilesize($size)
    Select
        Case $size > 1000
            Return Round($size / 1024, 1) & " KB"
        Case $size > 1048500
            Return Round($size / 1048576, 1) & " MB"
        Case Else
            Return $size & " Byte"
    EndSelect
EndFunc   ;==>_FormatFilesize

; Prog@ndy
Func _GUIImageList_GetSystemImageList($bLargeIcons = False)
    Local $dwFlags, $hIml, $FileInfo = DllStructCreate($tagSHFILEINFO)


    $dwFlags = BitOR($SHGFI_USEFILEATTRIBUTES, $SHGFI_SYSICONINDEX)
    If Not ($bLargeIcons) Then
        $dwFlags = BitOR($dwFlags, $SHGFI_SMALLICON)
    EndIf

;~    '// Load the image list - use an arbitrary file extension for the
;~    '// call to SHGetFileInfo (we don't want to touch the disk, so use
;~    '// FILE_ATTRIBUTE_NORMAL && SHGFI_USEFILEATTRIBUTES).
    $hIml = _WinAPI_SHGetFileInfo(".txt", $FILE_ATTRIBUTE_NORMAL, _
            DllStructGetPtr($FileInfo), DllStructGetSize($FileInfo), $dwFlags)

    Return $hIml
EndFunc   ;==>_GUIImageList_GetSystemImageList

; Prog@ndy
Func _WinAPI_SHGetFileInfo($pszPath, $dwFileAttributes, $psfi, $cbFileInfo, $uFlags)
    Local $return = DllCall("shell32.dll", "DWORD*", "SHGetFileInfo", "str", $pszPath, "DWORD", $dwFileAttributes, "ptr", $psfi, "UINT", $cbFileInfo, "UINT", $uFlags)
    If @error Then Return SetError(@error, 0, 0)
    Return $return[0]
EndFunc   ;==>_WinAPI_SHGetFileInfo

; Prog@ndy
Func _GUIImageList_GetFileIconIndex($sFileSpec, $bLargeIcons = False, $bForceLoadFromDisk = False)
    Local $dwFlags, $FileInfo = DllStructCreate($tagSHFILEINFO)

    $dwFlags = $SHGFI_SYSICONINDEX
    If $bLargeIcons Then
        $dwFlags = BitOR($dwFlags, $SHGFI_LARGEICON)
    Else
        $dwFlags = BitOR($dwFlags, $SHGFI_SMALLICON)
    EndIf
;~ ' We choose whether to access the disk or not. If you don't
;~ ' hit the disk, you may get the wrong icon if the icon is
;~ ' not cached. But the speed is very good!
    If Not $bForceLoadFromDisk Then
        $dwFlags = BitOR($dwFlags, $SHGFI_USEFILEATTRIBUTES)
    EndIf

;~ ' sFileSpec can be any file. You can specify a
;~ ' file that does not exist and still get the
;~ ' icon, for example sFileSpec = "C:\PANTS.DOC"
    Local $lR = _WinAPI_SHGetFileInfo( _
            $sFileSpec, $FILE_ATTRIBUTE_NORMAL, DllStructGetPtr($FileInfo), DllStructGetSize($FileInfo), _
            $dwFlags _
            )

    If ($lR = 0) Then
        Return SetError(1, 0, -1)
    Else
        Return DllStructGetData($FileInfo, "iIcon")
    EndIf
EndFunc   ;==>_GUIImageList_GetFileIconIndex

; Author(s):   Prog@ndy
Func __SHLV_FileDateString2Calc($filedate)
    Return StringRegExpReplace($filedate, "(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", "$1/$2/$3 $4:$5:$6")
EndFunc   ;==>_FileDateString2Calc
; Author(s):   Prog@ndy
Func __SHLV_CalcDate2FileDateString($calcdate)
    Return StringRegExpReplace($calcdate, "(\d{4})/(\d{2})/(\d{2}) (\d{2}):(\d{2}):(\d{2})", "$1$2$3$4$5$6")
EndFunc   ;==>_CalcDate2FileDateString

; Prog@ndy
Func _SHLV_WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo, $hListView1 = $SHELLLISTVIEWHANDLE

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListView1
            Switch $iCode
                Case $NM_DBLCLK ; Sent by a list-view control when the user double-clicks an item with the left mouse button
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
;~                     _DebugPrint("$NM_DBLCLK" & @LF & "--> hWndFrom:" & @TAB & $hWndFrom & @LF & _
;~                             "-->IDFrom:" & @TAB & $iIDFrom & @LF & _
;~                             "-->Code:" & @TAB & $iCode & @LF & _
;~                             "-->Index:" & @TAB & DllStructGetData($tInfo, "Index") & @LF & _
;~                             "-->SubItem:" & @TAB & DllStructGetData($tInfo, "SubItem") & @LF & _
;~                             "-->NewState:" & @TAB & DllStructGetData($tInfo, "NewState") & @LF & _
;~                             "-->OldState:" & @TAB & DllStructGetData($tInfo, "OldState") & @LF & _
;~                             "-->Changed:" & @TAB & DllStructGetData($tInfo, "Changed") & @LF & _
;~                             "-->ActionX:" & @TAB & DllStructGetData($tInfo, "ActionX") & @LF & _
;~                             "-->ActionY:" & @TAB & DllStructGetData($tInfo, "ActionY") & @LF & _
;~                             "-->lParam:" & @TAB & DllStructGetData($tInfo, "lParam") & @LF & _
;~                             "-->KeyFlags:" & @TAB & DllStructGetData($tInfo, "KeyFlags"))
                    ConsoleWrite("lll" & @CRLF)
                    If _GUICtrlListView_GetItemImage($hListView1, DllStructGetData($tInfo, "Index")) = $FOLDER_ICON_INDEX Then
                        $DIRECTORY_LOCAL &= _GUICtrlListView_GetItemText($hListView1, DllStructGetData($tInfo, "Index"))
                        _SHLV_PopulateLocalListView($ListView1,$DIRECTORY_LOCAL)
                    ElseIf StringRegExp(_GUICtrlListView_GetItemText($hListView1, DllStructGetData($tInfo, "Index"), 0), "\A[A-Za-z]:\\\Z") Then
                        $DIRECTORY_LOCAL = _GUICtrlListView_GetItemText($hListView1, DllStructGetData($tInfo, "Index"))
                        _SHLV_PopulateLocalListView($ListView1,$DIRECTORY_LOCAL)
                    ElseIf _GUICtrlListView_GetItemText($hListView1, DllStructGetData($tInfo, "Index")) = "[..]" Then
                        Local $slash = StringInStr($DIRECTORY_LOCAL, "\", 1, -2)
                        If $slash Then
                            $DIRECTORY_LOCAL = StringLeft($DIRECTORY_LOCAL, $slash)
                        ElseIf StringRegExp($DIRECTORY_LOCAL, "\A[A-Za-z]:\\\Z") Then
                            $DIRECTORY_LOCAL = ""
                        EndIf
                        _SHLV_PopulateLocalListView($ListView1,$DIRECTORY_LOCAL)
                    EndIf
                    ; No return value
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

; Author ........: SolidSnake <MetalGX91 at GMail dot com>
; Modified by Prog@ndy
Func _SHLV__FileListToArray2($sPath, $sFilter = "*", $iFlag = 0)
    Local $hSearch, $sFile, $asFileList
    If Not FileExists($sPath) Then Return SetError(1, 1, "")
    If (StringInStr($sFilter, "\")) Or (StringInStr($sFilter, "/")) Or (StringInStr($sFilter, ":")) Or (StringInStr($sFilter, ">")) Or (StringInStr($sFilter, "<")) Or (StringInStr($sFilter, "|")) Or (StringStripWS($sFilter, 8) = "") Then Return SetError(2, 2, "")
    If Not ($iFlag = 0 Or $iFlag = 1 Or $iFlag = 2) Then Return SetError(3, 3, "")
    If (StringMid($sPath, StringLen($sPath), 1) = "\") Then $sPath = StringTrimRight($sPath, 1) ; needed for Win98 for x:\  root dir
    $hSearch = FileFindFirstFile($sPath & "\" & $sFilter)
    If $hSearch = -1 Then Return SetError(4, 4, "")
    While 1
        $sFile = FileFindNextFile($hSearch)
        If @error Then
            SetError(0)
            ExitLoop
        EndIf
        If $iFlag = 1 And StringInStr(FileGetAttrib($sPath & "\" & $sFile), "D") <> 0 Then ContinueLoop
        If $iFlag = 2 And StringInStr(FileGetAttrib($sPath & "\" & $sFile), "D") = 0 Then ContinueLoop
        $asFileList &= $sFile & @CR
;~      ReDim $asFileList[UBound($asFileList) + 1]
;~      $asFileList[0] = $asFileList[0] + 1
;~      $asFileList[UBound($asFileList) - 1] = $sFile
    WEnd
    FileClose($hSearch)
    Return StringSplit(StringTrimRight($asFileList,1),@CR)
EndFunc   ;==>_SHLV__FileListToArray2

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

Hi!

Nice example, but I get an array out-of-bounds error when I try to navigate in my folders.

;)


Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Great example. I too get the error, but only when navigating to certain folders.

CODE
C:\Documents and Settings\bob\My Documents\My Programs\autoit3_2_12\Scripts\PortableFolders\Scripts\examples\filelist.au3 (74) : ==> Subscript used with non-Array variable.:

_GUICtrlListView_SetItemCount($hListView1,$files[0])

_GUICtrlListView_SetItemCount($hListView1,$files^ ERROR

I changed line 71 to

$files = _SHLV__FileListToArray2($DIRECTORY_LOCAL, "*.*", 2)

and put the *.* in line 82 as well.

It seemed to correct the issue.

Also, the list doesn't clear before update so, the new view gets tacked to the bottom of the list. Is this the intended behavior?

Bob

Edited by YellowLab

You can't see a rainbow without first experiencing the rain.

Share this post


Link to post
Share on other sites

Great Example!!

Share this post


Link to post
Share on other sites

i changed all occurances of _GUICtrlListView_DeleteAllItems( to _GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($hListView1)) and it deleted the listview, as expected.


$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])))''Chr("a")&"HI"Next;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)

Share this post


Link to post
Share on other sites

I noticed (well checked to see if it did this) that it doesn't get shortcut icons. Something I've been working on myself. I know I don't have the knowledge to do it right without finding hints in examples. I was close last week but haven't had time to work on it, so I've lost most knowledge of which I gained.


Giggity

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

I noticed (well checked to see if it did this) that it doesn't get shortcut icons. Something I've been working on myself. I know I don't have the knowledge to do it right without finding hints in examples. I was close last week but haven't had time to work on it, so I've lost most knowledge of which I gained.

just change this line
$item = _GUICtrlListView_AddItem($hListView1, $files[$i], _GUIImageList_GetFileIconIndex($files[$i]))

I forgot to use the full path as parameter for the function :)

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

I made a nifty (at least I thought) file browser gui for an unfinished (lets face it, abandoned) project of mine. I'm sure you prob wont use it, but just thought I'd throw it out there for ideas. Warning...it's a bit buggy. :)

filebrowser.au3

Share this post


Link to post
Share on other sites
:) exactly what I was looking for. Thanks a million

Giggity

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0