Jump to content

Drive Space Usage GUI


spudw2k
 Share

Recommended Posts

Just a simple GUI to show where drive space is used (directory sizes).  Yes...I know there are a plethora of tools that do this, but this is an exercise and may be useful in cases where I am not able to use those tools.

Still in it's early stages.  Comments and critiques welcome.

Question to the community.  Is my StringRegExReplace the most efficient way to do what I am doing (filtering out the [byte count] tags)?

Thanks to Yashield for the example of which I tailored my WM_NOTIFY func

GWGRfmT.png

Updates:

7-3-13

modularized some code

working on dynamic loading (got some decent dynamic loading)

7-4-13

Added quick n dirty refresh function (F5 key) - has bugs Implemented workaround...possibly still has bugs

7-10-13

Minor code cleanup/organization

todo:

improve look with ImageList

add check for 0 size folders to verify size or access denied

comments comments comments

finalize refresh function

add context menu

;WM_NOTIFY Example - http://www.autoitscript.com/forum/topic/124493-guictrlcreatetreeview/#entry864647
#include <Array.au3>
#include <File.au3>
#include <GuiTreeView.au3>
#include <GUIConstantsEx.au3>
#include <TreeViewConstants.au3>
#include <WindowsConstants.au3>

Opt("GUIOnEventMode", 1)

Global $busy = 0, $refresh = 0
Const $appTitle = "Drive Space Usage"

$gui = GUICreate($appTitle, 700, 500, -1, -1, BitOR($WS_SIZEBOX, $WS_MAXIMIZEBOX))
$tvFolders = GUICtrlCreateTreeView(4, 4, 688, 466, BitOR($TVS_LINESATROOT, $TVS_HASBUTTONS))
GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)

GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
HotKeySet("{f5}", "_ReCalc")
GUISetState(@SW_SHOW)

WinSetTitle(WinGetTitle($appTitle), "", $appTitle & " - Analyzing")
_GetLocalDrives()
WinSetTitle(WinGetTitle($appTitle), "", $appTitle)

While 1
    Sleep(10)
WEnd

Func _Exit()
    Exit
EndFunc   ;==>_Exit

Func _CalcFolderSize()
    If $busy Then Return 0
    $item = _GUICtrlTreeView_FindItem($tvFolders, "Pending", True)

    If Not $item Then
        $refresh = 0
        $busy = 0
        AdlibUnRegister()
        WinSetTitle(WinGetTitle($appTitle), "", $appTitle)
        Return 0
    Else
        $busy = 1
        $text = _GUICtrlTreeView_GetText($tvFolders, $item)
        WinSetTitle(WinGetTitle($appTitle), "", $appTitle & " - Analyzing " & _TreePath($tvFolders, $item))
        $text = StringReplace($text, "Pending", "Analyzing")
        _GUICtrlTreeView_SetText($tvFolders, $item, $text)
        $path = _TreePath($tvFolders, $item)
        $dirSize = _GetDirSize($path)
        $item = _GUICtrlTreeView_FindItem($tvFolders, $text)
        $subFolders = _FileListToArray($path, "*", 2)
        If UBound($subFolders) And Not $refresh Then _GUICtrlTreeView_AddChild($tvFolders, $item, "~")
        _GUICtrlTreeView_BeginUpdate($tvFolders)
        $text = StringReplace($text, "Analyzing", $dirSize)
        _GUICtrlTreeView_SetText($tvFolders, $item, $text)
        _GUICtrlTreeView_EndUpdate($tvFolders)

        $busy = 0
    EndIf
EndFunc   ;==>_CalcFolderSize

Func _FriendlySizeNotation($bytes, $mbMode = 0) ;Convert bytes into human readable format
    If Not $mbMode Then $bytes = $bytes / 1024 / 1024
    If $bytes >= 1024 Then
        $bytes /= 1024
        $bytes = Round($bytes, 2) & " GB"
    Else
        $bytes = Round($bytes, 2) & " MB"
    EndIf
    Return $bytes
EndFunc   ;==>_FriendlySizeNotation

Func _GetDirSize($dir)
    $dirSize = DirGetSize($dir)
    If Not $dirSize Then
        If Not _Touch($dir) Then
            $dirSize = "Access Denied"
        Else
            $dirSize = "0 MB"
        EndIf
    Else
        $dirSize = _FriendlySizeNotation($dirSize)
    EndIf
    Return $dirSize
EndFunc   ;==>_GetDirSize

Func _GetLocalDrives()
    Local $x
    $arrDrives = DriveGetDrive("ALL")
    For $x = 1 To $arrDrives[0]
        $driveSpaceTotal = DriveSpaceTotal($arrDrives[$x])
        If $driveSpaceTotal Then
            WinSetTitle(WinGetTitle($appTitle), "", $appTitle & " - Analyzing " & StringUpper($arrDrives[$x]))
            $driveSpaceFree = DriveSpaceFree($arrDrives[$x])
            $driveSpaceTotal = _FriendlySizeNotation($driveSpaceTotal, 1)
            $driveSpaceFree = _FriendlySizeNotation($driveSpaceFree, 1)
            $subFolders = _FileListToArray($arrDrives[$x], "*", 2)
            $arrDrives[$x] = StringUpper($arrDrives[$x]) & " [" & $driveSpaceTotal & " Total | " & $driveSpaceFree & " Free]"
            _GUICtrlTreeView_BeginUpdate($tvFolders)
            $root = _GUICtrlTreeView_Add($tvFolders, 0, $arrDrives[$x])
            If UBound($subFolders) Then _GUICtrlTreeView_AddChild($tvFolders, $root, "~")
            _GUICtrlTreeView_EndUpdate($tvFolders)
        EndIf
    Next
    Return 0
