Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.09.18;
Скачать: CL | DM;

Вниз

FWSysTrayInfo от Rouse   Найти похожие ветки 

 
Hint   (2011-02-22 17:36) [0]

Сегодня появилась задача получить список значков из области уведомлений. Нашел код  от Rouse:
http://rouse.drkb.ru/winapi.php

К сожалению, на Windows 7 код работал с ошибками:
1. Не отображались изображения у видимых значков. Причина в том, что для TImageList используется оригинальная нумерация, а индексы в W7 идут не по порядку (т. е. для трех элементов индексы могут быть 5, 7, 9, а не 0, 1, 2).
2. Не отображались скрытые значки. В W7 они находятся в отдельном окне (в отдельном списке). Т. е. надо получать еще один Handle и дополнительно читать из него.

Модифицированный модуль:
http://pastebin.com/vsa34NXq

Возможно, кому-нибудь пригодится.

P. S. На Windows 7 код не работает без прав администратора.


 
Hint   (2011-02-22 17:39) [1]

Загрузил файл с ошибкой :)
Надо заменить "and TBSTATE_HIDDEN" на "or TBSTATE_HIDDEN".
Исправленная версия:
http://pastebin.com/pLspXmxR


 
Rouse_ ©   (2011-02-22 20:30) [2]

Угу, спасибо, в следующем обновлении сайта поправлю.


 
Rouse_ ©   (2011-02-22 20:34) [3]

Кстати просьба - выложи модуль с измененным заголовком вверху указав там свои координаты.
По примеру вот этого: http://rouse.drkb.ru/components.php#fwiconex
Нам так сказать чужой славы не нужно :)


 
Hint   (2011-02-22 21:30) [4]

Забавно. Заработало без прав администратора :)

Код:
   // Выделяем в нем память под текстовый буффер
   pszTextBuffer := VirtualAllocEx(hProcess, nil, MAX_PATH,
     MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
   if pszTextBuffer <> nil then
   try
     // Выделяем в нем память под структуру TTBButtonInfo
     pButtonInfo := VirtualAllocEx(hProcess, nil, SizeOf(TTBButtonInfo),
       MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
     if GetLastError = 0 then
     try
       // Заполняем структуру
       ZeroMemory(@ButtonInfo, SizeOf(TTBButtonInfo));

GetLastError сообщает об ошибке ("вызывающая сторона не обладает всеми необходимыми правами доступа"), но функция VirtualAllocEx при этом возвращает адрес.
Заменил проверку GetLastError на проверку указателя, все заработало.
А GetLastError, как оказалось, возвращает ошибку после SetDebugPriv.

Последняя версия:
http://pastebin.com/UjM1nX9D

Если не против, то я поменял версию с 1.00 на 1.01 и добавил про поддержку Windows 7.


 
Rouse_ ©   (2011-02-22 21:42) [5]

Да конечно - не вопрос


 
Hint   (2011-03-04 16:20) [6]

Утечка всплыла.

         hImageList := SHGetFileInfo(PChar(FIconData.Items[I].szAppPath),
           0, SHFileInfo, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
         ImageList_ReplaceIcon(hImageList, SHFileInfo.iIcon, NprivIcon.hIcon);
         ImageList_ReplaceIcon(FIconData.ImageList.Handle, FIconData.Items[I].iImage,
           ImageList_GetIcon(hImageList, SHFileInfo.iIcon, ILD_NORMAL));

Не освобождается значок, полученный через ImageList_GetIcon.


 
Anatoly Podgoretsky ©   (2011-03-04 16:41) [7]

> Hint  (04.03.2011 16:20:06)  [6]

Значок какого цвета?


 
Hint   (2011-03-04 16:45) [8]


> Значок какого цвета?

Обычно зеленого, но иногда попадаются желтые. А что?


 
clickmaker ©   (2011-03-04 16:46) [9]

видимо, через желтые утекает


 
Rouse_ ©   (2011-03-04 17:01) [10]

Да скорее всего, чуть попозже гляну - еще руки не дошли до твоих правок.


 
Rouse_ ©   (2011-03-21 20:59) [11]

Обновил на сайте - проверяй...
http://rouse.drkb.ru/winapi.php#fwsystrayinfo


 
dimajest   (2011-05-26 03:47) [12]

Rouse_

DoGetIconsInfo
В случае использования 32 битного приложения с ключем IMAGE_FILE_LARGE_ADDRESS_AWARE в 64 битной среде имеем вылет оболочки.
В связи с тем, что выделение памяти происходит по правилу 4GB (приложения), а оболочка без этого ключа не может адресовать память выделеную с ключем MEM_TOP_DOWN (то есть последний мегабайт для приложения и оболочки - находятся в разной области памяти).

Спасибо за хороший класс.


 
Rouse_ ©   (2011-05-26 10:46) [13]

Не на чем проверить - 64 бит под рукой к сожалению нет.


 
Rouse_ ©   (2011-05-30 17:43) [14]


> dimajest   (26.05.11 03:47) [12]

Поковырялись на пару с Денисом, выложил новый вариант компонента. Можешь качать версию 1.03


 
Kerk ©   (2011-05-30 17:53) [15]

Годы идут, но вопрос "как запуздырить иконку в трей" все еще актуален :)


 
Rouse_ ©   (2011-05-30 19:24) [16]

Не Ромыч, тут задача как раз "как ее оттедова выпуздырить" :)
Вот Денис (harisma) например использует след образом: при старте своего приложения проверяет как был завершен предыдущий экземпляр приложения. Если аварийно, то при помощи данного класса ищет икону от старого экземпляра и удаляет ее :)


 
Юрий Зотов ©   (2011-05-30 22:52) [17]


