Jump to content

Another desktop positions restore script


Recommended Posts

Posted Image

Posted Image

Background

My desktop icons shift around often when I extend my screen or connect a higher resolution monitor to my laptop, or when a game crashes in an awkward resolution.

Recently I've not been having very much luck with programs and scripts that save desktop icon positions. I know there are various examples on this forum - but I've been frustrated by them as well as other options (eg: an outdated layout.dll shell extension)

For the record, I use Windows 7 64-bit ; I haven't tested this on anything else, but that was probably part of the problem. From some research it appears desktop positions can be saved in one of several different registry keys; older programs may not be searching for them all.

So, I decided to write my own crappy program that *did* search multiple locations for position settings.

TL;DR

Made a program to save desktop icon positions; checks for multiple settings before attempting.

Sauce

Anyway, here's my badly-informed bug-ridden spaghetti code that does what I need:

Note: See slightly cleaned-up code in a reply below!

#RequireAdmin
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <Array.au3>
Global $results[11];elements are array[5]= 0:$display_name 1:$bag_key 2:$bag 3:$valueName 4:$valueDisplayName
Global $ctrls[11][5]

Global $selected = Int(IniRead("itempos.ini", "settings", "selected", -1))
Global $uiOps = GUICreate("Desktop Position Options", 350 + 20, 100)
Global $txSel = GUICtrlCreateInput("Not Selected", 0, 0, 350, 20, $ES_READONLY)
Global $btSel = GUICtrlCreateButton("...", 350, 0, 20, 20)
Global $btSav = GUICtrlCreateButton("Save", 0, 20, 350 + 20, 40)
Global $btRes = GUICtrlCreateButton("Restore", 0, 60, 350 + 20, 40)
uiResetOptions()
Global $uiSel, $btRef
Local $hadSettings = load()
uiPopulate($results, $ctrls, $uiSel, $btRef, (Not $hadSettings));refresh if didn't cache settings
GUISetState(@SW_SHOW, $uiOps)
If (Not $hadSettings) Or $selected < 1 Then
    GUISetState(@SW_SHOW, $uiSel)
    WinActivate($uiSel)
Else
    GUISetState(@SW_HIDE, $uiSel)
    WinActivate($uiOps)
EndIf
;------------------------------------



While 1
    $amsg = GUIGetMsg(1)
    $msg = $amsg[0]
    Switch $msg
        Case $GUI_EVENT_CLOSE
            If $amsg[1] = $uiOps Then Quit()
            GUISetState(@SW_HIDE, $uiSel)
            WinActivate($uiOps)
        Case $btRef
            uiPopulate($results, $ctrls, $uiSel, $btRef)
            ContinueCase
        Case $btSel
            GUISetState(@SW_SHOW, $uiSel)
            WinActivate($uiSel)
        Case $btSav
            save()
            uiResetOptions()
        Case $btRes
            restore()
            uiResetOptions()
        Case $ctrls[0][0]
            MsgBox(0, "Position Information Locations", "This window lists system icon position settings" & @CRLF & "This selection may help if restoring settings does not work. If you do not know what to select, try `Current User`.  ")
    EndSwitch
    For $n = 1 To 10
        If $msg = $ctrls[$n][0] And $ctrls[$n][0] <> 0 Then
            uiSelect($n)
            ExitLoop
        EndIf
    Next
WEnd


;------------------------

Func load()
    Global $selected
    Global $results

    Local $hadSettings = False
    For $i = 0 To 10
        Local $entry[5]
        If IniRead("itempos.ini", "cache", $i, "") = "array" Then
            For $j = 0 To 4
                $entry[$j] = IniRead("itempos.ini", "cache", $i & '_' & $j, "")
            Next
            $results[$i] = $entry
            $hadSettings = True
        Else
            $results[$i] = IniRead("itempos.ini", "cache", $i, "")
        EndIf
    Next

    Local $n = Int(IniRead("itempos.ini", "settings", "selected", -1))
    If Not $hadSettings Then $n = -1
    uiSelect($n)

    Return $hadSettings
EndFunc   ;==>load

Func Quit()
    IniWrite("itempos.ini", "settings", "selected", $selected)
    For $i = 0 To 10
        Local $entry = $results[$i]
        If IsArray($entry) Then
            IniWrite("itempos.ini", "cache", $i, "array")
            For $j = 0 To 4
                IniWrite("itempos.ini", "cache", $i & '_' & $j, $entry[$j])
            Next
        Else
            IniWrite("itempos.ini", "cache", $i, $entry)
        EndIf
    Next
    Exit