EndFunc   ;==>_GetLocalDrives

Func _GetSubFolders(ByRef $treeviewitem)
    Local $x
    $path = _TreePath($tvFolders, $treeviewitem)
    $arrFolders = _FileListToArray($path, "*", 2)
    If Not UBound($arrFolders) Then Return 0
    For $x = 1 To $arrFolders[0]
        _GUICtrlTreeView_AddChild($tvFolders, $treeviewitem, $arrFolders[$x] & " [Pending]")
    Next
EndFunc   ;==>_GetSubFolders

Func _ReCalc()
    If $busy Then Return 0
    $busy = 1
    $item = 0
    Do
        $item = _GUICtrlTreeView_FindItem($tvFolders, "B]", True)
        If $item Then _GUICtrlTreeView_SetText($tvFolders, $item, StringRegExpReplace(_GUICtrlTreeView_GetText($tvFolders, $item), " \[.*", "") & " [Pending]")
    Until $item = 0
    $busy = 0
    $refresh = 1
    AdlibRegister("_CalcFolderSize", 100)
EndFunc   ;==>_ReCalc

Func _Touch($path, $file = "touch.txt")
    $file = $path & "\" & $file
    $touch = FileOpen($file, 1)
    If $touch Then
        FileClose($touch)
        Return FileDelete($file)
    EndIf
    Return 0
EndFunc   ;==>_Touch

Func _TreePath(ByRef $hWnd, $item) ;Determine full path of selected item in TreeView
    $txt = StringRegExpReplace(_GUICtrlTreeView_GetText($hWnd, $item), " \[.*", "")
    Do
        $parent = _GUICtrlTreeView_GetParentHandle($hWnd, $item)
        If $parent > 0 Then
            $txt = StringRegExpReplace(_GUICtrlTreeView_GetText($hWnd, $parent), " \[.*", "") & "\" & $txt
            $item = $parent
        EndIf
    Until $parent = 0
    Return $txt
EndFunc   ;==>_TreePath

Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMTREEVIEW = DllStructCreate($tagNMTREEVIEW, $lParam)
    Local $hItem = DllStructGetData($tNMTREEVIEW, 'NewhItem')
    Local $iState = DllStructGetData($tNMTREEVIEW, 'NewState')
    Local $hTV = DllStructGetData($tNMTREEVIEW, 'hWndFrom')
    Local $ID = DllStructGetData($tNMTREEVIEW, 'Code')

    Switch $hTV
        Case GUICtrlGetHandle($tvFolders)
            Switch $ID
                Case $TVN_ITEMEXPANDEDW
                    If Not BitAND($iState, $TVIS_EXPANDED) Then

                    Else
                        _GUICtrlTreeView_SelectItem($hTV, $hItem)
                        $child = _GUICtrlTreeView_GetFirstChild($hTV, $hItem)
                        If _GUICtrlTreeView_GetText($hTV, $child) = "~" Then
                            $busy = 1
                            _GUICtrlTreeView_BeginUpdate($tvFolders)
                            _GUICtrlTreeView_Delete($hTV, $child)
                            _GUICtrlTreeView_EndUpdate($tvFolders)
                            _GetSubFolders($hItem)
                            $busy = 0
                            AdlibRegister("_CalcFolderSize", 10)
                        EndIf
                    EndIf
                    ;Case $TVN_SELCHANGEDW

            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_NOTIFY
Edited by spudw2k
Link to comment
Share on other sites

@spudw2k

Nice and simple, but usefull.

Some suggestions :

- Add a refresh button and or context menu

- Add an Export Function

- Add some Icons

- Add a button and or context menu to collapse / expand - folders / sub folders

Just some thoughts :)

 

 

Link to comment
Share on other sites

Thanks ptrex; ideas welcome.  I was thinking of incorporating a few of those features (icons, content menu) but I dig the Export idea.  I also didn't think about a refresh button before, but that would be very cool.  Thinking about performance, do you think a refresh of say only the the folders that are visible (expanded) are refreshed or do you think and entire refresh off all the inspected folders?  Perhaps a "re-scan" of all inspected folders wouldn't be too bad.  I'm fairly pleased with how I came up with the mechanism to continue calculating folder sizes with Adlib because I never thought about it the way I coded it before.

 

edit:

I found a potential flaw.  I am using the [] chars to display the folder size info, but I just realized that those are valid characters for a foldername.  The way my regex is coded it will not work (calculate) with a folder that has a [ in the name.  Looking into another char I can use, but I really liked the look of the brackets. :( I don't recall ever seeing a foldername with those chars in it, but just the fact that it "could" happen bugs me

Edited by spudw2k
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...