
Получение координат иконки в трее
Сегодняшний пример - получение координат иконки в трее. Для чего это надо, я поясню чуть ниже. Сам код основан на уже знакомом вам переборе иконок в трее, поэтому практически все структуры будут такими же. Теоретическая часть работы с треем расписана там же, дублировать ее не буду. Начнем с описания всех необходимых структур и данных:Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- ; Структура пользовательских данных иконки
- struct EXTRADATA
- Wnd dd ?
- uID dd ?
- ends
- class1 db 'Shell_TrayWnd',0 ; Название класса окна трея
- class2 db 'TrayNotifyWnd',0 ; Название класса панели уведомлений
- class3 db 'SysPager',0 ; Трей
- class4 db 'ToolbarWindow32',0 ; Панель с иконками
- ; Структура для кнопки
- button TBBUTTON
- ; Структура для пользовательских данных иконки
- extra EXTRADATA
- ; Иконка в трее
- node NOTIFYICONDATA
- ; Координаты иконки в трее
- rc RECT
- ICON_ID = 777
- hInstance dd ? ; Хэндл приложения
- hToolbar dd ? ; Хэндл окна с иконками
- IconsCount dd ? ; Количество иконок в трее
- ProcId dd ? ; Id процесса
- hProcess dd ? ; Хэндл процесса
- lpData dd ? ; Указатель на блок памяти
- BytesRead dd ? ; Количество прочитанных символов
Не забываем про особенности чтения памяти 64-битного процесса из 32-битного. Пример реализации этого мощного колдунства также подробно расписан в статье по ссылке из первого абзаца. Тут приведен пример для x86.
Code (Assembler) : Убрать нумерацию
- ; Это наша иконка?
- mov eax,[hwnddlg]
- cmp eax,[extra.Wnd]
- ; Нет, пропустить
- jnz .loc_loop
- ; Это именно та иконка?
- cmp [extra.uID],ICON_ID
- ; Нет, пропустить
- jnz .loc_loop
- ; Получить координаты иконки в трее
- invoke SendMessage,[hToolbar],TB_GETITEMRECT,[IconsCount],[lpData]
- ; Прочитать данные координат иконки
- invoke ReadProcessMemory,[hProcess],[lpData],rc,\
- dword sizeof.RECT,BytesRead
- or eax,eax
- jz .clear_memory
- ; Прочиталась вся структура?
- cmp [BytesRead],sizeof.RECT
- jnz .clear_memory
- ; Преобразовать оконные координаты в экранные
- invoke MapWindowPoints,[hToolbar],HWND_DESKTOP,rc,2
Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- ; Структура для идентификации иконки
- struct NOTIFYICONIDENTIFIER
- cbSize dd ?
- hWnd dd ?
- uID dd ?
- guidItem rb 16
- ends
- ; Иконка в трее
- node NOTIFYICONDATA
- ; Идентификатор иконки
- notify NOTIFYICONIDENTIFIER
- ; Координаты иконки в трее
- rc RECT
Code (Assembler) : Убрать нумерацию
- ; Заполнить структуру для идентификации иконки
- mov [notify.cbSize],sizeof.NOTIFYICONIDENTIFIER
- mov eax,[hwnddlg]
- mov [notify.hWnd],eax
- mov [notify.uID],ICON_ID
- ; Получить координаты иконки в трее
- invoke Shell_NotifyIconGetRect,notify,rc
Важно помнить, что координаты иконки в трее не являются неизменными значениями. Пользователь может перетащить иконку на другую позицию или вообще скрыть иконку через настройки, вновь запущенное приложение может подвинуть иконку на другую позицию, Проводник может аварийно завершить работу и перезапуститься, в результате чего трей будет перерисован. Панель задач может изменить размер или положение на экране. Да мало ли чего может произойти. Поэтому обязательно надо заново получать координаты иконки перед тем, как выполнять связанные с этим действия.
Вот так мы плавно подошли к ответу на вопрос для чего это вообще надо. Дело в том, что система не предоставляет средств для полноценной обработки действий с мышью над иконкой в трее. Например, с помощью обычного обработчика сообщений совершенно невозможно отследить сообщения типа WM_MOUSEHOVER, WM_MOUSELEAVE и WM_MOUSEWHEEL. Но, зная координаты иконки, а затем сопоставив их с координатами события, это можно реализовать. Например, в следующем примере по таймеру можно опрашивать координаты иконки в трее и позицию курсора:
Code (Assembler) : Убрать нумерацию
- ; Получить позицию курсора
- invoke GetCursorPos,pt
- ; Курсор находится внутри прямоугольника иконки?
- invoke PtInRect,rc,[pt.x],[pt.y]
- or eax,eax
- ; Да
- jnz cursor_over_icon
В приложении примеры программ с исходными текстами, которые отслеживают изменение положения иконки в трее и перемещение курсора над этой иконкой.
Просмотров: 866 | Комментариев: 3

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(12.11.2021 в 11:18):
Добавил пример с Shell_NotifyIconGetRect, архив обновлен.

ManHunter
(11.11.2021 в 21:51):
Наверное, вот это
и то, что один фиг надо определять видимость иконки через все эти чтения памяти Проводника. Так что особого выигрыша оно не дает.
Но в остальном мысль правильная, обязательно добавлю в статью. Спасибо!
и то, что один фиг надо определять видимость иконки через все эти чтения памяти Проводника. Так что особого выигрыша оно не дает.
Но в остальном мысль правильная, обязательно добавлю в статью. Спасибо!

DRON
(11.11.2021 в 20:39):
А что не так с Shell_NotifyIconGetRect?

Добавить комментарий
Заполните форму для добавления комментария