EndFunc   ;==>quit


Func uiResetOptions()
    If $selected > 0 Then
        GUICtrlSetState($btSav, $GUI_ENABLE)
        If isSaved() Then
            GUICtrlSetState($btRes, $GUI_ENABLE)
        Else
            GUICtrlSetState($btRes, $GUI_DISABLE)
        EndIf
    Else
        GUICtrlSetState($btSav, $GUI_DISABLE)
        GUICtrlSetState($btRes, $GUI_DISABLE)
    EndIf
EndFunc   ;==>uiResetOptions

Func isSaved()
    Local $entry = $results[$selected]
    If Not IsArray($entry) Then Return False
    Return StringLen(IniRead("itempos.ini", safename($entry[0] & '-' & $entry[2] & '-' & $entry[4]), safename($entry[3]), "")) > 0
EndFunc   ;==>isSaved


Func save()
    GUICtrlSetState($btSav, $GUI_DISABLE)
    GUICtrlSetState($btRes, $GUI_DISABLE)
    WinActivate("Program Manager")
    Sleep(250)
    Send("{F5}")
    Sleep(1000)
    WinActivate($uiOps)

    Local $entry = $results[$selected]
    Local $nameSafe = safename($entry[0] & '-' & $entry[2] & '-' & $entry[4])
    Local $bag_key = $entry[1]
    Local $valueName = $entry[3]
    Local $valueNameSafe = safename($valueName)
    Local $value = RegRead($bag_key, $valueName)
    ConsoleWrite("Saving to " & $nameSafe & @CRLF)

    IniWrite("itempos.ini", $nameSafe, $valueNameSafe, $value)
EndFunc   ;==>save

Func restore()
    Local $entry = $results[$selected]
    Local $nameSafe = safename($entry[0] & '-' & $entry[2] & '-' & $entry[4])
    Local $bag_key = $entry[1]
    Local $valueName = $entry[3]
    Local $valueNameSafe = safename($valueName)
    Local $value = IniRead("itempos.ini", $nameSafe, $valueNameSafe, "")
    ConsoleWrite("Restoring from " & $nameSafe & @CRLF)

    If StringLen($value) = 0 Then Return MsgBox(0, 'Restore Error', "No data is available for this entry to be restored.")

    ProcessKill('explorer.exe')
    ProcessWaitClose('explorer.exe')
    RegWrite($bag_key, $valueName, "REG_BINARY", Binary($value))
    Run('explorer.exe')
EndFunc   ;==>restore

;--------------------------------------------------

Func uiSelect($n)
    Global $selected
    Global $results
    $selected = $n

    Local $entry = ""
    If $selected > 0 Then $entry = $results[$n]

    If IsArray($entry) Then
        GUICtrlSetData($txSel, $entry[0] & '-' & $entry[2] & '-' & $entry[4])
        If IsHWnd($uiSel) Then GUISetState(@SW_HIDE, $uiSel)
        WinActivate($uiOps)
        uiResetOptions()
        Return True
    Else
        GUICtrlSetData($txSel, "Nothing Selected")
        uiResetOptions()
        If IsHWnd($uiSel) Then GUISetState(@SW_SHOW, $uiSel)
        WinActivate($uiSel)
    EndIf
    Return False
EndFunc   ;==>uiSelect