> Rouse_ ©   (30.05.11 19:24) [16]

Хотя это должна была бы делать сама оболочка.
:o)


 
Inovet ©   (2011-05-30 22:57) [18]

Чьему перу принадлежит нетленное "запуздырить". Я первый раз вроде бы услышал в начале 1990-х в мульте "Чип и Дейл спешат на помощь", в той серии всему населению некая секта газировки запуздыривала мозг, а может и запузыривала, не помню, как там перевели.


 
Rouse_ ©   (2011-05-30 23:07) [19]


> Юрий Зотов ©   (30.05.11 22:52) [17]
> Хотя это должна была бы делать сама оболочка.

Юрч, ты глубоко заблуждаешся :) Оболочка удаляет инвалидную икону только когда с ней пользователь производит манипуляции (мышкой на ней провел, кликнул там не осторожно и т.д.). Собственно в этом и цимус ;)


 
Юрий Зотов ©   (2011-05-30 23:16) [20]


> Rouse_ ©   (30.05.11 23:07) [19]

Нет, Саша, это ты глубоко заблуждаешься. Или невнимательно читаешь. Я не хуже тебя знаю, когда оболочка УДАЛЯЕТ иконку, но говорил не об этом, а о том, когда она ДОЛЖНА была бы ее удалять.

Исчезло окно, принимающее сообщения от иконки - исчезла и сама иконка. Вот ТАК было бы правильно. И отслеживать это должна именно САМА оболочка.


 
Германн ©   (2011-05-31 00:27) [21]


>  Оболочка удаляет инвалидную икону только когда с ней пользователь
> производит манипуляции (мышкой на ней провел, кликнул там
> не осторожно и т.д.).

А я то думал, что это глюк моей программы.


 
Ega23 ©   (2011-05-31 10:08) [22]


> А я то думал, что это глюк моей программы.


Не. Попробуй через таск манагер процессы поприбивать. А иконки в трее останутся, пока мышой не проведёшь.


> Исчезло окно, принимающее сообщения от иконки - исчезла
> и сама иконка. Вот ТАК было бы правильно. И отслеживать
> это должна именно САМА оболочка.


Было бы совсем хорошо, если бы эта оболочка ещё дом сторожила, щи готовила и пиво подносила (правильной температуры). Но, к сожалению, таких совершенных систем пока не существует.


 
Rouse_ ©   (2011-05-31 10:20) [23]


> а о том, когда она ДОЛЖНА была бы ее удалять

А, понятно, только дело в том, что даже если окно исчезло, это никак не помешает мне переназначить _TNPRIVICON.hWnd на другое окно. Мошт на это и закладывались, мол негоже рубить сразу под корень? :)


 
Юрий Зотов ©   (2011-05-31 11:02) [24]


> Германн ©   (31.05.11 00:27) [21]

Видимо, это все же глюк программы - не посылаешь NIM_DELETE. Попробуй такую структуру кода:

if Shell_NotifyIcon(NIM_ADD, ...) then
try
 ...  
finally
  Shell_NotifyIcon(NIM_DELETE, ...)
end;

Иконка удаляется нормально, даже при аварийном завершении. Причем без всяких ректальных мероприятий.

> Ega23 ©   (31.05.11 10:08) [22]
> Было бы совсем хорошо, если бы эта оболочка ещё дом сторожила, щи
> готовила и пиво подносила (правильной температуры). Но, к сожалению,
> таких совершенных систем пока не существует.

Олег, что с тобой? Это же демагогия в чистом виде. Раньше ты такие "приемы" себе не позволял.

