<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AHK: Заголовки колонок ListView из другого приложения]]></title>
		<link>http://forum.script-coding.com/viewtopic.php?id=3440</link>
		<atom:link href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=3440&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AHK: Заголовки колонок ListView из другого приложения».]]></description>
		<lastBuildDate>Thu, 23 Jul 2009 05:04:41 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[AHK: Заголовки колонок ListView из другого приложения]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=26240#p26240</link>
			<description><![CDATA[<p>Заголовочный контрол в ListView — это окно класса SysHeader32. Для получения информации о заголовках он поддерживает сообщение HDM_GETITEM. Однако в этом сообщении требуется указать адрес, куда он должен поместить запрошенную информацию, и так как контрол находится в другом процессе по отношению к скрипту, подсовывать ему адреса переменных скрипта бессмысленно. Подробнее см. в теме <a href="http://www.forum.script-coding.com/viewtopic.php?id=2734">AHK: Доступ к памяти других процессов</a>.</p><p>Пример ниже читает текст заголовков на вкладке &quot;Процессы&quot; в окне Диспетчера задач. С помощью API-функции VirtualAllocEx выделяется память в адресном пространстве процесса под структуру HDITEM и строку заголовка. Потом строка читается оттуда через ReadProcessMemory. HDITEM сначала создаётся в самом скрипте, поскольку нужно заполнить некоторые её поля и я счёл, что проще сделать это в скрипте и потом скопировать структуру в память процесса одним вызовом WriteProcessMemory, нежели чем писать туда каждое поле по-отдельности.</p><div class="codebox"><pre><code>If not WinExist(&quot;Диспетчер задач Windows&quot;) {
  Run, Taskmgr.exe
  WinWait, Диспетчер задач Windows
}

; Переключиться на вкладку &quot;Процессы&quot; (взято из справки).
SendMessage, 0x1330, 1,, SysTabControl321  ; 0x1330 is TCM_SETCURFOCUS.
Sleep, 0
SendMessage, 0x130C, 1,, SysTabControl321  ; 0x130C is TCM_SETCURSEL.

ControlGet, hwndHeader, Hwnd,, SysHeader321   ; Хэндл заголовочного контрола.

Headers := HeaderGetText(hwndHeader)  ; Список заголовков.

MsgBox, % Headers


; ======== Функция, возвращающая список заголовков =======

HeaderGetText(hWnd) 
{
  MaxName := 100     ; Максимальная длина заголовка.
  Delimiter := &quot;`n&quot;  ; Разделитель заголовков в списке.

  PROCESS_VM_OPERATION := 0x8, PROCESS_VM_READ := 0x10
  PROCESS_VM_WRITE := 0x20,    MEM_COMMIT := 0x1000
  MEM_DECOMMIT := 0x4000,      PAGE_READWRITE = 0x4
  HDI_TEXT := 0x2,             HDM_GETITEMCOUNT := 0x1200
  HDM_GETITEMA := 0x1203

  VarSetCapacity(Buf, MaxName, 0)  ; Буфер под заголовок.
  VarSetCapacity(hdi, 48, 0)       ; Структура HDITEM, её размер 48 байт.
                                   ; В неё будет скидываться информация о каждом
                                   ; заголовке в ответ на сообщение HDM_GETITEM.

  ; PID процесса, создавшего заголовочный контрол.
  DllCall(&quot;GetWindowThreadProcessId&quot;, &quot;uint&quot;,   hWnd
                                    , &quot;uint *&quot;, PID)

  hProcess := DllCall(&quot;OpenProcess&quot;, &quot;uint&quot;, PROCESS_VM_READ
                                           | PROCESS_VM_WRITE
                                           | PROCESS_VM_OPERATION
                                   , &quot;int&quot;, FALSE
                                   , &quot;uint&quot;, PID)
  If (hProcess = 0) {
    MsgBox, Не удалось открыть процесс.
    Return
  }

  ; Выделение памяти в адресном пространстве процесса
  ; под структуру HDITEM и строку заголовка.
  phdi := DllCall(&quot;VirtualAllocEx&quot;, &quot;uint&quot;, hProcess
                                  , &quot;uint&quot;, 0
                                  , &quot;uint&quot;, MaxName + 48
                                  , &quot;uint&quot;, MEM_COMMIT
                                  , &quot;uint&quot;, PAGE_READWRITE)
  If (phdi = 0) {
    MsgBox, Ошибка выделения памяти в процессе.
    Goto, Close
  }

  ; Запись нужных значений в структуру.
  NumPut(HDI_TEXT, hdi), NumPut(phdi+48, hdi, 8), NumPut(MaxName, hdi, 16)

  ; Структура копируется в память процесса.
  Ret := DllCall(&quot;WriteProcessMemory&quot;, &quot;uint&quot;, hProcess
                                     , &quot;uint&quot;, phdi
                                     , &quot;uint&quot;, &amp;hdi
                                     , &quot;uint&quot;, 48
                                     , &quot;uint&quot;, 0)
  If (Ret = 0) {
    MsgBox, Ошибка записи в память процесса.
    Goto, Free
  }

  ; Запрос количества заголовков.
  Count := DllCall(&quot;SendMessageA&quot;, &quot;uint&quot;, hWnd
                                 , &quot;uint&quot;, HDM_GETITEMCOUNT
                                 , &quot;uint&quot;, 0
                                 , &quot;uint&quot;, 0)
  If (Count &lt; 0) {
    MsgBox, Ошибка определения количества заголовков.
    Goto, Free
  }

  Loop, % Count  ; Запрос информации о каждом заголовке.
  {
    DllCall(&quot;SendMessageA&quot;, &quot;uint&quot;, hWnd
                          , &quot;uint&quot;, HDM_GETITEMA
                          , &quot;uint&quot;, A_Index - 1
                          , &quot;uint&quot;, phdi)

    ; Заголовок копируется из памяти процесса в местный буфер.
    Ret := DllCall(&quot;ReadProcessMemory&quot;, &quot;uint&quot;, hProcess
                                      , &quot;uint&quot;, phdi+48
                                      , &quot;uint&quot;, &amp;Buf
                                      , &quot;uint&quot;, MaxName
                                      , &quot;uint&quot;, 0)
    If (Ret = 0) {
      MsgBox, Ошибка чтения из памяти процесса.
      Goto, Free
    }

    VarSetCapacity(Buf, -1)  ; Обновление переменной.
    Headers .= Buf . (A_Index != Count ? Delimiter : &quot;&quot;)
  }

  Free:  ; Освобождение памяти в процессе.
  DllCall(&quot;VirtualFreeEx&quot;, &quot;uint&quot;, hProcess
                         , &quot;uint&quot;, phdi
                         , &quot;uint&quot;, MaxName+48
                         , &quot;uint&quot;, MEM_DECOMMIT)

  Close:  ; Освобождение хэндла процесса.
  DllCall(&quot;CloseHandle&quot;, &quot;uint&quot;, hProcess)

  Return Headers
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (YMP)]]></author>
			<pubDate>Thu, 23 Jul 2009 05:04:41 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=26240#p26240</guid>
		</item>
	</channel>
</rss>
