<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AHK: Очистить трей от иконок закрытых приложений]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=12003</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=12003&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AHK: Очистить трей от иконок закрытых приложений».]]></description>
		<lastBuildDate>Tue, 13 Sep 2016 00:31:38 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107611#p107611</link>
			<description><![CDATA[<div class="quotebox"><cite>Drugoy пишет:</cite><blockquote><p>&#039;ptr&#039; можно обозвать и переменную, что способно запутать как пишущего, так и читающего код</p></blockquote></div><p>В современном AHK нет необходимости так делать. Это использовалось раньше при переходе с AHK-basic на L, т. к. в первой версии нет типа ptr.</p><div class="quotebox"><cite>Drugoy пишет:</cite><blockquote><p>Так что проще не экономить на кавычках (вы же не экономите, скажем, на пробелах после запятых-разделителей?)</p></blockquote></div><p> Дело вкуса, отсутствие пробелов после запятой вредит читабельностьи, чего неё скажешь об отсутствии кавычкек в типе. Достаточно запомнить, что в NumPut/Get они нужны, а в DllCall не обязательны.</p><div class="quotebox"><blockquote><p>Другого способа нет?</p></blockquote></div><p>В любом случае придётся перебирать все иконки, чтобы узнать хэндл связанного с ней окна (и её uID, если цель не удаление, а что-то другое), только так иконку можно идентифицировать.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Tue, 13 Sep 2016 00:31:38 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107611#p107611</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107581#p107581</link>
			<description><![CDATA[<div class="fancy_spoiler_switcher"><div class="fancy_spoiler_switcher_header" data-lang-open="открыть спойлер" data-lang-close="скрыть спойлер"><strong>+</strong>&nbsp;открыть спойлер</div><div class="fancy_spoiler"><p><strong>teadrinker</strong>, спасибо, что поправили, я думал, что это ошибка, просто не критическая (типа использования неверного типа данных, что тоже не всегда приводит к проблемам), а сейчас покопался в документации - и оказалось, что там это отмечено.<br />Правда, следует помнить, что:<br />- все типы со звёздочкой - в кавычки брать надо (звёздочку можно заменить на &quot;P&quot; и тогда кавычки не обязательны.<br />- &#039;ptr&#039; можно обозвать и переменную, что способно запутать как пишущего, так и читающего код.<br />- следует помнить, что вне DllCall (например, в NumPut) - кавычки уже обязательны, что способно запутать пишущего код.<br />Так что проще не экономить на кавычках (вы же не экономите, скажем, на пробелах после запятых-разделителей?) и всегда их употреблять, как правило хорошего тона.</p></div></div><p>Возник сопутствующий вопрос: получать информацию о каждой иконке и проверять жив ли связанный с ней процесс - это немножко оверкилл для случая, когда заранее известно, какой процесс будет убит так, что от него может остаться иконка (если у процесса была иконка в трее).<br />Можно ли как-то в этом случае выполнить очистку такой иконки (если она есть) чисто по pid ещё живого процесса (или hwnd его основного окна)?<br />У меня никак не получилось: подход №1 в этом случае не применим, а в подходе №2 требуется uID.<br />Вот у всех AutoHotkey скриптов uID у иконок в трее статичный и равен 1028 (AHK_NOTIFYICON), а вот у других иконок uID, получается надо вычитывать из памяти.<br />Другого способа нет?</p>]]></description>
			<author><![CDATA[null@example.com (Drugoy)]]></author>
			<pubDate>Mon, 12 Sep 2016 20:06:39 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107581#p107581</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107548#p107548</link>
			<description><![CDATA[<p>В DllCall типы данных можно указывать без кавычкек, это ошибкой не является, зато сокращает место.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Mon, 12 Sep 2016 15:30:49 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107548#p107548</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107544#p107544</link>
			<description><![CDATA[<div class="fancy_spoiler_switcher"><div class="fancy_spoiler_switcher_header" data-lang-open="открыть спойлер" data-lang-close="скрыть спойлер"><strong>+</strong>&nbsp;открыть спойлер</div><div class="fancy_spoiler"><p>Выделить тему в отдельную попросил я, т.к. мне потребовалось разобраться в работе с иконками в трее, и то ли из-за плохой работы поисковика, то ли из-за того, что обсуждение было в другой теме - я с трудом нашёл это обсуждение.<br />В теме есть обсуждение и разные коды, часть из которых - являются просто итерациями одного и того же кода, в чём сходу без какого-то резюмирования - не разобраться.<br />Итак, в этом посте я попробую резюмировать все подходы (пост будет обновляться, да и я пока не до конца разобрался и потому мне потребуется ваша помощь).</p></div></div><p><strong>РЕЗЮМЕ ПОСТА</strong><br />Задача: очистить трей (системный лоток, system tray) от иконок закрытых приложений (осиротевшие иконки, tray orphans).</p><p>У задачи есть несколько решений и они базируются на разных подходах.</p><p>Подход 1 - базируется на том, что осиротевшие иконки вычищаются из трэя сами (системой), если навести на них курсором. Но водить курсором (MouseMove) не обязательно: достаточно просто отправлять трею соответствующие сообщения.<br /></p><div class="codebox"><pre><code>WM_MOUSEMOVE := 0x200	; Сообщение для отправки.
coords := (y &lt;&lt; 16) + x		; &#039;x&#039; и &#039;y&#039; координаты преобразовываются в единое число.
PostMessage, WM_MOUSEMOVE, 0, coords, controlNN, wintitle</code></pre></div><p>Тут сразу стоит отметить, что controlNN похоже зависит от версии ОС: на Windows10, судя по <a href="https://autohotkey.com/boards/viewtopic.php?p=95533#p95533">чужим сообщениям</a>,&nbsp; оно принимает значение &quot;ToolbarWindow322&quot;, в то время как на других версиях -&nbsp; &quot;ToolbarWindow321&quot;.<br />wintitle же тоже может принимать 2 значения: &quot;ahk_class Shell_TrayWnd&quot; и &quot;ahk_class NotifyIconOverflowWindow&quot;: первое - это обычная область трея, а второе - область куда ОСью по-умолчанию автоматически скрываются неиспользуемые иконки из трея (это поведение отключаемо).</p><p>Подход 2 - базируется на цепочке из 3 действий:<br />1. сначала собирается информация о каждой иконке в трее;<br />2. затем циклически для каждой иконки выполняется проверка &quot;а жив ли процесс, связанный с hwnd этой иконки?&quot;;<br />3. если на шаге 2 ответ негативный, то иконка убирается одним из двух способов:<br />А. Надёжный, полагающийся на hWnd и uID иконки (первый из них практически гарантирует уникальность):<br /></p><div class="codebox"><pre><code>NIM_DELETE := 0x2	; выбираем сообщение, означающее удаление иконки.
; NID - структура, которая формируется несколькими NumPut&#039;ами и содержит hWnd и uID иконки. Более подробно здесь: https://msdn.microsoft.com/en-us/library/windows/desktop/bb773352
DllCall(&quot;shell32\Shell_NotifyIcon&quot;, &quot;UInt&quot;, NIM_DELETE, &quot;Ptr&quot;, &amp;NID)</code></pre></div><p>Б. Менее надёжный, просто по индексу иконки (соответственно, следует учитывать сдвиг после каждой исчезнувшей иконки):<br /></p><div class="codebox"><pre><code>; idx - индекс иконки в трее.
WM_SETTINGCHANGE := 0x1A, TB_DELETEBUTTON := 0x416
SendMessage, TB_DELETEBUTTON, idx, 0, controlNN, wintitle		; TB_DELETEBUTTON - https://msdn.microsoft.com/en-us/library/windows/desktop/bb787309(v=vs.85).aspx
SendMessage, WM_SETTINGCHANGE, 0, 0,, wintitle</code></pre></div><p><a href="https://autohotkey.com/boards/viewtopic.php?p=92861#p92861">Хороший пример реализации подхода №2-А</a>, основывающийся на использовании 3-ёх функций из <a href="https://autohotkey.com/boards/viewtopic.php?p=9186#p9186">библиотеки TrayIcon Library</a> от FanaticGuru (которая в свою очередь основывается на трудах других людей).</p><p>Вот и всё, что есть, а остальное - либо повторения, либо вариации реализации вышеописанных методов, например:<br />- представленный в этой теме <a href="http://forum.script-coding.com/viewtopic.php?pid=107514#p107514">скрипт DeleteDummyIcons()</a> от <strong>teadrinker</strong>&#039;а - является ещё одной реализацией подхода №2-А, но отличается (от реализации упомянутой выше) иной организацией кода по сбору информации обо всех иконках в трее.</p><p>p.s.: шаг 3 из подхода 2-А - позволяет удалять любые иконки в трее, не обязательно tray orphans.</p>]]></description>
			<author><![CDATA[null@example.com (Drugoy)]]></author>
			<pubDate>Mon, 12 Sep 2016 14:28:12 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107544#p107544</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107535#p107535</link>
			<description><![CDATA[<p>Вынес в отдельную тему.</p>]]></description>
			<author><![CDATA[null@example.com (ypppu)]]></author>
			<pubDate>Mon, 12 Sep 2016 06:10:46 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107535#p107535</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107509#p107509</link>
			<description><![CDATA[<p>По координатам попробовал, тогда меню появляется внизу экрана, и тоже не со всеми иконками работает:<br /></p><div class="codebox"><pre><code>idx := 2

#NoTrayIcon
SizeOfRect := 16
WM_USER := 0x400
TB_GETITEMRECT := WM_USER + 29

DetectHiddenWindows, On
ControlGet, hWnd, hwnd,, ToolbarWindow321, ahk_class Shell_TrayWnd
WinExist(&quot;ahk_id&quot; hWnd)
WinGet, PID, PID

RemoteBuff := New RemoteBuffer(PID, SizeOfRect)

SendMessage, TB_GETITEMRECT, idx - 1, RemoteBuff.ptr
pRect := RemoteBuff.Read(SizeOfRect)
x := NumGet(pRect + 0, &quot;UInt&quot;), y := NumGet(pRect + 4, &quot;UInt&quot;)   ; координаты относительно окна ToolbarWindow321

ControlFocus
ControlClick, % &quot;x&quot; x + 5 &quot; y&quot; y + 5,,, R,, Pos D
Sleep, 100
ControlClick, % &quot;x&quot; x + 5 &quot; y&quot; y + 5,,, R,, Pos U
Return

Class RemoteBuffer
{
   __New(PID, size)
   {
      static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20, PROCESS_VM_READ := 0x10
         , MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x4
         
      if !(this.hProc := DllCall(&quot;OpenProcess&quot;, UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, Int, 0, UInt, PID, Ptr))
         Return
      
      if !(this.ptr := DllCall(&quot;VirtualAllocEx&quot;, UInt, this.hProc, UInt, 0, UInt, size, UInt, MEM_COMMIT, UInt, PAGE_READWRITE, Ptr))
         Return, &quot;&quot;, DllCall(&quot;CloseHandle&quot;, Ptr, this.hProc)
   }
   
   __Delete()
   {
      DllCall(&quot;VirtualFreeEx&quot;, Ptr, this.hProc, Ptr, this.ptr, UInt, 0, UInt, MEM_RELEASE := 0x8000)
      DllCall(&quot;CloseHandle&quot;, Ptr, this.hProc)
   }
   
   Read(size, offset = 0)
   {
      static LocalBuff
      VarSetCapacity(LocalBuff, size, 0)
      if !DllCall(&quot;ReadProcessMemory&quot;, Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, &amp;LocalBuff, UInt, size, UInt, 0)
         Return, 0, DllCall(&quot;MessageBox&quot;, Ptr, 0, Str, &quot;Не удалось прочитать данные`nОшибка &quot; A_LastError, Str, &quot;&quot;, UInt, 0)
      
      VarSetCapacity(LocalBuff, -1)
      Return &amp;LocalBuff
   }
   
   Write(pLocalBuff, size, offset = 0)
   {
      res := DllCall(&quot;WriteProcessMemory&quot;, Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, pLocalBuff, UInt, size, UInt, 0)
      Return res ? res : 0, (!res) ? DllCall(&quot;MessageBox&quot;, Ptr, 0, Str, &quot;Не удалось записать данные`nОшибка &quot; A_LastError, Str, &quot;&quot;, UInt, 0)
   }
}</code></pre></div><p>Как получить хэндл, не знаю.<br />Мой способ отличается универсальностью, там только под 32 бита.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Thu, 29 May 2014 13:59:43 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107509#p107509</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107508#p107508</link>
			<description><![CDATA[<p>Так значит лучше клик правой кнопкой... Кстати как получить координаты. <br />И можно ли получить хэндл меню иконки, чтобы показать его в нужных координатах <a href="http://forum.script-coding.com/viewtopic.php?pid=82741#p82741">этим способом</a>.</p><p>И теоретический вопрос, в чём всё таки принципиальное отличие твоего метода от этого <a href="http://www.autohotkey.com/board/topic/80624-notrayorphans/">http://www.autohotkey.com/board/topic/8 … ayorphans/</a>.</p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Thu, 29 May 2014 07:31:48 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107508#p107508</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107507#p107507</link>
			<description><![CDATA[<p>А нет, вспомнил, уже писал такое. Нужно считать</p><p>IntPtr hwnd;<br />uint uID;<br />uint uCallbackMessage;</p><p>из TRAYDATA и послать в окно, связанное с иконкой, соответствующее сообщение. Так можно вызвать контекстное меню первой по порядку иконки в трее:<br /></p><div class="codebox"><pre><code>#NoTrayIcon
idx := 1
PostMessage2TrayIcon(idx, &quot;Tray&quot;, WM_RBUTTONDOWN := 0x204, WM_RBUTTONUP := 0x205)
Return

PostMessage2TrayIcon(idx, TrayOrOverflow, messages*)
{
   static WM_USER := 0x400, TB_BUTTONCOUNT := WM_USER + 24, TB_GETBUTTON := WM_USER + 23
      , PtrSize := A_Is64bitOS ? 8 : 4, SizeOfTBBUTTON := 8 + PtrSize*3, SizeOfTRAYDATA := 16 + PtrSize*2

   DHW_Prev := A_DetectHiddenWindows
   DetectHiddenWindows, On
   ControlGet, hWnd, hwnd,, ToolbarWindow321, % &quot;ahk_class &quot; . (TrayOrOverflow = &quot;Tray&quot; ? &quot;Shell_TrayWnd&quot; : &quot;NotifyIconOverflowWindow&quot;)
   WinExist(&quot;ahk_id&quot; hWnd)
   WinGet, PID, PID

   if !IsObject(RemoteBuff := New RemoteBuffer(PID, SizeOfTRAYDATA)) {
      DetectHiddenWindows, %DHW_Prev%
      Return, 0, DllCall(&quot;MessageBox&quot;, Ptr, 0, Str, &quot;Не удалось создать удалённый буфер`nОшибка &quot; A_LastError, Str, &quot;&quot;, UInt, 0)
   }
 
   SendMessage, TB_GETBUTTON, idx - 1, RemoteBuff.ptr
   if ! ( pTBBUTTON := RemoteBuff.Read(SizeOfTBBUTTON) )
      || !pTRAYDATA := RemoteBuff.Read(SizeOfTRAYDATA, NumGet(pTBBUTTON + 8 + PtrSize) - RemoteBuff.ptr) {
      DetectHiddenWindows, %DHW_Prev%
      Return
   }

   WinExist(&quot;ahk_id&quot; NumGet(pTRAYDATA+0))
   uID := NumGet(pTRAYDATA + PtrSize, &quot;UInt&quot;)
   uCallbackMessage := NumGet(pTRAYDATA + PtrSize + 4, &quot;UInt&quot;)

   for i, message in messages
      PostMessage, uCallbackMessage, uID, message
   
   DetectHiddenWindows, %DHW_Prev%
}

Class RemoteBuffer
{
   __New(PID, size)
   {
      static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20, PROCESS_VM_READ := 0x10
         , MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x4
         
      if !(this.hProc := DllCall(&quot;OpenProcess&quot;, UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, Int, 0, UInt, PID, Ptr))
         Return
      
      if !(this.ptr := DllCall(&quot;VirtualAllocEx&quot;, UInt, this.hProc, UInt, 0, UInt, size, UInt, MEM_COMMIT, UInt, PAGE_READWRITE, Ptr))
         Return, &quot;&quot;, DllCall(&quot;CloseHandle&quot;, Ptr, this.hProc)
   }
   
   __Delete()
   {
      DllCall(&quot;VirtualFreeEx&quot;, Ptr, this.hProc, Ptr, this.ptr, UInt, 0, UInt, MEM_RELEASE := 0x8000)
      DllCall(&quot;CloseHandle&quot;, Ptr, this.hProc)
   }
   
   Read(size, offset = 0)
   {
      static LocalBuff
      VarSetCapacity(LocalBuff, size, 0)
      if !DllCall(&quot;ReadProcessMemory&quot;, Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, &amp;LocalBuff, UInt, size, UInt, 0)
         Return, 0, DllCall(&quot;MessageBox&quot;, Ptr, 0, Str, &quot;Не удалось прочитать данные`nОшибка &quot; A_LastError, Str, &quot;&quot;, UInt, 0)
      
      VarSetCapacity(LocalBuff, -1)
      Return &amp;LocalBuff
   }
   
   Write(pLocalBuff, size, offset = 0)
   {
      res := DllCall(&quot;WriteProcessMemory&quot;, Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, pLocalBuff, UInt, size, UInt, 0)
      Return res ? res : 0, (!res) ? DllCall(&quot;MessageBox&quot;, Ptr, 0, Str, &quot;Не удалось записать данные`nОшибка &quot; A_LastError, Str, &quot;&quot;, UInt, 0)
   }
}</code></pre></div><p>Правда, показано оно будет в районе курсора мыши. Работает не со всеми иконками.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Wed, 28 May 2014 21:41:38 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107507#p107507</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107506#p107506</link>
			<description><![CDATA[<p>Проще всего вычислить её координаты и послать туда клик правой кнопкой. Может, ещё поумнее как-то можно.<br />Координаты вычисляются сообщением TB_GETITEMRECT. Затем его результат нужно считать из адресного пространства проводника, аналогично предыдущим примерам.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Wed, 28 May 2014 21:15:16 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107506#p107506</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107505#p107505</link>
			<description><![CDATA[<p>Ну хорошо. Например надо вызвать контекстное меню определённой иконки, как это организовать?</p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Wed, 28 May 2014 21:08:39 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107505#p107505</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107504#p107504</link>
			<description><![CDATA[<p>Сократил там нем немного, можно одним массивом <em>Dummy</em> обойтись. Что касается Коллекции, то мне кажется, тут нужно шире посмотреть на этот вопрос, там ведь главная фишка кода в том, что он получает информацию об иконках трея для всех процессов, а использовать эту информацию для удаления пустых иконок — лишь частный случай.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Wed, 28 May 2014 18:29:46 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107504#p107504</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107503#p107503</link>
			<description><![CDATA[<p>В этот раз запускал с закрытыми глазами, но с верой в тебя <img src="//forum.script-coding.com/img/smilies/wink.png" width="15" height="15" /></p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Wed, 28 May 2014 17:42:42 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107503#p107503</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107502#p107502</link>
			<description><![CDATA[<p>А я уж подумал, долго не отвечает, наверно систему к чертям снесло. <img src="//forum.script-coding.com/img/smilies/lol.png" width="15" height="15" /></p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Wed, 28 May 2014 17:37:37 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107502#p107502</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107501#p107501</link>
			<description><![CDATA[<p>Ага, этот работает нормально.</p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Wed, 28 May 2014 17:35:25 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107501#p107501</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Очистить трей от иконок закрытых приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=107500#p107500</link>
			<description><![CDATA[<p>У меня на обеих версиях так работает:<br /></p><div class="codebox"><pre><code>#NoTrayIcon
DeleteDummyIcons()

DeleteDummyIcons()
{
/*
Недокументированная структура TRAYDATA
typedef TRAYDATA
{
IntPtr hwnd;
uint uID;
uint uCallbackMessage;
uint Reserved;
uint Reserved2;
IntPtr hIcon;
}
*/
   PtrSize := A_Is64bitOS ? 8 : 4
   WM_USER := 0x400
   TB_BUTTONCOUNT := WM_USER + 24
   TB_GETBUTTON := WM_USER + 23
   SizeOfTBBUTTON := 8 + PtrSize*3
   SizeOfTRAYDATA := 16 + PtrSize*2
   
   DHW_Prev := A_DetectHiddenWindows
   DetectHiddenWindows, On
   ControlGet, hTray, hwnd,, ToolbarWindow321, ahk_class Shell_TrayWnd
   ControlGet, hOverflow, hwnd,, ToolbarWindow321, ahk_class NotifyIconOverflowWindow
   WinGet, PID, PID, ahk_id %hTray%

   ; создаём буфер в адресном пространстве проводника для чтения данных
   RemoteBuff := New RemoteBuffer(PID, SizeOfTRAYDATA)
   Dummy := []
   Loop 2
   {
      hwnd := A_Index = 1 ? hTray : hOverflow
      SendMessage, TB_BUTTONCOUNT,,,, ahk_id %hwnd%
      Loop % ErrorLevel
      {
         SendMessage, TB_GETBUTTON, A_Index - 1, RemoteBuff.ptr,, ahk_id %hwnd%
         ; получаем структуру TBBUTTON, в ней по смещению 8 + PtrSize адрес структуры TRAYDATA в адресном пространстве проводника
         pTBBUTTON := RemoteBuff.Read(SizeOfTBBUTTON)
         
         ; получаем структуру TRAYDATA
         pTRAYDATA := RemoteBuff.Read(SizeOfTRAYDATA, NumGet(pTBBUTTON+0, 8 + PtrSize) - RemoteBuff.ptr)
         hWndIcon := NumGet(pTRAYDATA+0), uID := NumGet(pTRAYDATA + PtrSize, &quot;UInt&quot;)
         
         ; если окна не существует (процесс не существует) — заносим в массив
         if !WinExist(&quot;ahk_id&quot; hWndIcon)
            Dummy.Insert({hWnd: hWndIcon, uID: uID})
      }
   }
   DetectHiddenWindows, %DHW_Prev%
   for k, v in Dummy
      RemoveTrayIcon(v.hWnd, v.uID)
}

RemoveTrayIcon(hWnd, uID)
{
   VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize = 8 ? 848 : A_IsUnicode? 828 : 444, 0)
   NumPut(size, NOTIFYICONDATA, &quot;UInt&quot;)
   NumPut(hWnd, NOTIFYICONDATA, A_PtrSize)
   NumPut(uID, NOTIFYICONDATA, 2*A_PtrSize)
   DllCall(&quot;shell32\Shell_NotifyIcon&quot;, &quot;UInt&quot;, NIM_DELETE := 2, Ptr, &amp;NOTIFYICONDATA)
   Return
}

Class RemoteBuffer
{
   __New(PID, size)
   {
      static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20, PROCESS_VM_READ := 0x10
         , MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x4
      
      if !(this.hProc := DllCall(&quot;OpenProcess&quot;, UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, Int, 0, UInt, PID, Ptr))
         Return
      
      if !(this.ptr := DllCall(&quot;VirtualAllocEx&quot;, UInt, this.hProc, UInt, 0, UInt, size, UInt, MEM_COMMIT, UInt, PAGE_READWRITE, Ptr))
         Return, &quot;&quot;, DllCall(&quot;CloseHandle&quot;, Ptr, this.hProc)
   }
   
   __Delete()
   {
      DllCall(&quot;VirtualFreeEx&quot;, Ptr, this.hProc, Ptr, this.ptr, UInt, 0, UInt, MEM_RELEASE := 0x8000)
      DllCall(&quot;CloseHandle&quot;, Ptr, this.hProc)
   }
   
   Read(size, offset = 0)
   {
      static LocalBuff
      VarSetCapacity(LocalBuff, size, 0)
      DllCall(&quot;ReadProcessMemory&quot;, Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, &amp;LocalBuff, UInt, size, UInt, 0)
      VarSetCapacity(LocalBuff, -1)
      Return &amp;LocalBuff
   }
   
   Write(pLocalBuff, size, offset = 0)
   {
      return DllCall(&quot;WriteProcessMemory&quot;, Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, pLocalBuff, UInt, size, UInt, 0)
   }
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Wed, 28 May 2014 15:50:24 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=107500#p107500</guid>
		</item>
	</channel>
</rss>
