Принудительное обновление иконок в трее

В случае аварийного завершения или некорректной работы некоторых приложений, в системном трее могут оставаться "мертвые" иконки, которые уже не принадлежат ни одному запущенному процессу. Глюк хоть и не смертельный, но все равно неприятный. И основная проблема в том, что область трея никак не реагирует на внешние сообщения типа WM_REPAINT, и функции типа UpdateWindow и InvalidateRect. То есть автоматически обновить или перерисовать его, чтобы избавиться от "мертвых" иконок, не получится. Но такие иконки удаляются, если провести курсором мышки над ними. Значит единственный способ перерисовать иконки в трее - это сэмулировать движение мыши над окном трея. Как найти окно трея и его хэндл мы уже знаем, тут ничего нового. В сегменте данных те же значения:
; Сегмент данных
section '.data' data readable writeable 
 
class1  db 'Shell_TrayWnd',0    ; Название класса окна трея
class2  db 'TrayNotifyWnd',0    ; Название класса панели уведомлений
class3  db 'SysPager',0         ; Трей
class4  db 'ToolbarWindow32',0  ; Панель с иконками
 
ToolbarHandle   dd ?            ; Хэндл окна трея
ToolbarRect     RECT            ; Размер окна трея

С поиском окна тоже никаких проблем. Способ универсальный, прекрасно работает на Windows XP и Windows 7.
        ; Найти окно трея
        invoke  FindWindow,class1,NULL
        or      eax,eax
        jz      exit_process
 
        ; Найти панель уведомлений
        invoke  FindWindowEx,eax,NULL,class2,NULL
        or      eax,eax
        jz      exit_process
 
        ; Найти трей
        invoke  FindWindowEx,eax,NULL,class3,NULL
        or      eax,eax
        jz      exit_process
 
        ; Найти панель иконок в трее
        invoke  FindWindowEx,eax,NULL,class4,NULL
        or      eax,eax
        jz      exit_process
 
        ; Сохранить хэндл окна с иконками
        mov     [ToolbarHandle],eax

Окно трея найдено, осталось сэмулировать движение мышки. Для этого надо просто получить размеры окна трея и в цикле отправить сообщение WM_MOUSEMOVE. Не обязательно эмулировать движение мышки над каждой точкой окна, достаточно пройтись один раз над каждой иконкой. Так как размер маленькой иконки 16х16 пикселов, то шаг выберем также 16.

И, собственно, сам код. Обратите внимание, что сообщения трею мы отправляем через PostMessage, чтобы не тратить время на ожидание от него ответа.
        ; Получить размеры окна трея
        invoke  GetClientRect,[ToolbarHandle],ToolbarRect
 
        ; Эмуляция движения мыши над окном трея
        xor     esi,esi
loc_move_line:
 
        xor     edi,edi
loc_move_column:
        ; y << 16
        mov     eax,esi
        shl     eax,16
 
        ; x
        add     eax,edi
 
        ; Отправить сообщение движения мыши
        invoke  PostMessage,[ToolbarHandle],WM_MOUSEMOVE,NULL,eax
 
        ; Следующий столбец
        add     edi,16
        cmp     edi,[ToolbarRect.right]
        jb      loc_move_column
 
        ; Следующая строка
        add     esi,16
        cmp     esi,[ToolbarRect.bottom]
        jb      loc_move_line

Этот способ, несмотря на то, что он работает, не лишен недостатков. Некоторые приложения, устанавливающие свои иконки в трей, реагируют на перемещение курсора над ними. Например, антивирус DrWeb показывает всплывающее окно с версией своей базы, менеджер USB-устройств Zentimo показывает окно со списком подключенных устройств, какие-нибудь другие программы также могут выполнять свои действия. Так вот, раз мы эмулируем движение мышки над иконками, то и программы срабатывают на это как на реальное движение курсора. Если вы используете трюк с обновлением трея в своей программе, то обязательно оформляйте его как отключаемую опцию с предупреждением о возможной несовместимости. К сожалению, пока что это единственный реальный способ заставить Проводник перерисовать иконки в трее из пользовательского приложения.

В приложении пример программы, обновляющей иконки в трее описанным в статье способом. Для тестов прилагается программа, которая устанавливает свою иконку в трей, и не удаляет ее после выхода.
Теги:
трей
Добавлено: 28 Сентября 2013 10:05:18 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...