Func uiPopulate(ByRef $results, ByRef $ctrls, ByRef $ui, ByRef $button, $doRefresh = True)
    ;results and ctrls must have the same UBound.
    ProgressOn("Refreshing...", "Refreshing...")
    ProgressSet(1, "Cleaning up...")
    Sleep(250)

    Local $x = UBound($ctrls) - 1

    GUISwitch($ui)
    GUICtrlDelete($button)
    For $n = 0 To $x
        For $i = 0 To 3
            If $ctrls[$n][$i] Then GUICtrlDelete($ctrls[$n][$i])
        Next
    Next
    If IsHWnd($ui) Then GUIDelete($ui)

    If $doRefresh Then
        For $i = 0 To UBound($results) - 1
            $results[$i] = ''
        Next
        ProgressSet(5, "Finding folder information sources...")
        searchhive($results)
    EndIf
    ProgressSet(95, "Creating User Interface...")
    Sleep(250)


    Local $count = 0
    For $n = 1 To $x
        Local $y = ($n - 1) * 20
        If IsArray($results[$n]) Then $count += 1
    Next

    $ui = GUICreate("Select system setting to use...", 450, 20 * ($count + 2) + 10)
    $ctrls[0][0] = GUICtrlCreateButton("??", 0, 0, 20, 20)
    $ctrls[0][1] = GUICtrlCreateLabel("Profile", 020, 5, 250, 20)
    $ctrls[0][2] = GUICtrlCreateLabel("Bag", 270, 5, 050, 20)
    $ctrls[0][3] = GUICtrlCreateLabel("ItemPos", 320, 5, 150, 20)
    $ctrls[0][4] = GUICtrlCreateLabel("-----------------------------------", 0, 20, 450, 5, $SS_ETCHEDHORZ)


    $count = 0
    For $n = 1 To $x
        Local $y = $n * 20 + 5
        Local $entry = $results[$n]
        If IsArray($entry) Then
            $count += 1
            $ctrls[$n][0] = GUICtrlCreateButton($count & '.', 0, $y, 20, 20)
            $y += 5
            $ctrls[$n][1] = GUICtrlCreateLabel($entry[0], 020, $y, 250, 20)
            $ctrls[$n][2] = GUICtrlCreateLabel($entry[2], 270, $y, 050, 20)
            $ctrls[$n][3] = GUICtrlCreateLabel($entry[4], 320, $y, 150, 20)
        EndIf
    Next
    $ctrls[$x][4] = GUICtrlCreateButton("Refresh", 0, 20 * ($count + 1) + 10, 450, 20)
    $button = $ctrls[$x][4]
    GUISwitch($ui)

    ProgressSet(100, "Showing off...")
    Sleep(250)
    ProgressOff()
    Return $ui