Речь не идет о том, чего оболочка не может и не должна делать. И даже о чем-то сложном речь не идет. Речь идет о простой операции, которую, оболочка вполне спокойно может и должна делать (кстати, и делает - только не тогда, когда надо).

> Rouse_ ©   (31.05.11 10:20) [23]
> даже если окно исчезло, это никак не помешает мне переназначить
> _TNPRIVICON.hWnd на другое окно.
</ I>
Так вот и будь добр СНАЧАЛА переназначить, а уж ПОТОМ убивай старое окно. Хоть сто порций.

А показывать невалидную иконку - некошерно, потому что это дезориентация юзера. Юзер видит иконку и думает, что программа нормально работает - а она на самом деле давно отвалилась и только одна иконка от нее осталась. Причем юзер совершенно не обязан каждую минуту проводить мышкой по иконкам, чтобы проверить, работают ли они.
I>
> Мошт на это и закладывались

Мошт. Но слабо верится.


 
Ega23 ©   (2011-05-31 11:17) [25]


> Речь идет о простой операции, которую, оболочка вполне спокойно
> может и должна делать (кстати, и делает - только не тогда,
>  когда надо).


Да чёрт его знает. Это как с"автоматическим обновлением данных у пользователя в гриде, когда другой юзверь данные как-то изменил.
можно регулярно рефрешить набор данных. Можно прикрутить событийный механизм. А можно отдать это дело пользователю - обновил тогда, когда сам захотел.
Последний вариант из трёх наименее эстетичен для искушённого пользователя, зато и наименьшую нагрузку даёт.
Вот, ИМХО, примерно то же самое и здесь.


 
Юрий Зотов ©   (2011-05-31 11:47) [26]

> Ega23 ©   (31.05.11 11:17) [25]
> Вот, ИМХО, примерно то же самое и здесь.

Не-а, далеко не  то же самое.

Сколько раз в минуту будет срабатывать автоматическая обновлялка данных при 1000 клиентских мест? Наверное, далеко не один. И каждый раз через сетку будет прокачиваться куча данных, а на каждом клиенте будет обновляться куча контролов. Накладно получается.

Кроме того, каково будет работать юзеру? Вот он набивает текст в каком-нибудь DB-контроле. Вдруг - хлоп! - вся его набивка исчезла и в этом контроле появился совсем другой текст. И юзер должен начинать набивку своего текста заново. Он набивает - а текст снова исчез и снова появился другой. И снова все сначала - сказка про белого бычка. Ты представляешь, что скажет юзер после 20-й неудачной попытки ввести в БД свой текст?

А в нашем случае что имеем? Одноразовую операцию без всякого трафика  и с обновлением только одного окна. И без напряга юзера. Кстати, еще и с освобождением неиспользуемых системных ресурсов, пусть даже и малых.

Когда убивается окно, система по-любому об этом событии знает. Привязка окон к иконкам ей тоже известна. Поэтому никто не мешает в момент убиения окна проверить, не завязан ли его хэндл на иконки - и если завязан, то такие иконки удалить. Накладных расходов - практически нет. И юзеру вполне себе комфортно.


 
Германн ©   (2011-06-01 01:28) [27]


> Юрий Зотов ©   (31.05.11 11:02) [24]
>
>
> > Германн ©   (31.05.11 00:27) [21]
>
> Видимо, это все же глюк программы - не посылаешь NIM_DELETE.
>  Попробуй такую структуру кода:
>
> if Shell_NotifyIcon(NIM_ADD, ...) then
> try
>  ...  
> finally
>   Shell_NotifyIcon(NIM_DELETE, ...)
> end;
>
> Иконка удаляется нормально, даже при аварийном завершении.
>  Причем без всяких ректальных мероприятий.
>

Хм. А как мне в блок try-finally запихать всю программу?


 
Ega23 ©   (2011-06-01 02:04) [28]


> Иконка удаляется нормально, даже при аварийном завершении.


А если извне процесс убить? Не "завершение приложение", а именно процесс грохнуть?



Страницы: 1 вся ветка

Текущий архив: 2011.09.18;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.008 c
15-1306509683
Чайник
2011-05-27 19:21
2011.09.18
Не включается монитор


2-1306929088
Reformator
2011-06-01 15:51
2011.09.18
Создать класс


15-1306314143
KSergey
2011-05-25 13:02
2011.09.18
Про гугль-почту


15-1306699762
LDV
2011-05-30 00:09
2011.09.18
распознавание текста


3-1264093758
SAN_i
2010-01-21 20:09
2011.09.18
Связать DataSource и Grid из разных dll