Обработка изменения иконок в системном трее
С обновлением иконок в системном трее разобрались, теперь давайте разберем, как можно отслеживать изменения в трее. Причем изменения касаются не только добавления-удаления иконок, но также изменения всплывающих подсказок и изменения иконки с сохранением ее индекса.Code (Assembler) : Убрать нумерацию
- CLSCTX_LOCAL_SERVER = 0x04
- S_OK = 0
- struct NOTIFYITEM
- pszExeName dd ?
- pszTip dd ?
- hIcon dd ?
- hWnd dd ?
- dwPreference dd ?
- uID dd ?
- guidItem rd 4
- ends
- ; GUID {D782CCBA-AFB0-43F1-94DB-FDA3779EACCB}
- IID_INotificationCB dd 0D782CCBAh
- dw 0AFB0h
- dw 043F1h
- db 094h, 0DBh, 0FDh, 0A3h, 077h, 09Eh, 0ACh, 0CBh
- ; INotificationCB interface
- struct INotificationCB
- QueryInterface dd ?
- AddRef dd ?
- Release dd ?
- ; INotificationCB
- Notify dd ?
- ends
- ; GUID {FB852B2C-6BAD-4605-9551-F15F87830935}
- IID_ITrayNotify dd 0FB852B2Ch
- dw 06BADh
- dw 04605h
- db 095h, 051h, 0F1h, 05Fh, 087h, 083h, 009h, 035h
- ; ITrayNotify interface
- struct ITrayNotify
- QueryInterface dd ?
- AddRef dd ?
- Release dd ?
- ; ITrayNotify
- RegisterCallback dd ?
- SetPreference dd ?
- EnableAutoTray dd ?
- ends
- ; GUID {25DEAD04-1EAC-4911-9E3A-AD0A4AB560FD}
- CLSID_TrayNotify dd 025DEAD04h
- dw 01EACh
- dw 04911h
- db 09Eh, 03Ah, 0ADh, 00Ah, 04Ah, 0B5h, 060h, 0FDh
- ; GUID {00000000-0000-0000-C000-000000000046}
- IID_IUnknown dd 000000000h
- dw 00000h
- dw 00000h
- db 0C0h, 000h, 000h, 000h, 000h, 000h, 000h, 046h
Для отслеживания изменений в системном трее создается COM-объект TrayNotify, затем заполняется структура INotificationCB для callback-обработчика, после чего через метод RegisterCallback этот обработчик активируется.
Code (Assembler) : Убрать нумерацию
- ; Создать объект
- invoke CoCreateInstance,CLSID_TrayNotify,NULL,\
- CLSCTX_LOCAL_SERVER,IID_ITrayNotify,pTrNotDisp
- cmp eax,S_OK
- jne wmclose
- ; Настроить структуру INotificationCB
- mov [NCallBack.QueryInterface],CallBack_QueryInterface
- mov [NCallBack.AddRef],CallBack_AddRef
- mov [NCallBack.Release],CallBack_Release
- mov [NCallBack.Notify],CallBack_Notify
- mov eax,NCallBack
- mov [pNCallBack],eax
- ; Установить callback-функцию
- mov eax,[pTrNotDisp]
- mov eax,[eax]
- stdcall dword [eax+ITrayNotify.RegisterCallback],\
- [pTrNotDisp],pNCallBack
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------------
- ; Метод QueryInterface интерфейса IUnknown / INotificationCB
- ;------------------------------------------------------------------
- proc CallBack_QueryInterface pthis:DWORD, iid:DWORD, ppvObject:DWORD
- pusha
- mov eax,[ppvObject]
- cmp eax,0
- jne @f
- ; E_POINTER
- mov eax,0x80004003
- jmp .loc_ret
- @@:
- ; Это интерфейс INotificationCB?
- push 4
- pop ecx
- mov esi,[iid]
- mov edi,IID_INotificationCB
- xor eax,eax
- repe cmpsd
- jz .loc_call
- ; Это интерфейс IUnknown?
- push 4
- pop ecx
- mov esi,[iid]
- mov edi,IID_IUnknown
- xor eax,eax
- repe cmpsd
- jz .loc_call
- ; E_NOINTERFACE
- mov eax,0x80004002
- jmp .loc_ret
- .loc_call:
- mov eax,[pthis]
- ; Установить интерфейс
- mov ecx,[ppvObject]
- mov [ecx],eax
- mov ecx,[eax]
- stdcall dword [ecx+INotificationCB.AddRef],eax
- .loc_ok:
- ; S_OK
- xor eax,eax
- .loc_ret:
- mov [esp+28],eax
- popa
- ret
- endp
- ;------------------------------------------------------------------
- ; Заглушка для INotificationCB::AddRef
- ;------------------------------------------------------------------
- proc CallBack_AddRef pthis:DWORD
- mov eax,1
- ret
- endp
- ;------------------------------------------------------------------
- ; Заглушка для INotificationCB::Release
- ;------------------------------------------------------------------
- proc CallBack_Release pthis:DWORD
- mov eax,1
- ret
- endp
- ;------------------------------------------------------------------
- ; Callback-функция для получения уведомлений об изменении трея
- ;------------------------------------------------------------------
- proc CallBack_Notify pthis:DWORD, Event:DWORD, pItem:DWORD
- ; [Event] -> тип события: иконка добавлена, удалена, изменена
- ; Указатель на структуру NOTIFYITEM
- mov ebx,[pItem]
- ...
- ; Действия с иконкой
- ...
- ; S_OK
- xor eax,eax
- ret
- endp
По результатам тестов выяснились интересные особенности. Например, удаленные ранее иконки тоже могут попадать в обработчик, отловить их можно по невалидному хэндлу окна, а удалить по индексу, как при принудительном обновлении иконок. Имена исполняемых файлов могут передаваться в привычном виде, но если файл расположен в одной из папок, относящихся к стандартным папкам Windows, часть пути будет представлена в виде идентификатора KNOWNFOLDERID. Что-то типа {D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27}\taskmgr.exe. Как превратить такие ссылки в нормальный путь я подробно рассказал в этой статье.
Еще одно важное замечание. Если включен UAC, а процесс, который отслеживает изменения в трее, имеет повышенные привилегии (запущено от имени Администратора), то при попытке создать объект TrayNotify будет возвращена ошибка "Class not registered". Такое поведение наблюдается по крайней мере в Windows 7. Это связано с тем, что обработчик трея и оболочка имеют разные уровни контроля целостности, а приложение с большим уровнем контроля не может принимать сообщения от приложения с меньшим уровнем и наоборот.
В приложении пример программы с исходным текстом, которая отслеживает все изменения в системном трее и выводит их в лог.
Просмотров: 891 | Комментариев: 1
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Василий
(09.02.2022 в 20:59):
Очень пригодилось спасибо))) Набросал прогу для клиента mega.nz, чтобы при остановке закачки меняла айпишник и качала дальше)))
Добавить комментарий
Заполните форму для добавления комментария