EndFunc   ;==>uiPopulate
;--------------------------------------------------------------------
Func searchhive(ByRef $results)
    ;ConsoleWrite('Current'&@CRLF)
    ProgressInitial(5)
    searchuser($results, 'HKEY_CURRENT_USER', 'Current User')
    ProgressSet(25)
    For $i = 1 To 9999
        Local $u = RegEnumKey("HKEY_USERS\", $i)
        If @error <> 0 Then ExitLoop
        ;ConsoleWrite($u&@CRLF)
        searchuser($results, "HKEY_USERS\" & $u, $u)
        ProgressSet(25 + $i * 10)
    Next
EndFunc   ;==>searchhive
Func searchuser(ByRef $results, $user_key, $display_name)
    Local $software_key[2] = ["Software\Microsoft\Windows", "Software\Classes\Local Settings\Software\Microsoft\Windows"]
    Local $shell_key[2] = ["Shell", "ShellNoRoam"]
    Local $name_suffix

    For $sw In $software_key
        $name_suffix = ""
        If StringInStr($sw, "Local") Then $name_suffix = "L"
        For $shell In $shell_key
            If StringInStr($shell, "NoRoam") Then $name_suffix &= "NR"
            Local $bags_key = $user_key & "\" & $sw & "\" & $shell & "\Bags"
            For $i = 1 To 9999
                ProgressIncrement(0.01)
                Local $bag = RegEnumKey($bags_key, $i)
                If @error <> 0 Then ExitLoop
                If StringLen($name_suffix) > 0 Then $name_suffix = "(" & $name_suffix & ")"
                searchbag($results, $bags_key, $bag, $display_name & $name_suffix)
            Next
        Next
    Next
EndFunc   ;==>searchuser
Func searchbag(ByRef $results, $bags_key, $bag, $display_name)
    Local $bag_key = $bags_key & '\' & $bag & '\Shell'
    For $i = 1 To 9999
        Local $value = RegEnumVal($bag_key, $i)
        If @error <> 0 Then ExitLoop
        If StringInStr($value, 'ItemPos') Then
            Local $entry[5] = [$display_name, $bag_key, $bag, $value, StringTrimLeft($value, 7)]
            _Array_Fixed_Push($results, $entry)
        EndIf
    Next
    $bag_key = $bags_key & '\' & $bag & '\Desktop'
    For $i = 1 To 9999
        Local $value = RegEnumVal($bag_key, $i)
        If @error <> 0 Then ExitLoop
        ;ConsoleWrite($value&@CRLF)
        If StringInStr($value, 'ItemPos') Then
            Local $entry[5] = [$display_name, $bag_key, $bag, $value, StringTrimLeft($value, 7)]
            _Array_Fixed_Push($results, $entry)
        EndIf
    Next
EndFunc   ;==>searchbag
Func _Array_Fixed_Push(ByRef $array, $value);adds an item, overwriting the oldest item | NOTE: Edited from original intent, see comments
    Local $x = UBound($array) - 1
    If $array[0] = $x Then Return False; *** decided later that overwriting sucked for systems with many profiles.
    Local $i = Mod($array[0], $x); values from 0 to x-1
    Local $n = $i + 1;(0 to x-1)+1 = 1 to x
    $array[0] = $n; this is also the nonadjusted index for the next item :)
    $array[$n] = $value
EndFunc   ;==>_Array_Fixed_Push


Func ProgressInitial($n = 0)
    Global $ProgressIncrement
    $ProgressIncrement = $n
    ProgressSet($n)
EndFunc   ;==>ProgressInitial
Func ProgressIncrement($n = 1)
    Global $ProgressIncrement
    $ProgressIncrement += $n
    ProgressSet($ProgressIncrement)
EndFunc   ;==>ProgressIncrement

Func safename($s)
    Return StringRegExpReplace($s, "[^a-zA-Z0-9_\-]", "_")
EndFunc   ;==>safename


Func ProcessKill($p); I should probably credit someone for this function
    $Kernel32 = DllOpen("kernel32.dll")
    $hproc = DllCall($Kernel32, 'int', 'OpenProcess', 'int', 0x1F0FFF, 'int', True, 'int', ProcessExists($p))
    DllCall($Kernel32, "int", "TerminateProcess", "int", $hproc[0], "dword", 1)
    DllClose($Kernel32)
EndFunc   ;==>ProcessKill

Other Notes

This only scans for settings/prompts you on the first run, it should keep that information for the next run. It also limits you to using one of the first 10 profiles the scan results in.

Sorry about having to kill/restart explorer when restoring positions - nothing else worked for me.

Clarification for the ItemPos text: from what I've read, it is <Resolution>(<Monitor>). I'm unsure how settings behave when you have icons dragged from one screen to the next and restore one of the screens.

Edited by crashdemons

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Link to comment
Share on other sites

Here is a ZIP for the compiled executables (x86 and x64). DesktopPos.zip

Note: I encountered issues trying to run the script or compiled versions as x86 under a 64-bit platform - please choose executable and interpreter platform appropriately.

Specifically, launching explorer with Run() does not seem to have the desired effect from a 32-bit executable ran on a 64-bit OS. There could be Registry differences also that effect this program's function.

Edited by crashdemons

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Link to comment
Share on other sites

Did some spring-cleaning on the source code:

#RequireAdmin
#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_AU3Check_Stop_OnWarning=y
#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <Array.au3>


Global Enum $UIO_HWND = 0, $UIO_TEXT, $UIO_SELECT, $UIO_SAVE, $UIO_RESTORE
Global Enum $UIS_HWND = 0, $UIS_HELP, $UIS_REFRESH = 6, $UIS_DYNAMIC = 7, $UIS_DYNCTRLS = 4, $UIS_DYNBUTTONMOD = Mod($UIS_DYNAMIC, $UIS_DYNCTRLS)


Global $ProgressIncrement

Global $bag_entries[11];elements are array[5]= 0:$display_name 1:$bag_key 2:$bag 3:$valueName 4:$valueDisplayName
Global $selected = -1


Global $uiInfo_Ops = uiCreateOptions()
uiOptions_Reset($bag_entries, $selected, $uiInfo_Ops)
Global $uiInfo_Sel[60]
Global $hadSettings = load($uiInfo_Ops, $uiInfo_Sel, $selected, $bag_entries)
uiSelector_Populate($uiInfo_Sel, $bag_entries, Not $hadSettings);refresh if didn't cache settings


GUISetState(@SW_SHOW, $uiInfo_Ops[$UIO_HWND])
If (Not $hadSettings) Or $selected < 1 Then
    GUISetState(@SW_SHOW, $uiInfo_Sel[$UIS_HWND])
    WinActivate($uiInfo_Sel[$UIS_HWND])
Else
    GUISetState(@SW_HIDE, $uiInfo_Sel[$UIS_HWND])
    WinActivate($uiInfo_Ops[$UIO_HWND])
EndIf


;------------------------------------


Global $amsg, $msg
While 1
    $amsg = GUIGetMsg(1)
    Switch $amsg[0]
        Case $GUI_EVENT_CLOSE
            If $amsg[1] = $uiInfo_Ops[$UIO_HWND] Then Quit($selected, $bag_entries)
            GUISetState(@SW_HIDE, $uiInfo_Sel[$UIS_HWND])
            WinActivate($uiInfo_Ops[$UIO_HWND])
        Case $uiInfo_Sel[$UIS_REFRESH]
            uiSelector_Populate($uiInfo_Sel, $bag_entries)
            ContinueCase
        Case $uiInfo_Ops[$UIO_SELECT]
            GUISetState(@SW_SHOW, $uiInfo_Sel[$UIS_HWND])
            WinActivate($uiInfo_Sel[$UIS_HWND])
        Case $uiInfo_Ops[$UIO_SAVE]
            uiOptions_Save($uiInfo_Ops, $bag_entries, $selected)
            uiOptions_Reset($bag_entries, $selected, $uiInfo_Ops)
        Case $uiInfo_Ops[$UIO_RESTORE]
            uiOptions_Restore($uiInfo_Ops, $bag_entries, $selected)
            uiOptions_Reset($bag_entries, $selected, $uiInfo_Ops)
        Case $uiInfo_Sel[$UIS_HELP]
            MsgBox(0, "Position Information Locations", "This window lists system icon position settings" & @CRLF & "This selection may help if restoring settings does not work. If you do not know what to select, try `Current User`.  ")
    EndSwitch
    For $i = $UIS_DYNAMIC To UBound($uiInfo_Sel) - 1
        If $amsg[0] = $uiInfo_Sel[$i] And $uiInfo_Sel[$i] <> 0 And Mod($i, $UIS_DYNCTRLS) = $UIS_DYNBUTTONMOD Then
            uiSelector_Submit(Int(GUICtrlRead($uiInfo_Sel[$i])), $uiInfo_Ops, $uiInfo_Sel, $selected, $bag_entries); the displayed count number will also be the 1-based index of the item, since they're inserted sequentially without gaps.
            ExitLoop
        EndIf
    Next
WEnd


;------------------------

Func load(ByRef $uiInfo_Options, ByRef $uiInfo_Selector, ByRef $iSelected_out, ByRef $bags)

    Local $hadSettings = False
    For $i = 0 To UBound($bags)-1
        Local $entry[5]
        If IniRead("itempos.ini", "cache", $i, "") = "array" Then
            For $j = 0 To 4
                $entry[$j] = IniRead("itempos.ini", "cache", $i & '_' & $j, "")
            Next
            $bags[$i] = $entry
            $hadSettings = True
        Else
            $bags[$i] = IniRead("itempos.ini", "cache", $i, "")
        EndIf
    Next

    Local $n = Int(IniRead("itempos.ini", "settings", "selected", -1))
    If Not $hadSettings Then $n = -1
    uiSelector_Submit($n, $uiInfo_Options, $uiInfo_Selector, $iSelected_out, $bags)

    Return $hadSettings
EndFunc   ;==>load

Func Quit(ByRef $iSelected_in, ByRef $bags_in)
    IniWrite("itempos.ini", "settings", "selected", $iSelected_in)
    For $i = 0 To UBound($bags_in)-1
        Local $entry = $bags_in[$i]
        If IsArray($entry) Then
            IniWrite("itempos.ini", "cache", $i, "array")
            For $j = 0 To 4
                IniWrite("itempos.ini", "cache", $i & '_' & $j, $entry[$j])
            Next
        Else
            IniWrite("itempos.ini", "cache", $i, $entry)
        EndIf
    Next
    Exit
EndFunc   ;==>Quit


Func isSaved(ByRef $iSelected, ByRef $bags_in)
    Local $entry = $bags_in[$iSelected]
    If Not IsArray($entry) Then Return False
    Return StringLen(IniRead("itempos.ini", safename($entry[0] & '-' & $entry[2]), safename($entry[3]), "")) > 0
EndFunc   ;==>isSaved


Func uiOptions_Save(ByRef $uiInfo_Options, ByRef $bags, ByRef $iSelected)
    GUICtrlSetState($uiInfo_Options[$UIO_SAVE], $GUI_DISABLE)
    GUICtrlSetState($uiInfo_Options[$UIO_RESTORE], $GUI_DISABLE)
    WinActivate("Program Manager")
    Sleep(250)
    Send("{F5}")
    Sleep(1000)
    WinActivate($uiInfo_Options[$UIO_HWND])

    Local $entry = $bags[$iSelected]
    Local $nameSafe = safename($entry[0] & '-' & $entry[2])
    Local $bag_key = $entry[1]
    Local $valueName = $entry[3]
    Local $valueNameSafe = safename($valueName)
    Local $value = RegRead($bag_key, $valueName)
    ConsoleWrite("Saving to " & $nameSafe & @CRLF)

    IniWrite("itempos.ini", $nameSafe, $valueNameSafe, $value)
EndFunc   ;==>uiOptions_Save

Func uiOptions_Restore(ByRef $uiInfo_Options, ByRef $bags, ByRef $iSelected)
    GUICtrlSetState($uiInfo_Options[$UIO_SAVE], $GUI_DISABLE)
    GUICtrlSetState($uiInfo_Options[$UIO_RESTORE], $GUI_DISABLE)
    Local $entry = $bags[$iSelected]
    Local $nameSafe = safename($entry[0] & '-' & $entry[2])
    Local $bag_key = $entry[1]
    Local $valueName = $entry[3]
    Local $valueNameSafe = safename($valueName)
    Local $value = IniRead("itempos.ini", $nameSafe, $valueNameSafe, "")
    ConsoleWrite("Restoring from " & $nameSafe & @CRLF)

    If StringLen($value) = 0 Then Return MsgBox(0, 'Restore Error', "No data is available for this entry to be restored.")

    ProcessKill('explorer.exe')
    ProcessWaitClose('explorer.exe')
    RegWrite($bag_key, $valueName, "REG_BINARY", Binary($value))
    Run('explorer.exe')
EndFunc   ;==>restore

;--------------------------------------------------

Func uiCreateOptions()
    Local $uiInfo[5]
    $uiInfo[0] = GUICreate("Desktop Position Options", 350 + 20, 100)
    $uiInfo[1] = GUICtrlCreateInput("Not Selected", 0, 0, 350, 20, $ES_READONLY)
    $uiInfo[2] = GUICtrlCreateButton("...", 350, 0, 20, 20)
    $uiInfo[3] = GUICtrlCreateButton("Save", 0, 20, 350 + 20, 40)
    $uiInfo[4] = GUICtrlCreateButton("Restore", 0, 60, 350 + 20, 40)
    Return $uiInfo
EndFunc   ;==>uiCreateOptions


Func uiOptions_Reset(ByRef $bags, ByRef $iSelected_in, ByRef $uiInfo_Options)
    If $iSelected_in > 0 Then
        GUICtrlSetState($uiInfo_Options[3], $GUI_ENABLE)
        If isSaved($iSelected_in, $bags) Then
            GUICtrlSetState($uiInfo_Options[4], $GUI_ENABLE)
        Else
            GUICtrlSetState($uiInfo_Options[4], $GUI_DISABLE)
        EndIf
    Else
        GUICtrlSetState($uiInfo_Options[3], $GUI_DISABLE)
        GUICtrlSetState($uiInfo_Options[4], $GUI_DISABLE)
    EndIf
EndFunc   ;==>uiOptions_Reset



Func uiSelector_Submit($n, ByRef $uiInfo_Options, ByRef $uiInfo_Selector, ByRef $iSelected, ByRef $bags_in)
    $iSelected = $n

    Local $entry = ""
    If $iSelected > 0 Then $entry = $bags_in[$n]

    If IsArray($entry) Then
        GUICtrlSetData($uiInfo_Options[1], $entry[0] & '-' & $entry[2] & '-' & $entry[4])
        If IsHWnd($uiInfo_Selector[0]) Then GUISetState(@SW_HIDE, $uiInfo_Selector[0])
        WinActivate($uiInfo_Options[$UIO_HWND])
        uiOptions_Reset($bags_in, $iSelected, $uiInfo_Options)
        Return True
    Else
        GUICtrlSetData($uiInfo_Options[1], "Nothing Selected")
        uiOptions_Reset($bags_in, $iSelected, $uiInfo_Options)
        If IsHWnd($uiInfo_Selector[0]) Then
            GUISetState(@SW_SHOW, $uiInfo_Selector[0])
            WinActivate($uiInfo_Selector[0])
        EndIf
    EndIf
    Return False
EndFunc   ;==>uiSelector_Submit

Func uiSelector_Populate(ByRef $uiInfo, ByRef $bags, $doRefresh = True);; NOTE: uiInfo must be a 60-element array (ah hell, lets just give ourselves room to develop the UI a bit, the max dynamic controls will be 4*10 at this time)
    ProgressOn("Refreshing...", "Refreshing...")
    Local $maxCtrl = UBound($uiInfo) - 1
    Local $maxBags = UBound($bags) - 1

    ;to produce a UI without alot of extra Globals, we need to dynamically create our UI. So we need to discard of the old one.  Sizing is also much easier this way.
    ProgressSet(1, "Cleaning up...")
    Sleep(250)
    For $n = 1 To $maxCtrl
        If $uiInfo[$n] Then GUICtrlDelete($uiInfo[$n])
    Next
    If IsHWnd($uiInfo[0]) Then GUIDelete($uiInfo[0])

    ;reset data
    If $doRefresh Then
        For $i = 0 To $maxBags
            $bags[$i] = ''
        Next
        ProgressSet(5, "Finding folder information sources...")
        searchhive($bags)
    EndIf
    ProgressSet(95, "Creating User Interface...")
    Sleep(250)

    ;get the count of dynamic entries so that we can determine UI dimensions.
    Local $count = 0
    For $n = 1 To $maxBags
        If IsArray($bags[$n]) Then $count += 1
    Next

    ;creating our UI and static elements first.
    $uiInfo[0] = GUICreate("Select system setting to use...", 450, 20 * ($count + 2) + 10)
    $uiInfo[1] = GUICtrlCreateButton("??", 0, 0, 20, 20)
    $uiInfo[2] = GUICtrlCreateLabel("Profile", 020, 5, 250, 20)
    $uiInfo[3] = GUICtrlCreateLabel("Bag", 270, 5, 050, 20)
    $uiInfo[4] = GUICtrlCreateLabel("ItemPos", 320, 5, 150, 20)
    $uiInfo[5] = GUICtrlCreateLabel("-----------------------------------", 0, 20, 450, 5, $SS_ETCHEDHORZ)
    $uiInfo[6] = GUICtrlCreateButton("Refresh", 0, 20 * ($count + 1) + 10, 450, 20)

    ;  creating dynamic elements
    $count = 0
    For $n = 1 To $maxBags
        Local $entry = $bags[$n]
        If IsArray($entry) Then
            Local $y = ($count + 1) * 20 + 5;back-to-back rows of 20px with an initial offset of 5
            $count += 1
            $uiInfo[07 + ($count - 1) * 4] = GUICtrlCreateButton($count & '.', 0, $y, 20, 20)
            $y += 5;offset labels slightly so that they look centered on the buttons instead of top-aligned.
            $uiInfo[08 + ($count - 1) * 4] = GUICtrlCreateLabel($entry[0], 020, $y, 250, 20)
            $uiInfo[09 + ($count - 1) * 4] = GUICtrlCreateLabel($entry[2], 270, $y, 050, 20)
            $uiInfo[10 + ($count - 1) * 4] = GUICtrlCreateLabel($entry[4], 320, $y, 150, 20)
        EndIf
    Next

    ProgressSet(100, "Showing off...")
    Sleep(250)
    GUISwitch($uiInfo[0])
    ProgressOff()
    Return $uiInfo
EndFunc   ;==>uiSelector_Populate
;--------------------------------------------------------------------
Func searchhive(ByRef $results)
    ;ConsoleWrite('Current'&@CRLF)
    ProgressInitial(5)
    searchuser($results, 'HKEY_CURRENT_USER', 'Current User')
    ProgressSet(25)
    For $i = 1 To 9999; this looks bad, but substituting a While loop creates unnecessary lines for an index variable, and introduces an exhaustive search (limited by Signed Int maximum)
        Local $u = RegEnumKey("HKEY_USERS\", $i)
        If @error <> 0 Then ExitLoop
        ;ConsoleWrite($u&@CRLF)
        searchuser($results, "HKEY_USERS\" & $u, $u)
        ProgressSet(25 + $i * 10)
    Next
EndFunc   ;==>searchhive
Func searchuser(ByRef $results, $user_key, $display_name)
    Local $software_key[2] = ["Software\Microsoft\Windows", "Software\Classes\Local Settings\Software\Microsoft\Windows"]
    Local $shell_key[2] = ["Shell", "ShellNoRoam"]
    Local $name_suffix

    For $sw In $software_key
        $name_suffix = ""
        If StringInStr($sw, "Local") Then $name_suffix = "L"
        For $shell In $shell_key
            If StringInStr($shell, "NoRoam") Then $name_suffix &= "NR"
            Local $bags_key = $user_key & "\" & $sw & "\" & $shell & "\Bags"
            For $i = 1 To 9999; this looks bad, but substituting a While loop creates unnecessary lines for an index variable, and introduces an exhaustive search (limited by Signed Int maximum)
                ProgressIncrement(0.01)
                Local $bag = RegEnumKey($bags_key, $i)
                If @error <> 0 Then ExitLoop
                If StringLen($name_suffix) > 0 Then $name_suffix = "(" & $name_suffix & ")"
                searchbag($results, $bags_key, $bag, $display_name & $name_suffix)
            Next
        Next
    Next
EndFunc   ;==>searchuser
Func searchbag(ByRef $results, $bags_key, $bag, $display_name)
    Local $bag_key = $bags_key & '\' & $bag & '\Shell'
    Local $value
    For $i = 1 To 9999; this looks bad, but substituting a While loop creates unnecessary lines for an index variable, and introduces an exhaustive search (limited by Signed Int maximum)
        $value = RegEnumVal($bag_key, $i)
        If @error <> 0 Then ExitLoop
        If StringInStr($value, 'ItemPos') Then
            Local $entry[5] = [$display_name, $bag_key, $bag, $value, StringTrimLeft($value, 7)]
            _ArrayFixed_Add($results, $entry)
        EndIf
    Next
    $bag_key = $bags_key & '\' & $bag & '\Desktop'
    For $i = 1 To 9999; this looks bad, but substituting a While loop creates unnecessary lines for an index variable, and introduces an exhaustive search (limited by Signed Int maximum)
        $value = RegEnumVal($bag_key, $i)
        If @error <> 0 Then ExitLoop
        ;ConsoleWrite($value&@CRLF)
        If StringInStr($value, 'ItemPos') Then
            Local $entry[5] = [$display_name, $bag_key, $bag, $value, StringTrimLeft($value, 7)]
            _ArrayFixed_Add($results, $entry)
        EndIf
    Next
EndFunc   ;==>searchbag
Func _ArrayFixed_Add(ByRef $array, $value);adds an item, overwriting the oldest item | NOTE: Edited from original intent, see comments
    Local $x = UBound($array) - 1
    If $array[0] = $x Then Return False; *** decided later that overwriting sucked for systems with many profiles.
    Local $i = Mod($array[0], $x); values from 0 to x-1
    Local $n = $i + 1;(0 to x-1)+1 = 1 to x
    $array[0] = $n; this is also the nonadjusted index for the next item :)
    $array[$n] = $value
EndFunc   ;==>_Array_Fixed_Push


Func ProgressInitial($n = 0)
    $ProgressIncrement = $n
    ProgressSet($n)
EndFunc   ;==>ProgressInitial
Func ProgressIncrement($n = 1)
    $ProgressIncrement += $n
    ProgressSet($ProgressIncrement)
EndFunc   ;==>ProgressIncrement

Func safename($s)
    Return StringRegExpReplace($s, "[^a-zA-Z0-9_\-]", "_")
EndFunc   ;==>safename


Func ProcessKill($p); I should probably credit someone for this function
    Local $Kernel32 = DllOpen("kernel32.dll")
    Local $hproc = DllCall($Kernel32, 'int', 'OpenProcess', 'int', 0x1F0FFF, 'int', True, 'int', ProcessExists($p))
    DllCall($Kernel32, "int", "TerminateProcess", "int", $hproc[0], "dword", 1)
    DllClose($Kernel32)
EndFunc   ;==>ProcessKill

UI Arrays were absolutely necessary to maintain conciseness while eliminating Global references.

Edited by crashdemons

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

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

×
×
  • Create New...