Jump to content

Recommended Posts

Deye

Desktop Refresh

  * Recover window when its missing its address bar 
 * Close duplicate explorer windows
 * Sort items in the explorer task bar group  

  * Notifications (where needed) using Melba's cool Notify UDF 
  * to test this out : compile with an icon (for the notifications to look better) then pin to the  taskbar or the start menu and start refreshing !
  
 off course if you have anything here to add or improve , please leave a note

 Thanks 

#NoTrayIcon
#include <windowsConstants.au3>
#include <Array.au3>
#include <WinAPI.au3>
#include <WinAPISys.au3>
#include <WinAPIProc.au3>
#include <Misc.au3>
#include "Notify.au3" ; https://www.autoitscript.com/forum/topic/136149-notify-new-version-15-aug-15/
#include "StringSize.au3" ; Included in Notify.zip

Opt("WinTitleMatchMode", 3)

If _Singleton(@ScriptName, 1) = 0 Then Exit

$TaskList = _WinAPI_FindWindow('TaskListThumbnailWnd', '')
_WinAPI_ShowWindow($TaskList, 0)

$aWin = WinList("[class:MMCMainFrame]")
If IsArray($aWin) And UBound($aWin) - 1 > 1 Then
    If Not IsAdmin() Then
        ShellExecute(@ScriptFullPath, "", @ScriptDir, "runas")
        Exit
    EndIf
    For $i = UBound($aWin) - 1 To 2 Step -1
        _ArraySearch($aWin, $aWin[$i][0], 1, $i - 1)
        If Not @error Then
            WinClose($aWin[$i][1])
        EndIf
    Next
EndIf

OnAutoItExitRegister("_Update_changes_Refresh")

_Notify_RegMsg()

; Set notification location
_Notify_Locate(0)

; Settings for visible notifications
_Notify_Set(1, 0xffffff, 0x5f9180, Default, "MS Comic Sans", 250, 100)

Global $hNot = _Notify_Show(@ScriptFullPath, "Desktop Refresh ", " Processing Desktop Refresh ", 0)

;Get array for all visible windows
$aWin = _Get_WinArray()
If Not IsArray($aWin) Then Exit

;Get window state ,explorer paths and reload any jammed windows ( when the window address bar or Search Box are not visible)
For $i = UBound($aWin) - 1 To 1 Step -1
    If _WinAPI_GetClassName($aWin[$i][1]) = "CabinetWClass" Then
        $aWin[$i][2] = _ExprWinPath($aWin[$i][1])
        $aWin[$i][3] = _GetWindowPlacement($aWin[$i][1])
        If $aWin[$i][2] = False Then
            $aWin[$i][2] = StringReplace(ControlGetText($aWin[$i][1], "", 1001), "Address: ", '')
            If $aWin[$i][2] = "" Then $aWin[$i][2] = False
        EndIf
        If Not ControlGetHandle($aWin[$i][1], "", "Address Band Root1") Then _Restore($aWin, $aWin[$i][2], $i)
        If Not ControlGetHandle($aWin[$i][1], "", "Search Box1") Then _Restore($aWin, $aWin[$i][2], $i)
    Else
        $aWin[$i][2] = False
    EndIf
    $aWin[$i][4] = ProcessExists(WinGetProcess($aWin[$i][1]))
Next

;Close duplicate explorer windows
If UBound($aWin) - 1 > 1 Then
    For $i = UBound($aWin) - 1 To 2 Step -1
        If $aWin[$i][2] <> False Then
            _ArraySearch($aWin, $aWin[$i][2], 1, $i - 1, 0, 2, 1, 2)
            If @error = 6 Then ContinueLoop
            _Notify_Modify($hNot, Default, Default, "Duplicate Window", $aWin[$i][0], 1)
            WinClose($aWin[$i][1])
            _ArrayDelete($aWin, $i)
        EndIf
    Next
EndIf

; Free RAM for window processes
$Process = __Array_FromColumn($aWin, 4)
If IsArray($Process) And UBound($Process) - 1 >= 1 Then
    $WinProcess = _ArrayUnique($Process, 0, 0, 0, 0)
    If IsArray($WinProcess) And UBound($WinProcess) - 1 >= 1 Then
        For $i = 1 To UBound($WinProcess) - 1
            If ProcessExists($WinProcess[$i]) Then
                If _WinAPI_GetCurrentProcessID() = $WinProcess[$i] Then ContinueLoop
                _WinAPI_EmptyWorkingSet($WinProcess[$i])
            EndIf
        Next
    EndIf
EndIf

; Sorts windows explorer task bar group
$TaskGroup = $aWin

; sort by path
_ArraySort($TaskGroup, "", "", "", 2)

;sort by name
;~ _ArraySort($TaskGroup, "", "", "", 0)

For $i = 1 To UBound($TaskGroup) - 1
    If $TaskGroup[$i][2] <> False Then
        _WinAPI_ShowWindow($TaskGroup[$i][1], @SW_HIDE)
    EndIf
Next

For $i = 1 To UBound($TaskGroup) - 1
    If $TaskGroup[$i][2] <> False Then
        _WinAPI_ShowWindow($TaskGroup[$i][1], @SW_SHOWNOACTIVATE)
    EndIf
Next

; Restore window positions
For $i = UBound($aWin) - 1 To 1 Step -1
    If $aWin[$i][2] <> False Then
        $pos = StringSplit($aWin[$i][3], ',', 3)
        If IsArray($pos) Then
            _RestoreWindowPlacement($aWin[$i][1], $pos)
        EndIf
    EndIf
Next

_Notify_Hide($hNot)

Exit

Func _Update_changes_Refresh()

    ; Rid the taskbar from ghost icons
    _Taskbar_Refresh()

    ;Refresh for changes
    _WinAPI_PostMessage($HWND_BROADCAST, $WM_COMMAND, 41504, Null)

    ;https://www.autoitscript.com/forum/topic/181514-command-line-refresh-desktop/?do=findComment&comment=1303396
    DllCall("shell32.dll", "none", "SHChangeNotify", "long", 0x8000000, "uint", BitOR(0x0, 0x1000), "ptr", 0, "ptr", 0)

    ; Refreshes the OS environment (https://www.autoitscript.com/forum/topic/116484-solved-autoit3-encountered-a-problem-and-needs-to-close/?do=findComment&comment=812972)
    DllCall("user32.dll", "lresult", "SendMessageTimeoutW", _
            "hwnd", $HWND_BROADCAST, _
            "dword", 0, _
            "ptr", $WM_SETTINGCHANGE, _
            "wstr", "Environment", _
            "dword", $SMTO_ABORTIFHUNG, _
            "dword", 5000, _
            "dword_ptr*", 0)

    ; Visual effects Refresh
    If _GetMinAnimate() Then _SetMinAnimate(True)

EndFunc   ;==>_Update_changes_Refresh

Func _Get_WinArray()
    Local $aWinList = WinList(), $iEx_Style, $iStyle
    If IsArray($aWinList) Then
        For $i = UBound($aWinList) - 1 To 1 Step -1
            $iEx_Style = BitAND(_WinAPI_GetWindowLong($aWinList[$i][1], $GWL_EXSTYLE), $WS_EX_TOOLWINDOW)
            $iStyle = BitAND(WinGetState($aWinList[$i][1]), 2)
            If Not $iEx_Style And $iStyle Then
            Else
                _ArrayDelete($aWinList, $i)
                $aWinList[0][0] -= 1
            EndIf
        Next
        If UBound($aWinList) - 1 > 2 Then
            ReDim $aWinList[UBound($aWinList)][5]
            $aWinList[0][2] = False
            Return $aWinList
        EndIf
    EndIf
EndFunc   ;==>_Get_WinArray

Func __Array_FromColumn(ByRef $aArray, $iColumn = 0, $istart = 1)
    Local $aArray1D = ['']
    For $i = $istart To UBound($aArray) - 1
        _ArrayAdd($aArray1D, $aArray[$i][$iColumn])
    Next
    Return $aArray1D
EndFunc   ;==>__Array_FromColumn

Func _Restore(ByRef $aArray, $iPath, $index)
    If FileExists($iPath) Then
        _Notify_Modify($hNot, Default, Default, "Restoring ..", $aArray[$index][0], 1)
        Run('explorer.exe \separate,"' & $iPath & '"')
        Local $hwnd = WinWaitActive($aArray[$index][0], "", 4)
        If HWnd($hwnd) Then
            WinKill($aArray[$index][1])
            $aArray[$index][1] = $hwnd
        Else
            _Notify_Modify($hNot, Default, Default, "Failed Restoring ..", $aArray[$index][0], 1)
        EndIf
    Else
        _ArrayDelete($aArray, $index)
    EndIf
EndFunc   ;==>_Restore

Func _ExprWinPath($hwnd) ;https://www.autoitscript.com/forum/topic/89833-windows-explorer-current-folder/
    Local $sFolder
    $sFolder = _ObjectSHFolder($hwnd)
    If IsObj($sFolder) Then
        If StringInStr($sFolder.Folder.Self.Path, "\0") Then Return False
        Return $sFolder.Folder.Self.Path
    EndIf
    Return False
EndFunc   ;==>_ExprWinPath

Func _ObjectSHFolder($hwnd)
    Local $oShell, $oShellWindows, $oIEObject, $sFolder
    $oShell = ObjCreate("Shell.Application")
    $oShellWindows = $oShell.Windows()
    For $oIEObject In $oShellWindows
        If $oIEObject.HWND = $hwnd Then
            $sFolder = $oIEObject.Document
            If IsObj($sFolder) Then Return $sFolder
        EndIf
    Next
EndFunc   ;==>_ObjectSHFolder

Func _GetWindowPlacement($hwnd) ;https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_GetWindowPlacement.htm
    Local $tRET = _WinAPI_GetWindowPlacement($hwnd)
    If @error = 0 Then
        Local $length = DllStructGetData($tRET, "length")
        Local $flags = DllStructGetData($tRET, "flags")
        Local $showCmd = DllStructGetData($tRET, "showCmd")

        Local $MinX = DllStructGetData($tRET, "ptMinPosition", 1)
        Local $MinY = DllStructGetData($tRET, "ptMinPosition", 2)

        Local $MaxX = DllStructGetData($tRET, "ptMaxPosition", 1)
        Local $MaxY = DllStructGetData($tRET, "ptMaxPosition", 2)

        Local $left = DllStructGetData($tRET, "rcNormalPosition", 1)
        Local $top = DllStructGetData($tRET, "rcNormalPosition", 2)
        Local $right = DllStructGetData($tRET, "rcNormalPosition", 3)
        Local $bottom = DllStructGetData($tRET, "rcNormalPosition", 4)

        Return $length & "," & $flags & "," & $showCmd & "," & $MinX & "," & $MinY & "," & $MaxX & "," & $MaxY & "," & $left & "," & $top & ", " & $right & "," & $bottom
    EndIf
EndFunc   ;==>_GetWindowPlacement

Func _RestoreWindowPlacement($hwnd, ByRef $ipos) ;https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_SetWindowPlacement.htm
    Local $tRET = _WinAPI_GetWindowPlacement($hwnd)
    DllStructSetData($tRET, "lqflags", $ipos[1])
    DllStructSetData($tRET, "showCmd", $ipos[2])

    DllStructSetData($tRET, "ptMinPosition", $ipos[3], 1)
    DllStructSetData($tRET, "ptMinPosition", $ipos[4], 2)

    DllStructSetData($tRET, "ptMaxPosition", $ipos[5], 1)
    DllStructSetData($tRET, "ptMaxPosition", $ipos[6], 2)

    DllStructSetData($tRET, "rcNormalPosition", $ipos[7], 1)
    DllStructSetData($tRET, "rcNormalPosition", $ipos[8], 2)
    DllStructSetData($tRET, "rcNormalPosition", $ipos[9], 3)
    DllStructSetData($tRET, "rcNormalPosition", $ipos[10], 4)

    _WinAPI_SetWindowPlacement($hwnd, $tRET)
EndFunc   ;==>_RestoreWindowPlacement

Func _Taskbar_Refresh() ;http://www.autoitscript.com/forum/topic/66629-systemtray-refresh/
    Local $hTaskBar, $hParent, $hwnd, $WinRect, $aMousePos, $left, $right, $top, $tRect

    $hTaskBar = _WinAPI_FindWindow("Shell_TrayWnd", "")
    $hParent = ControlGetHandle($hTaskBar, "", "TrayNotifyWnd1")

    $hwnd = ControlGetHandle($hParent, "", "ToolbarWindow321")
    $WinRect = _WinAPI_GetWindowRect($hwnd)
    $left = DllStructGetData($WinRect, "Left")
    $right = DllStructGetData($WinRect, "Right")
    $top = DllStructGetData($WinRect, "Top")
    $top += 20

    $hwnd = ControlGetHandle($hParent, "", "TrayClockWClass1")
    $WinRect = _WinAPI_GetWindowRect($hwnd)
    $tRect = DllStructGetData($WinRect, "Left")

    $aMousePos = MouseGetPos()
    If $left < $tRect Then
        For $i = $left To $tRect
            MouseMove($i, $top, 0)
        Next
    Else
        For $i = $tRect To $right
            MouseMove($i, $top, 0)
        Next
    EndIf
    MouseMove($aMousePos[0], $aMousePos[1], 0)
EndFunc   ;==>_Taskbar_Refresh

Func _SetMinAnimate($bBoolean = True) ; $SPI_SETANIMATION = 0x0049 ;https://www.autoitscript.com/forum/topic/177149-systemparametersinfo-result/
    Local Const $tagANIMATIONINFO = "uint cbSize;int iMinAnimate"
    Local $sStruct = DllStructCreate($tagANIMATIONINFO)
    DllStructSetData($sStruct, "iMinAnimate", $bBoolean)
    DllStructSetData($sStruct, "cbSize", DllStructGetSize($sStruct))
    Local $aReturn = DllCall('user32.dll', 'int', 'SystemParametersInfo', 'uint', 0x0049, 'int', DllStructGetSize($sStruct), 'ptr', DllStructGetPtr($sStruct), 'uint', 0)
    If IsArray($aReturn) Then Return 1
    Return 0
EndFunc   ;==>_SetMinAnimate

Func _GetMinAnimate() ; $SPI_GETANIMATION = 0x0048
    Local Const $tagANIMATIONINFO = "uint cbSize;int iMinAnimate"
    Local $sStruct = DllStructCreate($tagANIMATIONINFO)
    DllStructSetData($sStruct, "cbSize", DllStructGetSize($sStruct))
    Local $aReturn = DllCall('user32.dll', 'int', 'SystemParametersInfo', 'uint', 0x0048, 'int', DllStructGetSize($sStruct), 'ptr', DllStructGetPtr($sStruct), 'uint', 0)
    If IsArray($aReturn) Then Return $sStruct.iMinAnimate
    Return 0
EndFunc   ;==>_GetMinAnimate

 

Edited by Deye

Share this post


Link to post
Share on other sites
Deye

Updated!

Edited by Deye

Share this post


Link to post
Share on other sites
Deye

..

Edited by Deye

Share this post


Link to post
Share on other sites
Deye

Updated for some other here and there refreshes + slight improvements, hope its all good now 

Share this post


Link to post
Share on other sites
MattHiggs

What versions of Windows is this tested on?  Is it supposed to work for all versions?  Out of curiosity. 

Share this post


Link to post
Share on other sites
Deye

    Hi MattHiggs,     

    Its tested on windows 7_64 and with an initial run on windows 10_64 it seems to run just fine
    is may need some amending for the taskbar refresh (just noticed) when on windows 10
    and the animation effect refresh can do better ..
    but the basic stuff seems to work just fine

Share this post


Link to post
Share on other sites
int3lln3t

 

This version reports two errors

Include\Array.au3" (2290) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:

@Script ---> (163) : ==> Variable used without being declared.: ->  _WinAPI_EndDeferWindowPos($hInfo)

Share this post


Link to post
Share on other sites
argumentum
48 minutes ago, int3lln3t said:

This version reports two errors

@int3lln3t, I can not say "welcome to the forum" as you been here since 2015.
I personally dislike the choice of font you've made.
@Deye, thanks for sharing. 

  • Like 1

Share this post


Link to post
Share on other sites
Deye

 int3lln3t,

Welcome to the autoit forum

first Try adding this line to where are all includes are

#include <WinAPISys.au3> 

and check for the latest beta

Edit : Updated

Run it now to See if those issues are fixed 

Updated _Taskbar_Refresh() ; to work on windows 10 too

Edited by Deye

Share this post


Link to post
Share on other sites
Deye

Updated:  Was using _ArrayUnique() in the wrong way, what might have caused a crash for some of you

made a few fixes in some fragile points

 

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

×