Search the Community
Showing results for tags 'positions'.
-
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.