Reacting to SHChangeNotify calls to shell32.dll (taskbar icon flickering issue)

Get help with using AutoHotkey and its commands and hotkeys
fanfare
Posts: 2
Joined: 20 Jul 2018, 23:42
GitHub: fanfare

Reacting to SHChangeNotify calls to shell32.dll (taskbar icon flickering issue)

21 Jul 2018, 01:01

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:

Image

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 'SHChangeNotify' call made to shell32.dll. For example, the following ahk script will reproduce the very flickering that is so annoying:

Code: [Select all] [Download] GeSHi © Codebox Plus

DllCall("Shell32\SHChangeNotify", Int, 0x8000000, UInt,0, Ptr,0, Ptr,0)


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: [Select all] [Download] GeSHi © Codebox Plus

ControlGet, rebar, hwnd,, MSTaskListWClass1, ahk_class Shell_TrayWnd
WinSet, Style, 0x16000000, ahk_id %rebar%


This sets the style for the icon area in the taskbar to no longer have WM_CHILD 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 0x56000000 -- re-enabling WM_CHILD.

Now - when it comes to the SHChangeNotify part, I found a very useful ahk script by forum user SKAN ( https://autohotkey.com/board/topic/84131-shell-change-notification-spy/ ) that actively listens for SHChangeNotify 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 WM_CHILD 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 WinSet command, and then passing on the real request to shell32 (i dont think this is possible) - or something like, using the https://github.com/tariqporter/Gdip 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 SHChangeNotify call is made, and drop it a few milliseconds later, covering up the flickering (maybe it would be faster than WinSet? 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: [Select all] [Expand] [Download] (temporaryfreezetaskbar.ahk)GeSHi © Codebox Plus



Again Here is the script by SKAN, Shell Change Notify Spy:

https://autohotkey.com/board/topic/84131-shell-change-notification-spy/

Code: [Select all] [Expand] [Download] (ShellChangeNotifySpy.ahk)GeSHi © Codebox Plus



Note the following part of the script in the above link:

Code: [Select all] [Download] GeSHi © Codebox Plus

MsgNo := DllCall( "RegisterWindowMessage", Str,"SHCHANGENOTIFY" )
OnMessage( MsgNo, "ShChangeNotify" )


If you changed it to:

Code: [Select all] [Download] GeSHi © Codebox Plus

OnMessage( MsgNo, "snubflashingicons" )


where 'snubflashingicons' 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.

Return to “Ask For Help”

Who is online

Users browsing this forum: asghar5676, dee1337, IsaacElenbaas, ivyandrei, MIRKOSOFT and 55 guests