Advertisement
Guest User

Untitled

a guest
Jul 21st, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.40 KB | None | 0 0
  1. 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.
  2.  
  3. 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]
  4.  
  5. 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:
  6.  
  7. [code]DllCall("Shell32\SHChangeNotify", Int, 0x8000000, UInt,0, Ptr,0, Ptr,0)[/code]
  8.  
  9. 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:
  10.  
  11. [code]
  12. ControlGet, rebar, hwnd,, MSTaskListWClass1, ahk_class Shell_TrayWnd
  13. WinSet, Style, 0x16000000, ahk_id %rebar%
  14. [/code]
  15.  
  16. 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].
  17.  
  18. 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.
  19.  
  20. 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.
  21.  
  22. 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:
  23.  
  24. 1) freezes it in time (so you dont see any transition)
  25. 2) freezes it a few milliseconds too late (so you see the flicker)
  26. 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.
  27.  
  28. 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).
  29.  
  30. 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:
  31.  
  32. [code=autohotkey file=temporaryfreezetaskbar.ahk]
  33. #SingleInstance, Force
  34. #Persistent
  35. OnExit("recovershell")
  36.  
  37. global snubflashingactive := 0
  38.  
  39. ControlGet, controlrebar, hwnd,, MSTaskListWClass1, ahk_class Shell_TrayWnd
  40. global rebar := controlrebar
  41.  
  42. recovershell() {
  43. if (snubflashingactive = 1) {
  44. taskbarunfreeze()
  45. ExitApp
  46. }
  47. }
  48.  
  49. taskbarunfreeze() {
  50. SetTimer, taskbarunfreeze, Off
  51. WinSet, Style, 0x56000000, ahk_id %rebar%
  52. global snubflashingactive := 0
  53. }
  54.  
  55. snubflashingicons() {
  56. if (snubflashingactive = 0) {
  57. global snubflashingactive := 1
  58. WinSet, Style, 0x16000000, ahk_id %rebar%
  59. SetTimer, taskbarunfreeze, 500
  60. return
  61. }
  62. else {
  63. return
  64. }
  65. }
  66.  
  67. ; call this to freeze the taskbar
  68. snubflashingicons()[/code]
  69.  
  70. Again Here is the script by SKAN, Shell Change Notify Spy:
  71.  
  72. [url]https://autohotkey.com/board/topic/84131-shell-change-notification-spy/[/url]
  73. [code=autohotkey file=ShellChangeNotifySpy.ahk]
  74. ; Shell Change Notification Spy - By SKAN Created : 24-Aug-2012
  75. ; http://dl.dropbox.com/u/6428211/AutoHotkey/ShellChangeNotification/ShChangeNotifySpy.ahk
  76.  
  77. #SingleInstance, Force
  78. SetWorkingDir, %A_ScriptDir%
  79. OnExit, QuitScript
  80.  
  81. Gui +AlwaysOnTop +LastFound
  82. hGui := WinExist()
  83. Gui, Font, S8
  84. Gui, Add, ListView, +Grid w600 r50, EVENT|Values
  85. LV_SetImageList( DllCall( "ImageList_Create", Int,2, Int,20, Int,0x18, Int,1, Int,1 ), 1 )
  86. LV_ModifyCol( 1, 150 )
  87. Gui, Show, y150, Shell Change Notification Spy
  88.  
  89. MsgNo := DllCall( "RegisterWindowMessage", Str,"SHCHANGENOTIFY" )
  90. OnMessage( MsgNo, "ShChangeNotify" )
  91.  
  92. DriveGet, DriveList, List, Fixed
  93. Entries := StrLen( DriveList )
  94. VarSetCapacity( $SHChangeNotifyEntry, 8 * Entries, 0 )
  95. Loop, Parse, DriveList
  96. Off := ( A_Index - 1 ) * 8
  97. , PIDL := PathGetPIDL( A_LoopField ":" )
  98. , NumPut( PIDL, $SHChangeNotifyEntry, Off+0 )
  99. , NumPut( True, $SHChangeNotifyEntry, Off+4 )
  100.  
  101. SHCNR_ID := DllCall( "Shell32\SHChangeNotifyRegister", UInt,hGui
  102. , UInt, 0x8000|0x1000|0x2|0x1
  103. , Int, 0xC0581E0|0x7FFFFFFF|0x80000000
  104. , UInt, MsgNo
  105. , Int, Entries
  106. , UInt, &$SHChangeNotifyEntry )
  107. Return
  108.  
  109.  
  110. GuiClose:
  111. GuiEscape:
  112. QuitScript:
  113. OnExit
  114. DllCall( "Shell32\SHChangeNotifyDeregister", UInt,SHCNR_ID )
  115. ExitApp
  116.  
  117.  
  118. ShChangeNotify( wParam, lParam, msg, hwnd ) {
  119. hLock := DllCall( "Shell32\SHChangeNotification_Lock"
  120. , UInt,wParam, UInt,lParam, UIntP,pppidl, UIntP,plEvent )
  121.  
  122. Event := "SHCNE_UNDEFINED"
  123. IfEqual,plEvent,0x7FFFFFFF ,SetEnv,Event, SHCNE_ALLEVENTS
  124. IfEqual,plEvent,0x08000000 ,SetEnv,Event, SHCNE_ASSOCCHANGED
  125. IfEqual,plEvent,0x00000800 ,SetEnv,Event, SHCNE_ATTRIBUTES
  126. IfEqual,plEvent,0x00000002 ,SetEnv,Event, SHCNE_CREATE
  127. IfEqual,plEvent,0x00000004 ,SetEnv,Event, SHCNE_DELETE
  128. IfEqual,plEvent,0x0002381F ,SetEnv,Event, SHCNE_DISKEVENTS
  129. IfEqual,plEvent,0x00000100 ,SetEnv,Event, SHCNE_DRIVEADD
  130. IfEqual,plEvent,0x00010000 ,SetEnv,Event, SHCNE_DRIVEADDGUI
  131. IfEqual,plEvent,0x00000080 ,SetEnv,Event, SHCNE_DRIVEREMOVED
  132. IfEqual,plEvent,0x04000000 ,SetEnv,Event, SHCNE_EXTENDED_EVENT
  133. IfEqual,plEvent,0x00040000 ,SetEnv,Event, SHCNE_FREESPACE
  134. IfEqual,plEvent,0x0C0581E0 ,SetEnv,Event, SHCNE_GLOBALEVENTS
  135. IfEqual,plEvent,0x80000000 ,SetEnv,Event, SHCNE_INTERRUPT
  136. IfEqual,plEvent,0x00000020 ,SetEnv,Event, SHCNE_MEDIAINSERTED
  137. IfEqual,plEvent,0x00000040 ,SetEnv,Event, SHCNE_MEDIAREMOVED
  138. IfEqual,plEvent,0x00000008 ,SetEnv,Event, SHCNE_MKDIR
  139. IfEqual,plEvent,0x00000200 ,SetEnv,Event, SHCNE_NETSHARE
  140. IfEqual,plEvent,0x00000400 ,SetEnv,Event, SHCNE_NETUNSHARE
  141. IfEqual,plEvent,0x00020000 ,SetEnv,Event, SHCNE_RENAMEFOLDER
  142. IfEqual,plEvent,0x00000001 ,SetEnv,Event, SHCNE_RENAMEITEM
  143. IfEqual,plEvent,0x00000010 ,SetEnv,Event, SHCNE_RMDIR
  144. IfEqual,plEvent,0x00004000 ,SetEnv,Event, SHCNE_SERVERDISCONNECT
  145. IfEqual,plEvent,0x00001000 ,SetEnv,Event, SHCNE_UPDATEDIR
  146. IfEqual,plEvent,0x00008000 ,SetEnv,Event, SHCNE_UPDATEIMAGE
  147. IfEqual,plEvent,0x00002000 ,SetEnv,Event, SHCNE_UPDATEITEM
  148.  
  149. If Val2 := PIDLGetPath( NumGet( pppidl+4 ) )
  150. LV_Insert( 1, "", "", Val2 )
  151.  
  152. Val1 := PIDLGetPath( NumGet( pppidl+0 ) )
  153. LV_Insert( 1, "", Event, Val1 )
  154.  
  155. DllCall( "Shell32\SHChangeNotification_Unlock", UInt,hLock )
  156. }
  157.  
  158. PathGetPIDL( sPath ) {
  159. Return DllCall( "Shell32\ILCreateFromPath" ( A_IsUnicode ? "W":"A" ), Str,sPath, UInt )
  160. }
  161.  
  162. PIDLGetPath( PIDL ) {
  163. VarSetCapacity( sPath, 520, 0 )
  164. DllCall( "Shell32\SHGetPathFromIDList" ( A_IsUnicode ? "W":"A" ), UInt,PIDL, Str,sPath )
  165. Return sPath
  166. }
  167. [/code]
  168.  
  169. Note the following part of the script in the above link:
  170.  
  171. [code]
  172. MsgNo := DllCall( "RegisterWindowMessage", Str,"SHCHANGENOTIFY" )
  173. OnMessage( MsgNo, "ShChangeNotify" )
  174. [/code]
  175.  
  176. If you changed it to:
  177.  
  178. [code]
  179. OnMessage( MsgNo, "snubflashingicons" )
  180. [/code]
  181.  
  182. 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