Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- I've been trying to mess with a script for some time now, and I feel like it is really close, but it's just not quite there.
- There is an annoying flicker that happens on all the icons in the taskbar once in a while (sometimes all the time). This can be reproduced on demand by moving a file to the recycle bin, when nothing else is in the recycle bin, such as demonstrated here: [url]https://i.imgur.com/LHUdDnM.gif[/url]
- After doing much research, I discovered that the flickering comes about when a program requests that the icons on the system be redrawn (for example, due to a file association change). The specific request is a '[font=courier new]SHChangeNotify[/font]' call made to [font=courier new]shell32.dll[/font]. For example, the following ahk script will reproduce the very flickering that is so annoying:
- [code]DllCall("Shell32\SHChangeNotify", Int, 0x8000000, UInt,0, Ptr,0, Ptr,0)[/code]
- Just as an aside - I had thought of ways in the past to try and 'freeze' the taskbar visually while still letting a user click on the icons - and had some success with the following script:
- [code]
- ControlGet, rebar, hwnd,, MSTaskListWClass1, ahk_class Shell_TrayWnd
- WinSet, Style, 0x16000000, ahk_id %rebar%
- [/code]
- This sets the style for the icon area in the taskbar to no longer have [font=courier new]WM_CHILD[/font] style - which when triggered will keep a ghost copy of the taskbar icons in place, while still letting a user click on the icons. It can be recovered back to full interactiveness by changing the style back to [font=courier new]0x56000000[/font] -- re-enabling [font=courier new]WM_CHILD[/font].
- Now - when it comes to the [font=courier new]SHChangeNotify[/font] part, I found a very useful ahk script by forum user SKAN ( [url]https://autohotkey.com/board/topic/84131-shell-change-notification-spy/[/url] ) that actively listens for [font=courier new]SHChangeNotify[/font] calls made to shell32 and outputs the messages to a box, live as they happen.
- I figured the two could maybe be combined - so that when a request is made to shell32 to do some kind of redrawing, ahk could quickly trigger the dropping of [font=courier new]WM_CHILD[/font] on the taskbar, and then re-instating it about 500ms later, after the flickering had finished, so visually, you wouldn't see the flickering happen.
- I attempted to do so and.. it works -- but not all of the time. It looks like it's some kind of race condition. The system performs the redrawing pretty much the exact same time my script attempts to freeze the taskbar, so it either:
- 1) freezes it in time (so you dont see any transition)
- 2) freezes it a few milliseconds too late (so you see the flicker)
- 3) freezes mid-way during a flicker, so the taskbar icons disappear, and my script freezes it, so you end up with 500ms of no icons, then back to normal.
- I've tried all I could think of messing with putting 'critical' in different places in the script, and running the script with 'real time' priority, attempting to prioritize what I'm trying to do, but I simply do not know if it is even possible to perform the WinSet taskbar freeze faster than shell32 performs the icon redrawing. My only thoughts left are either to somehow truly intercept the call being made to shell32, doing the [font=courier new]WinSet[/font] command, and then passing on the real request to shell32 (i dont think this is possible) - or something like, using the [url]https://github.com/tariqporter/Gdip[/url] library to occasionally create a hidden bitmap clone of the taskbar, waiting in memory, then temporarily paint it on top of the taskbar in-place when the [font=courier new]SHChangeNotify[/font] call is made, and drop it a few milliseconds later, covering up the flickering (maybe it would be faster than [font=courier new]WinSet[/font]? Not sure - sort of doubtful).
- Below is a basic script that can be used to trigger a temporary freezing (yet still clickable) state of the taskbar.. I made it in such a way that the request to the initial function quickly returns, without using sleep or anything to trigger the secondary function which un-freezes the taskbar:
- [code=autohotkey file=temporaryfreezetaskbar.ahk]
- #SingleInstance, Force
- #Persistent
- OnExit("recovershell")
- global snubflashingactive := 0
- ControlGet, controlrebar, hwnd,, MSTaskListWClass1, ahk_class Shell_TrayWnd
- global rebar := controlrebar
- recovershell() {
- if (snubflashingactive = 1) {
- taskbarunfreeze()
- ExitApp
- }
- }
- taskbarunfreeze() {
- SetTimer, taskbarunfreeze, Off
- WinSet, Style, 0x56000000, ahk_id %rebar%
- global snubflashingactive := 0
- }
- snubflashingicons() {
- if (snubflashingactive = 0) {
- global snubflashingactive := 1
- WinSet, Style, 0x16000000, ahk_id %rebar%
- SetTimer, taskbarunfreeze, 500
- return
- }
- else {
- return
- }
- }
- ; call this to freeze the taskbar
- snubflashingicons()[/code]
- Again Here is the script by SKAN, Shell Change Notify Spy:
- [url]https://autohotkey.com/board/topic/84131-shell-change-notification-spy/[/url]
- [code=autohotkey file=ShellChangeNotifySpy.ahk]
- ; Shell Change Notification Spy - By SKAN Created : 24-Aug-2012
- ; http://dl.dropbox.com/u/6428211/AutoHotkey/ShellChangeNotification/ShChangeNotifySpy.ahk
- #SingleInstance, Force
- SetWorkingDir, %A_ScriptDir%
- OnExit, QuitScript
- Gui +AlwaysOnTop +LastFound
- hGui := WinExist()
- Gui, Font, S8
- Gui, Add, ListView, +Grid w600 r50, EVENT|Values
- LV_SetImageList( DllCall( "ImageList_Create", Int,2, Int,20, Int,0x18, Int,1, Int,1 ), 1 )
- LV_ModifyCol( 1, 150 )
- Gui, Show, y150, Shell Change Notification Spy
- MsgNo := DllCall( "RegisterWindowMessage", Str,"SHCHANGENOTIFY" )
- OnMessage( MsgNo, "ShChangeNotify" )
- DriveGet, DriveList, List, Fixed
- Entries := StrLen( DriveList )
- VarSetCapacity( $SHChangeNotifyEntry, 8 * Entries, 0 )
- Loop, Parse, DriveList
- Off := ( A_Index - 1 ) * 8
- , PIDL := PathGetPIDL( A_LoopField ":" )
- , NumPut( PIDL, $SHChangeNotifyEntry, Off+0 )
- , NumPut( True, $SHChangeNotifyEntry, Off+4 )
- SHCNR_ID := DllCall( "Shell32\SHChangeNotifyRegister", UInt,hGui
- , UInt, 0x8000|0x1000|0x2|0x1
- , Int, 0xC0581E0|0x7FFFFFFF|0x80000000
- , UInt, MsgNo
- , Int, Entries
- , UInt, &$SHChangeNotifyEntry )
- Return
- GuiClose:
- GuiEscape:
- QuitScript:
- OnExit
- DllCall( "Shell32\SHChangeNotifyDeregister", UInt,SHCNR_ID )
- ExitApp
- ShChangeNotify( wParam, lParam, msg, hwnd ) {
- hLock := DllCall( "Shell32\SHChangeNotification_Lock"
- , UInt,wParam, UInt,lParam, UIntP,pppidl, UIntP,plEvent )
- Event := "SHCNE_UNDEFINED"
- IfEqual,plEvent,0x7FFFFFFF ,SetEnv,Event, SHCNE_ALLEVENTS
- IfEqual,plEvent,0x08000000 ,SetEnv,Event, SHCNE_ASSOCCHANGED
- IfEqual,plEvent,0x00000800 ,SetEnv,Event, SHCNE_ATTRIBUTES
- IfEqual,plEvent,0x00000002 ,SetEnv,Event, SHCNE_CREATE
- IfEqual,plEvent,0x00000004 ,SetEnv,Event, SHCNE_DELETE
- IfEqual,plEvent,0x0002381F ,SetEnv,Event, SHCNE_DISKEVENTS
- IfEqual,plEvent,0x00000100 ,SetEnv,Event, SHCNE_DRIVEADD
- IfEqual,plEvent,0x00010000 ,SetEnv,Event, SHCNE_DRIVEADDGUI
- IfEqual,plEvent,0x00000080 ,SetEnv,Event, SHCNE_DRIVEREMOVED
- IfEqual,plEvent,0x04000000 ,SetEnv,Event, SHCNE_EXTENDED_EVENT
- IfEqual,plEvent,0x00040000 ,SetEnv,Event, SHCNE_FREESPACE
- IfEqual,plEvent,0x0C0581E0 ,SetEnv,Event, SHCNE_GLOBALEVENTS
- IfEqual,plEvent,0x80000000 ,SetEnv,Event, SHCNE_INTERRUPT
- IfEqual,plEvent,0x00000020 ,SetEnv,Event, SHCNE_MEDIAINSERTED
- IfEqual,plEvent,0x00000040 ,SetEnv,Event, SHCNE_MEDIAREMOVED
- IfEqual,plEvent,0x00000008 ,SetEnv,Event, SHCNE_MKDIR
- IfEqual,plEvent,0x00000200 ,SetEnv,Event, SHCNE_NETSHARE
- IfEqual,plEvent,0x00000400 ,SetEnv,Event, SHCNE_NETUNSHARE
- IfEqual,plEvent,0x00020000 ,SetEnv,Event, SHCNE_RENAMEFOLDER
- IfEqual,plEvent,0x00000001 ,SetEnv,Event, SHCNE_RENAMEITEM
- IfEqual,plEvent,0x00000010 ,SetEnv,Event, SHCNE_RMDIR
- IfEqual,plEvent,0x00004000 ,SetEnv,Event, SHCNE_SERVERDISCONNECT
- IfEqual,plEvent,0x00001000 ,SetEnv,Event, SHCNE_UPDATEDIR
- IfEqual,plEvent,0x00008000 ,SetEnv,Event, SHCNE_UPDATEIMAGE
- IfEqual,plEvent,0x00002000 ,SetEnv,Event, SHCNE_UPDATEITEM
- If Val2 := PIDLGetPath( NumGet( pppidl+4 ) )
- LV_Insert( 1, "", "", Val2 )
- Val1 := PIDLGetPath( NumGet( pppidl+0 ) )
- LV_Insert( 1, "", Event, Val1 )
- DllCall( "Shell32\SHChangeNotification_Unlock", UInt,hLock )
- }
- PathGetPIDL( sPath ) {
- Return DllCall( "Shell32\ILCreateFromPath" ( A_IsUnicode ? "W":"A" ), Str,sPath, UInt )
- }
- PIDLGetPath( PIDL ) {
- VarSetCapacity( sPath, 520, 0 )
- DllCall( "Shell32\SHGetPathFromIDList" ( A_IsUnicode ? "W":"A" ), UInt,PIDL, Str,sPath )
- Return sPath
- }
- [/code]
- Note the following part of the script in the above link:
- [code]
- MsgNo := DllCall( "RegisterWindowMessage", Str,"SHCHANGENOTIFY" )
- OnMessage( MsgNo, "ShChangeNotify" )
- [/code]
- If you changed it to:
- [code]
- OnMessage( MsgNo, "snubflashingicons" )
- [/code]
- where '[font=courier new]snubflashingicons[/font]' is a function in my script to trigger my taskbar freezer/unfreezer, it will either work or almost work, as mentioned in my bullet points above. Like I said, it's really close (and a very hackish solution to a problem that I don't know if Microsoft will ever fix, since I've investigated thoroughly and traces of this visual glitch are present even in Windows 95, sadly) .. but I'm hoping someone here might have some insight, or alternative solutions to getting this problem solved once and for all.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement